complete_all函数功能描述:此函数主要用于唤醒等待队列中的所有的睡眠进程,并能更改等待队列被唤醒的次数,唤醒次数保存在参数的done字段中,函数设置字段done的值为在done原值的基础上加上UINT_MAX的二分之一,其中UINT_MAX内核的定义值为:#def ine UINT_MAX(~0U),值为4294967295。此函数实现唤醒等待队列中的进程通过调用函数__wake_up_locked( ),传递的参数确定唤醒的进程的状态只能是TASK_INTERRUPTIBLE状态或TASK_UNINTERRUPTIBLE状态,并且唤醒进程不是同步的,即只能按等待队列中进程的顺序一个一个地唤醒,但能唤醒等待队列中的所有睡眠状态的进程。
complete_all文件包含
complete_all函数定义
在内核源码中的位置:linux-3.19.3/kernel/sched/completion.c
函数定义格式:
complete_all输入参数说明
此函数的输入参数是struct completion结构体类型的指针,包含一个等待队列信息及等待队列的状态信息,等待队列的状态代表此等待队列是否被唤醒过,其定义及详细解释参考函数complete( )。
complete_all返回参数说明
此函数的返回结果是void类型的变量,即不返回任何类型的结果。
complete_all实例解析
编写测试文件:complete_all.c
头文件引用及全局变量定义:
子进程处理函数定义:
模块加载函数定义:
模块退出函数定义:
模块加载、退出函数调用:
实例运行结果及分析:
首先编译模块,执行命令insmod complete_all.ko插入内核模块,然后输入命令dmesg -c查看模块插入结果,会出现如图所示的结果。
结果分析:
由图上4结果可以看出子进程和父进程都已执行,并且子进程在父进程之前执行完毕。在子进程执行时父进程的状态发生了变化,state值由2变为0。状态值首先为2是因为函数schedule_timeout_uninterruptible( )执行的原因,此函数使父进程处于TASK_UNINTERRUPTIBLE状态。在子进程中,函数complete_all( )调用之前父进程的状态值为2,参数comple的done字段的值为0,函数调用之后,父进程的状态变为0,处于TASK_RUNNING状态,参数comple的done字段的值变为2147483647,说明函数complete_all( )能够改变done字段的值,并且父进程被成功唤醒。函数schedule_timeout_uninterruptible( )的返回结果是1000,说明父进程是被强制唤醒的,而不是等待超时才被唤醒的,这正好也说明了函数complete_all( )能够唤醒等待队列中的进程。
函数功能比较:
函数complete( )和函数complete_all( )都能唤醒等待队列中的睡眠进程,但在唤醒数量上可能有差别。函数complete( )调用函数__wake_up_locked( )时传递的第三个参数值是1,而函数complete_all( )函数传递的相应的参数值是0,从而保证函数complete_all( )能够唤醒等待队列中的所有的进程,而函数complete( )有可能不能。当等待队列中的第一个等待队列元素的f lags字段的值是WQ_FLAG_EXCLUSIVE时,函数complete( )将只唤醒此等待队列元素对应的进程,然后退出,而函数complete_all( )将继续唤醒其他的进程。
函数complete( )调用时,只是将参数的done字段加1,这个字段可以代表等待队列被唤醒的次数,而函数complete_all( )在调用时,将参数的done字段的值加上UINT_MAX的二分之一,此时字段done的值就不能代表等待队列被唤醒的次数了。
进程状态说明:对于进程能够处于的状态,参考函数__wake_up( )。