Linux内核的休眠与唤醒机制

在Linux内核中存在着等待队列的数据结构,该数据结构是基于双端链表实现,Linux内核通过将阻塞的进程任务添加到等待队列中,而进程任务被唤醒则是在队列轮询遍历检测是否处于就绪状态,如果是那么会等待队列中删除等待节点并通过节点上的回调函数进行通知然后加入到cpu就绪队列中等待cpu调度执行.其具体流程主要包含以下两个处理逻辑,即休眠逻辑以及唤醒逻辑.

休眠逻辑

  • linux 内核休眠逻辑核心代码
// 其中cmd = schedule(), 即一个调用schedule函数的指针
#define ___wait_event(wq_head, condition, state, exclusive, ret, cmd)
({                                      __label__ __out;                            struct wait_queue_entry __wq_entry;                 long __ret = ret;  /* explicit shadow */               // 初始化过程(内部代码这里省略,直接说明)// 1. 设置独占标志到当前节点entry// 2. 将当前任务task指向节点的private// 3. 同时为当前entry节点传递一个唤醒的回调函数autoremove_wake_function,一旦唤醒将会自动被删除init_wait_entry(&__wq_entry, exclusive ? WQ_FLAG_EXCLUSIVE : 0);   for (;;) {// 防止队列中没有entry产生不断的轮询,主要处理wait_queue与entry节点添加或者删除long __int = prepare_to_wait_event(&wq_head, &__wq_entry, state);// 事件轮询检查是否事件有被唤醒                            if (condition)                          break;                          if (___wait_is_interruptible(state) && __int) {         __ret = __int;                     goto __out;                     }                               // 调用schedule()方法                       cmd;                                }// 事件被唤醒,将当前的entry从队列中移除               finish_wait(&wq_head, &__wq_entry);
__out:  __ret;
})
  • 对此,我们可以总结如下:

    • 在linux内核中某一个进程任务task执行需要等待某个条件condition被触发执行之前,首先会在内核中创建一个等待节点entry,然后初始化entry相关属性信息,其中将进程任务存放在entry节点并同时存储一个wake_callback函数并挂起当前进程
    • 其次不断轮询检查当前进程任务task执行的condition是否满足,如果不满足则调用schedule()进入休眠状态
    • 最后如果满足condition的话,就会将entry从队列中移除,也就是说这个时候事件已经被唤醒,进程处于就绪状态

唤醒逻辑

  • linux内核的唤醒核心代码
static int __wake_up_common(struct wait_queue_head *wq_head, unsigned int mode,int nr_exclusive, int wake_flags, void *key,wait_queue_entry_t *bookmark)
{// 省略其他非核心代码...// 循环遍历整个等待队列list_for_each_entry_safe_from(curr, next, &wq_head->head, entry) {unsigned flags = curr->flags;int ret;if (flags & WQ_FLAG_BOOKMARK)continue;//调用唤醒的函数ret = curr->func(curr, mode, wake_flags, key);if (ret < 0)break;// 检查当前节点是否为独占节点,如果是,即nr_exclusive = 0退出循环遍历if (ret && (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)break;if (bookmark && (++cnt > WAITQUEUE_WALK_BREAK_CNT) &&(&next->entry != &wq_head->head)) {bookmark->flags = WQ_FLAG_BOOKMARK;list_add_tail(&bookmark->entry, &next->entry);break;}}return nr_exclusive;
}struct wait_queue_entry {unsigned int      flags;void          *private;// 这里的func就是上述休眠的时候在init_wait_entry传递autoremove_wake_functionwait_queue_func_t func;   struct list_head    entry;
};// 唤醒函数
int autoremove_wake_function(struct wait_queue_entry *wq_entry, unsigned mode, int sync, void *key)
{// 公用的唤醒函数逻辑// 内部执行try_to_wake_up, 也就是将wq_entry的private(当前进程)添加到cpu的执行队列中,让cpu能够调度task执行int ret = default_wake_function(wq_entry, mode, sync, key);// 其他为当前唤醒函数私有逻辑if (ret)list_del_init(&wq_entry->entry);return ret;
}
EXPORT_SYMBOL(autoremove_wake_function);
  • 对此,基于上述的唤醒逻辑可以总结如下:

    • 在等待队列中循环遍历所有的entry节点,并执行回调函数,直到当前entry为排他节点的时候退出循环遍历
    • 执行的回调函数中,存在私有逻辑与公用逻辑,类似模板方法设计模式
    • 对于default_wake_function的唤醒回调函数主要是将entry的进程任务task添加到cpu就绪队列中等待cpu调度执行任务tas

Linux之WakeupCallback机制相关推荐

  1. linux进程管理机制,linux进程管理,linux进程管理机制

    linux进程管理,linux进程管理机制 一.基本介绍 1.在 LINUX 中,每个执行的程序(代码)都称为一个进程.每一个进程都分配一个 ID 号 2.每一个进程,都会对应一个父进程,而这个父进程 ...

  2. Linux内核同步机制之(四):spin lock【转】

    转自:http://www.wowotech.net/kernel_synchronization/spinlock.html 一.前言 在linux kernel的实现中,经常会遇到这样的场景:共享 ...

  3. linux驱动模型开发——linux platform总线机制讲解与实例开发

    1.概述: 通常在Linux中,把SoC系统中集成的独立外设单元(如:I2C.IIS.RTC.看门狗等)都被当作平台设备来处理. 从Linux2.6起,引入了一套新的驱动管理和注册机制:Platfor ...

  4. Linux内存管理机制研究

    Linux内存管理机制研究 查看linux系统中处于free状态的内存有两个角度,一个是从内核的角度来看,一个是从应用层的角度来看的. 1.从内核的角度来看free的内存,就是内核目前可以直接分配到, ...

  5. Linux kernel 同步机制(下篇)

    之前的文章 Linux kernel同步机制 在上一部分,我们讨论了最基本常见的几类同步机制,这一部分我们将讨论相对复杂的几种同步机制,尤其是读写信号量和RCU,在操作系统内核中有相当广泛的应用. 读 ...

  6. 文件名为空linux,文件系统:隐匿在Linux背后的机制

    原标题:文件系统:隐匿在Linux背后的机制 在 Linux 中,最直观.最可见的部分就是 文件系统(file system) .下面我们就来一起探讨一下关于 Linux 中国的文件系统,系统调用以及 ...

  7. linux内存管理的主要概念是虚拟内存,有关linux内存管理机制的相关内容,linux物理内存和虚拟内存,深入了解Linux内存运行 ......

    在linux中空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然. 这是Linux内存管理的一个优秀特性,区别于Windows的内存管理. 主要特点: 无论物理内存有多大,L ...

  8. Linux保护文件实现,Linux完整性保护机制模块实现分析(1)

    原标题:Linux完整性保护机制模块实现分析(1) 2 详细分析2.1 模块功能描述 文件系统完整性模块包含四种机制:监控磁盘机制.同步机制.检查修复文件系统机制.监视文件系统机制. 1.监控磁盘机制 ...

  9. linux内存管理机制

    物理内存和虚拟内存 我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概念. 物理内存就是系统 ...

最新文章

  1. java的快速开发框架
  2. 进程间通信(4) 匿名管道
  3. Mysql 死锁过程及案例详解之显式与隐式锁Explicit Table Lock Implicit Table Lock
  4. leetcode 516. Longest Palindromic Subsequence | 516. 最长回文子序列(递归 -> 傻缓存 ->DP)
  5. 将tomcat添加到服务中
  6. [线性代数]Note 1--方程组的几何解释
  7. 10打开没有反应_118个遇水反应化学品清单及高压反应釜操作经验
  8. HTML-浮动(特点-影响-居中)-定位
  9. IDEA和VS code设置默认换行符为LF
  10. ezcad旋转轴标刻参数_激光打标机软件ezcad中菜单下的旋转角度标刻2功能介绍及其操作设置...
  11. Mac系统安装Photoshop CS6教程
  12. 2009年全国数模比赛,江苏三等奖名单
  13. Ubuntu配置locale
  14. gg修改器修改内购_【技术分享】通过GG修改器 修改王者荣耀皮肤(美化)
  15. java打印超市消费小票_Java-超市购物小票案例-详细介绍
  16. 最大奇约数(c++实现)
  17. 记录:d3实现刻度尺
  18. 用wps/excel绘制仪表盘
  19. [转]PHP编码规范
  20. 4.4V/3.85V锂电池充电器方案

热门文章

  1. 操作系统有哪些结构?
  2. MySQL 查询表的所有列名
  3. 关于event.cancelBubble
  4. 智能语音储备战升级 人工智能助产业快速增长
  5. c语言画椭圆弧插补算法实现,一种椭圆弧插补算法
  6. 安全漏洞漫谈 【http://luoluo.cnblogs.com/】
  7. Unity3D入门:摄像机与光照
  8. 错误描述:Non-terminating decimal expansion; no exact representable decimal result.
  9. android 接入阿里百川,阿里百川android 引入SDK
  10. 计算机ping 的快捷键,巧用电脑快捷键