Linux内核API __wake_up_sync_key

__wake_up_sync_key函数功能描述:此函数用于唤醒等待队列中处于特定状态的进程,此特定状态由第二个参数mode给出。当进程的状态满足此特定状态时就有可能被唤醒,获得CPU资源,从而被调度执行。此函数唤醒的进程不会改变进程之前所在的CPU,不会引起额外的CPU的抢占,并且可以同步唤醒进程。

__wake_up_sync_key文件包含

#include <linux/wait.h>

__wake_up_sync_key函数定义

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

函数定义格式:

void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr, void * key)

__wake_up_sync_key输入参数说明

此函数的输入参数与函数__wake_up( )的输入参数基本相同,详细信息参考__wake_up( )

__wake_up_sync_key返回参数说明

此函数的返回结果是一个void型的变量,即没有任何返回结果。

__wake_up_sync_key实例解析

编写测试文件:__wake_up_sync_key.c

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

/*头文件引用*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/pid.h>
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/kthread.h>
MODULE_LICENSE("GPL");

/*全局变量定义*/
static wait_queue_head_t head;  //等待队列头元素
struct task_struct * old_thread; //保存进程描述符信息

子进程处理函数定义:

int my_function(void * argc)
{
    printk("in the kernel thread function! \n");
    printk("the current pid is:%d\n", current->pid);      //显示当前进程的PID值

    /*显示父进程的状态*/
    printk("the state of the init funcation is :%ld\n", old_thread->state);
    __wake_up_sync_key(&head, TASK_ALL,0, NULL);          //调用函数唤醒等待队列中的进程

    // 显示函数调用之后的父进程的状态
    printk("the state of the init function after __wake_up_sync_key is :%ld\n", old_thread->state);
    printk("out the kernel thread function\n");
    return 0;
}

模块加载函数定义:

static int __init __wake_up_sync_key_init(void)
{
    char namefrm[]="__wake_up_sync_key.c%s";        //线程的输出类型名,在此无影响
    long time_out; //保存schedule_timeout_uninterruptible( )的返回结果
    struct task_struct * result;                   //保存新进程的信息
    wait_queue_t data;                              //等待队列元素
    printk("into __wake_up_sync_key_init.\n");
    result=kthread_create_on_node(my_function, NULL, -1, namefrm); //创建新进程
    printk("the pid of the new thread is:%d\n", result->pid); //显示新线程的PID值
    printk("the current pid is:%d\n", current->pid);            //显示当前进程的PID值

    init_waitqueue_head(&head);                     //初始化等待队列头元素
    init_waitqueue_entry(&data, current);           //用当前进程初始化等待队列中的一个元素
    add_wait_queue(&head, &data);                   //将等待队列元素加入等待队列中
    old_thread=current;                             //记录当前进程的信息
    wake_up_process(result);                        //唤醒新创建的线程
    time_out=schedule_timeout_uninterruptible(1000*10); //让当前进程进入睡眠状态

    //输出schedule_timeout_uninterruptible( )返回结果
    printk("the schedule timeout is:%ld\n", time_out);
    printk("out __wake_up_sync_key_init.\n");
    return 0;
}

模块退出函数定义:

static void __exit __wake_up_sync_key_exit(void)
{
            printk("Goodbye __wake_up_sync_key\n");
}

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

module_init(__wake_up_sync_key_init);
module_exit(__wake_up_sync_key_exit);

实例运行结果及分析:

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

Linux内核API __wake_up_sync_key

结果分析:

由上图可知模块初始化进程的进程号为6207,新进程的进程号为6208。在新进程中函数__wake_up_sync_key( )执行前模块初始化进程的状态值为2,即处于不可中断的等待状态,因为进程中执行了函数schedule_timeout_uninterruptible( )。函数__wake_up_sync_key( )执行后,模块初始化进程的状态值变为0,并且函数schedule_timeout_uninterruptible( )的返回结果是10000,说明父进程是被强制唤醒的,而非等待超时唤醒。由此可以说明函数__wake_up_sync_key( )能够唤醒等待队列中的满足条件的进程,此条件是进程所处的状态在函数的第二个参数所定义的状态范围内。

进程状态说明:

对于进程能够处于的状态,在函数__wake_up( )的进程状态说明部分有详细的说明。

赞(1)
未经允许不得转载:极客笔记 » Linux内核API __wake_up_sync_key
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址