default_wake_function函数功能描述:此函数是内核定义的默认的进程唤醒函数,唤醒处于等待队列中的进程,使进程由非TASK_RUNNING状态变为TASK_RUNNING状态,并获得CPU资源,被调度执行。而对于唤醒的进程的状态有一定的要求,只有进程的状态属于此函数的第二个参数所定义的状态时进程才能被唤醒。
default_wake_function文件包含
#include <linux/wait.h>
default_wake_function函数定义
在内核源码中的位置:linux-3.19.3/kernel/sched.c
函数定义格式:
int default_wake_function(wait_queue_t *wait, unsigned mode, int f lags, void*key)
default_wake_function输入参数说明
此函数的第一个输入参数是wait_queue_t类型的指针,代表等待队列中的一个元素,其定义及详细信息参考函数abort_exclusive_wait( )。
此函数的第二个参数是无符号的整型变量,代表能够被唤醒的进程的所处的状态,即只有处于此状态的进程才能够被唤醒,可能的取值为宏TASK_NORMAL和TASK_ALL,此二者的定义如下:
#define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)
#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED)
其中TASK_NORMAL代表唤醒等待队中处于可中断的等待状态的进程及处于不可中断的等待状态的进程;TASK_ALL代表唤醒处于TASK_NORMAL状态的进程及处于暂停状态和跟踪状态的进程。
此函数的第三个参数是一个整型变量,代表唤醒等待队列中进程的方式,可能的取值是0或非0,0代表非同步唤醒,非0代表同步唤醒。
此函数的第四个参数是一个void型的指针变量,代表唤醒进程时执行的函数,一般传递NULL。
default_wake_function返回参数说明
此函数的返回结果是int型的变量值,此值可能是0或1。返回0说明唤醒进程失败,此进程的状态不满足唤醒要求,即状态不属于第二个参数所定义的状态;返回1说明唤醒进程成功,使进程由非TASK_RUNNING状态转变为TASK_RUNNING状态,并获得CPU资源,将被调度执行。
default_wake_function实例解析
编写测试文件:default_wake_function.c
头文件引用及全局变量定义:
/*头文件引用*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/pid.h>
#include <linux/wait.h>
#include <linux/kthread.h>
MODULE_LICENSE("GPL");
/*全局变量定义*/
static wait_queue_head_t head; //等待队列头变量
static wait_queue_t data; //等待队列元素变量
struct task_struct * old_thread; //保存初始化进程的信息
子进程处理函数定义:
int my_function(void * argc)
{
int result=-1;
printk("in the kernel thread function! \n");
printk("the current pid is:%d\n", current->pid); //显示当前进程的PID值
printk("the state of the parent process before default_wake_function is:%ld\n", old_thread->state); //显示当前进程的父进程的状态
if(data.private! =NULL)
result=default_wake_function(&data, TASK_ALL,0, NULL);
//调用函数唤醒处于睡眠状态的进程
printk("the state of the parent process after default_wake_function is:%ld\n", old_thread->state); //显示函数调用之后父进程的状态
printk("the result of the default_wake_function is:%d\n", result);
//显示函数default_wake_function( )的返回结果
printk("out the kernel thread function\n");
return 0;
}
模块加载函数定义:
static int __init default_wake_function_init(void)
{
struct task_struct *result;
int result2=0; //局部变量定义
long result1=0;
char namefrm[] = "default_wake_function";
printk("into default_wake_function_init.\n");
old_thread = current;
result = kthread_create_on_node(my_function, NULL, -1, namefrm); //创建新进程
wake_up_process(result);
init_waitqueue_head(&head); //初始化等待队列的头元素
init_waitqueue_entry(&data, current); //用当前进程初始化等待队列元素
add_wait_queue(&head, &data); //将等待队列元素加入等待队列
result1 = schedule_timeout_uninterruptible(1000);
// 将等待队列置于睡眠状态,此睡眠状态是不可中断的
if(data.private! =NULL)
result2=default_wake_function(&data, TASK_ALL,0, NULL);
// 调用函数唤醒在等待队列中的进程
printk("the pid of new thread is :%d\n", result->pid);
//显示函数kernel_thread( )函数的返回结果
printk("the result of the schedule_timeout_uninterruptible is:%ld\n", result1);
//显示函数sleep_on_timeout( )的返回结果
printk("the result of the default_wake_function is:%d\n", result2);
//显示函数default_wake_function( )的返回结果
printk("the current pid is:%d\n", current->pid); //显示当前进程的PID值
printk("out default_wake_function_init.\n");
return 0;
}
模块退出函数定义:
static void __exit default_wake_function_exit(void)
{
printk("Goodbye default_wake_function\n");
}
模块加载、退出函数调用:
module_init(default_wake_function_init);
module_exit(default_wake_function_exit);
实例运行结果及分析:
首先编译模块,执行命令insmod default_wake_function.ko插入内核模块,然后输入命令dmesg -c查看模块插入结果,会出现如图所示的结果。
结果分析:
由上图结果可以看出子进程和父进程都执行了,并且子进程在父进程之前执行完毕。在子进程执行时父进程的状态发生了变化,state值由2变为0,状态值首先为2是因为函数schedule_timeout_uninterruptible( )执行的原因,此函数使父进程处于TASK_UNINTERRUPTIBLE状态。在子进程中调用了函数default_wake_function( ),此函数负责唤醒父进程,当函数执行之后父进程的状态变为0,即处于TASK_RUNNING状态,并且函数default_wake_function( )的返回结果是1,函数schedule_timeout_uninterruptible( )的返回结果是1000,说明父进程是被强制唤醒的而不是等待超时才被唤醒的,此二者的返回结果正好说明了是函数default_wake_function( )唤醒的父进程。在父进程中也调用了函数default_wake_function( )唤醒父进程,而此时函数的返回值为0,说明唤醒父进程失败,因为此时父进程已处于TASK_RUNNING状态,所以会唤醒失败。
进程状态说明:
对于进程能够处于的状态,在函数__wake_up( )的进程状态说明部分有详细的说明。