Linux内核API autoremove_wake_function

autoremove_wake_function函数功能描述:函数在实现过程中,调用了函数default_wake_function( ),完成唤醒此等待队列中的某一进程;如果唤醒进程成功,则调用函数list_del_init( ),将此进程从等待队列中删除,否则不进行其他操作,函数执行结束,返回结果。

autoremove_wake_function文件包含

#include <linux/wait.h>

autoremove_wake_function函数定义

在内核源码中的位置:linux-3.19.3/kernel/sched/wait.c

函数定义格式:

int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)

autoremove_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。

autoremove_wake_function返回参数说明

此函数的返回结果是int型的变量值,此值可能为0或1。返回0说明唤醒进程失败,并且进程没有从等待队列中删除,说明此进程的状态不满足唤醒要求,即状态不属于第二个参数所定义的状态;返回1说明唤醒进程成功,使进程由非TASK_RUNNING状态转变为TASK_RUNNING状态,并获得CPU资源,将被调度执行,并且成功从等待队列中删除。

autoremove_wake_function实例解析

编写测试文件:autoremove_wake_function.c

头文件引用及全局变量定义:

/*头文件引用*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/list.h>
#include <linux/wait.h>
#include <linux/kthread.h>
MODULE_LICENSE("GPL");
/*全局变量定义*/
wait_queue_head_t head;   //等待队列头元素
wait_queue_t data;        //等待队列元素

子进程处理函数定义:

int my_function(void * argc)
{
    int   wait_queue_num=0, return_data;
    wait_queue_t *curr, *next;
    printk("in the kernel thread function! \n");
    list_for_each_entry_safe(curr, next, &(head.task_list), task_list)
                          // 扫描等待队列,显示等待队列中的进程的PID值及进程所处的状态
    {
        wait_queue_num++; // 记录当前等待队列中的进程的数
        printk("the pid value of the current data of the waitqueue is:%d\n", ((struct task_struct *)(curr->private))->pid);   //显示进程的PID值
        printk("the state of the current data of the waitqueue is:%ld\n", ((struct task_struct *)(curr->private))->state); //显示进程的状态
    }
    printk("the value of the wait_queue_num is :%d\n", wait_queue_num);
                          // 输出等待队列中的进程数
    return_data=autoremove_wake_function(&data, TASK_NORMAL,1, NULL);
                          // 调用函数将父进程从等待队列中删除
    wait_queue_num=0;
    list_for_each_entry_safe(curr, next, &(head.task_list), task_list)
                          // 显示函数调用之后等待队列中进程的信息
    {
        wait_queue_num++;
        printk("the pid value of the current data of the waitqueue is:%d\n", ((struct task_struct *)(curr->private))->pid);
        printk("the state of the current data of the waitqueue is:%ld\n", ((struct task_struct *)(curr->private))->state);
    }
    printk("the value of the wait_queue_num is :%d\n", wait_queue_num);
                          // 显示函数调用之后等待队列中的元素个数
    printk("the return_data of the autoremove_wake_function is :%d\n", return_data);
                          //显示autoremove_wake_function( )函数的返回结果
    printk("the current pid is:%d\n", current->pid);    //显示当前进程的PID值
    printk("out the kernel thread function\n");
    return 0;
}

模块加载函数定义:

static int __init autoremove_wake_function_init(void)
{
    // 局部变量定义
    char namefrm[] = "add_wait_queue.c";
    struct task_struct * result;
    int result1=-2, wait_queue_num=0, left_time;
    wait_queue_t *curr, *next;
    printk("into autoremove_wake_function_init.\n");
    result=kthread_create_on_node(my_function, NULL, -1, namefrm); //创建1个新进程
    wake_up_process(result);
    init_waitqueue_head(&head);           //初始化等待队列头元素
    init_waitqueue_entry(&data, current); // 用当前进程初始化等待队列中的一个元素
    add_wait_queue(&head, &data);         //将当前进程加入等待队列
    left_time = schedule_timeout_uninterruptible(1000); //将等待队列置于不可中断的等待状态
    if(data.private! =NULL)
            result1=autoremove_wake_function(&data, TASK_ALL,0, NULL);
                                          // 将当前进程从等待队列中删除
    list_for_each_entry_safe(curr, next, &(head.task_list), task_list)
                                          // 显示当前等待队列中的进程的信息
    {
        wait_queue_num++;
        printk("the pid value of the current data of the waitqueue is:%d\n", ((struct task_struct *)(curr->private))->pid);
        printk("the state of the current data of the waitqueue is:%ld\n", ((struct task_struct *)(curr->private))->state);
    }
    printk("the letf time of the sleep_on_timeout is :%d\n", left_time);
                                          //显示函数sleep_on_timeout( )的返回结果
    printk("the return result of the autoremove_wake_function is :%d\n", result1);
                                  //显示函数autoremove_wake_function( )的返回结果
    printk("the value of the wait_queue_num is :%d\n", wait_queue_num);
                                          // 显示当前等待队列中的元素个数
    printk("the pid of the kthread_create_on_node is :%d\n", result->pid);
                                          //显示函数kernel_thread( )的返回结果
    printk("the current pid is:%d\n", current->pid);    //显示当前进程的PID值
    printk("out autoremove_wake_function_init.\n");
    return 0;
}

模块退出函数定义:

static void __exit autoremove_wake_function_exit(void)
{
    printk("Goodbye autoremove_wake_function\n");
}

模块加载、退出函数调用:

module_init(autoremove_wake_function_init);
module_exit(autoremove_wake_function_exit);

实例运行结果及分析:

首先编译模块,执行命令insmod autoremove_wake_function.ko插入内核模块,然后输入命令dmesg -c查看模块插入结果,会出现如图所示的结果。

Linux内核API autoremove_wake_function

结果分析:

由上图可以得出在子进程执行时,函数autoremove_wake_function( )执行前,等待队列中有一个元素,并且进程的状态是2,即处于不可中断的等待状态。在子进程中当函数autoremove_wake_function( )执行之后,等待队列中的元素个数变为0,函数autoremove_wake_function( )的返回结果是1,说明函数能够唤醒进程,并将进程从等待队列中删除。

在父进程中函数schedule_timeout_uninterruptible ( )的返回结果是1000,说明进程是被强制唤醒的而非超时唤醒的,也说明了函数autoremove_wake_function( )能够唤醒进程。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程