news 2026/8/1 12:52:17

set_current_state()和schedule()

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
set_current_state()和schedule()

schedule()set_current_state()结合使用的场景与逻辑,这是 Linux 内核中进程主动休眠的核心组合,二者配合实现了 “进程主动放弃 CPU 并进入休眠状态,等待特定事件唤醒” 的核心功能,也是驱动、内核同步机制中最常用的休眠方式。

首先明确核心逻辑:set_current_state()负责设置当前进程的休眠状态(标记进程为非运行态),schedule()负责放弃 CPU 并触发调度,二者必须配合使用,否则会出现 “伪休眠” 或进程无法被正常唤醒的问题。

两个函数的核心配合逻辑

1. 为什么必须配合使用?
  • 单独调用schedule():进程只是暂时让出 CPU,仍处于TASK_RUNNING状态,会被pick_next_task()重新挑选,很快又会获得 CPU 执行权,无法实现 “长期休眠等待事件”。
  • 单独调用set_current_state():仅修改了进程状态,进程仍持有 CPU 执行权,不会主动放弃,直到时间片耗尽被抢占,且休眠状态无法生效。
  • 配合使用:set_current_state()先将进程标记为休眠状态(非TASK_RUNNING),再调用schedule()放弃 CPU 并触发调度,此时进程会被从运行队列中移除,不再被调度器挑选,直到被wake_up_process()等函数唤醒并恢复为TASK_RUNNING状态。
2. 核心配合流程(主动休眠的标准步骤)
  1. 前置准备:确保进程运行在进程上下文,且未持有自旋锁(自旋锁不允许休眠)。
  2. 设置休眠状态:调用set_current_state(),将当前进程状态设为TASK_INTERRUPTIBLE(可中断休眠,优先选择)或TASK_UNINTERRUPTIBLE(不可中断休眠,慎用)。
  3. 检查唤醒条件:再次检查目标事件是否已就绪(防止 “惊群效应” 或唤醒信号丢失),若已就绪,重置进程状态为TASK_RUNNING,无需休眠。
  4. 触发调度放弃 CPU:调用schedule(),触发调度并放弃 CPU,进程进入休眠状态,被从运行队列中移除。
  5. 休眠唤醒后清理:进程被唤醒后,首先重置进程状态为TASK_RUNNING,然后处理唤醒后的业务逻辑(如读取数据、释放资源)。
  6. 异常处理:若为可中断休眠,检查是否被信号中断,返回对应错误码。

set_current_state()函数

这是一个内核宏(封装了对当前进程task_struct的状态修改),核心作用是修改当前进程的state成员变量

函数原型(Linux 5.10)

#define set_current_state(state_value) \ do { \ current->state = (state_value); \ } while (0)
  • 常用参数(休眠状态)
    • TASK_INTERRUPTIBLE:可中断休眠,优先选择。进程会休眠等待事件,同时响应信号(如kill命令),被信号唤醒后会返回-ERESTARTSYS错误码,符合用户态进程使用习惯。
    • TASK_UNINTERRUPTIBLE:不可中断休眠。进程仅会被硬件事件 / 内核主动唤醒,忽略所有信号,无法被kill杀死,可能导致进程 “僵死”,仅用于驱动中必须等待硬件操作完成的场景(如磁盘 IO 完成)。
    • 禁止使用TASK_RUNNING:该宏用于设置休眠状态,设置为TASK_RUNNING无实际意义,应直接修改current->state或调用wake_up_process()

核心注意点:

  • 该宏仅修改状态,不做其他操作(如不将进程从运行队列移除,不放弃 CPU)。
  • 调用后必须尽快调用schedule(),否则进程仍持有 CPU,休眠状态无法生效。
  • 唤醒后必须手动重置进程状态为TASK_RUNNING,否则进程下次调度时会被误认为仍处于休眠状态,无法被正常挑选。

schedule()函数的配合行为

schedule()检测到当前进程状态为非TASK_RUNNING时,会执行额外逻辑:

  1. __schedule()中,调用dequeue_task()将当前进程从运行队列中移除。
  2. 标记进程的on_rq0,表示进程不在运行队列中。
  3. 挑选下一个进程并完成上下文切换,当前进程进入休眠,暂停执行。
  4. 当进程被唤醒并重新调度执行时,从schedule()返回,继续执行后续代码。

wait_event()系列宏的关联

wait_event()系列宏(驱动首选),内部就是封装了set_current_state()schedule(),二者是 “底层实现” 与 “上层封装” 的关系。

wait_event_interruptible(wq, condition)为例,其核心内部逻辑简化如下:

#define wait_event_interruptible(wq, condition) \ ({ \ int __ret = 0; \ if (!(condition)) { \ // 1. 设置可中断休眠状态(对应 set_current_state()) set_current_state(TASK_INTERRUPTIBLE); \ // 2. 循环检查条件,避免惊群效应 while (!(condition)) { \ // 3. 调用 schedule() 放弃 CPU schedule(); \ // 4. 检查信号中断 if (signal_pending(current)) { \ __ret = -ERESTARTSYS; \ break; \ } \ // 5. 重新设置休眠状态(防止调度过程中状态被修改) set_current_state(TASK_INTERRUPTIBLE); \ } \ // 6. 重置进程状态为运行态 set_current_state(TASK_RUNNING); \ } \ __ret; \ })

可以看到,wait_event()系列宏只是在set_current_state()schedule()的基础上,增加了循环检查条件、自动状态重置、封装信号处理等逻辑,让使用更安全、简洁,因此驱动中优先使用wait_event()而非直接调用二者。

常见问题与避坑指南

  1. 忘记重置进程状态:休眠唤醒后未调用set_current_state(TASK_RUNNING),导致进程下次被调度时,仍被认为是休眠状态,无法被正常挑选,出现 “进程消失” 或 “僵死”。
  2. 使用不可中断休眠:滥用TASK_UNINTERRUPTIBLE,导致进程无法被信号杀死,出现 “ps查看进程存在,但无法kill” 的情况,仅在必须等待硬件操作完成时使用。
  3. 在中断上下文调用set_current_state()schedule()仅能在进程上下文调用,中断上下文中调用会导致栈混乱、系统崩溃。
  4. 持有自旋锁时休眠:持有spin_lock()时调用二者,会导致死锁(自旋锁要求进程不能休眠、不能切换),休眠前必须释放所有自旋锁。
  5. 未处理惊群效应:未二次检查条件直接休眠,导致多个进程被同时唤醒,但只有一个进程能处理数据,其他进程白唤醒,增加系统开销。

总结

  1. set_current_state()+schedule()是 Linux 内核进程主动休眠的核心底层组合,前者设置休眠状态,后者放弃 CPU 触发调度。
  2. 标准使用流程为 “设置休眠状态 → 检查条件 → 调用schedule()→ 唤醒后重置运行状态 → 处理异常”,必须严格遵循以避免问题。
  3. 二者的上层封装是wait_event()系列宏,驱动中优先使用封装宏,更安全、简洁,底层内核开发可直接使用二者。
  4. 核心禁忌:中断上下文、持有自旋锁时不可使用,可中断休眠必须处理信号中断,唤醒后必须重置进程状态为TASK_RUNNING
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/31 10:18:39

詹姆斯 — 朗格情绪说

詹姆斯 — 朗格情绪说 詹姆斯 — 朗格情绪说是情绪心理学中经典的情绪外周理论,由美国心理学家威廉・詹姆斯、丹麦生理学家卡尔・朗格于 19 世纪末各自独立提出,二人理论核心一致,故合称此说,也是心理分析批评中解读文本人物情绪…

作者头像 李华
网站建设 2026/7/31 2:58:21

意义互联工程:构建生命与非生命的跨存在对话系统

意义互联工程:构建生命与非生命的跨存在对话系统 开篇:从意义的丰盈走向意义的交响 当意义的丰盈成为宇宙的基本事实,文明的下一步便清晰浮现:我们不仅要认识丰盈,更要学会在丰盈中导航、翻译与合奏。 “余行”是意义…

作者头像 李华
网站建设 2026/7/31 11:19:51

【小程序毕设全套源码+文档】基于微信小程序的小餐桌管理系统设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/7/31 5:44:34

【小程序毕设全套源码+文档】基于微信小程序的投票系统设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

作者头像 李华
网站建设 2026/7/31 3:47:17

python基于微信小程序 宠物爱心领养回访疫苗系统设计与实现

文章目录 摘要内容技术栈创新点 系统设计与实现的思路主要技术与实现手段源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式! 摘要内容 该系统基于Python后端与微信小程序前端,设计并实现了一个宠物爱心领养、回访及疫苗管理的综…

作者头像 李华