Linux内核API —— __wake_up

函数原型:

    void __wake_up(struct wait_queue_head* q, unsigned int mode, int nr, void* key);

功能:

    此函数用于唤醒等待队列中的处于特定状态中的进程。当该进程的状态为mode时,则有可能被唤醒获得cpu资源,从而被调度执行。

进程状态定义:

    在linux/sched.h中有进程相关的状态定义。

/*
 * Task state bitmask. NOTE! These bits are also
 * encoded in fs/proc/array.c: get_task_state().
 *
 * We have two separate sets of flags: task->state
 * is about runnability, while task->exit_state are
 * about the task exiting. Confusing, but this way
 * modifying one set can't modify the other one by
 * mistake.
 */

/* Used in tsk->state: */
#define TASK_RUNNING                    0
#define TASK_INTERRUPTIBLE              1
#define TASK_UNINTERRUPTIBLE            2
#define __TASK_STOPPED                  4
#define __TASK_TRACED                   8
/* Used in tsk->exit_state: */
#define EXIT_DEAD                       16
#define EXIT_ZOMBIE                     32
#define EXIT_TRACE                      (EXIT_ZOMBIE | EXIT_DEAD)
/* Used in tsk->state again: */
#define TASK_DEAD                       64
#define TASK_WAKEKILL                   128
#define TASK_WAKING                     256
#define TASK_PARKED                     512
#define TASK_NOLOAD                     1024
#define TASK_NEW                        2048
#define TASK_STATE_MAX                  4096

#define TASK_STATE_TO_CHAR_STR          "RSDTtXZxKWPNn"

/* Convenience macros for the sake of set_current_state: */
#define TASK_KILLABLE                   (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
#define TASK_STOPPED                    (TASK_WAKEKILL | __TASK_STOPPED)
#define TASK_TRACED                     (TASK_WAKEKILL | __TASK_TRACED)

#define TASK_IDLE                       (TASK_UNINTERRUPTIBLE | TASK_NOLOAD)

/* Convenience macros for the sake of wake_up(): */
#define TASK_NORMAL                     (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)
#define TASK_ALL                        (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED)

    不同内核会有所区别,具体各状态代表什么意思,大家可以google一下,这里不展开。

    实例Demo:

    __wake_up.c

#include<linux/wait.h>
#include<linux/kthread.h>
#include<linux/list.h>
#include<linux/sched.h>
#include<linux/delay.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("viz");

static int  __init __weakup_test_init(void);
static void __exit __weakup_test_exit(void);

static struct task_struct* old_task;
static struct wait_queue_head head;

int func_weakup(void* args)
{
   printk("func_weakup...\n");
   printk("this thread pid = %\d\n",current->pid);

   //print init status
   printk("init status, old_task->state = %ld\n",old_task->state);

   //__wake_up
   //__wake_up(&head,TASK_ALL,0,NULL);

   printk("after __weak_up, old_task->state = %ld\n",old_task->state);
return 0;
}

static int __init __weakup_test_init(void)
{
   printk("test init...\n");

   char namefrt[] = "__weakup.c:%s";
   long timeout;
   struct task_struct* result;
   struct wait_queue_entry data;
   printk("into weak up...\n");
   result = kthread_create_on_node(func_weakup,NULL,-1,namefrt);
   printk("the new thread pid is : %ld\n",result->pid);
   printk("the current pid is: %ld\n",current->pid);
   init_waitqueue_head(&head);
   init_waitqueue_entry(&data,current);
   add_wait_queue(&head,&data);
   old_task = current;
   //wake_up(&head);
    wake_up_process(result);
   timeout = schedule_timeout_uninterruptible(1000*10);
   printk("sleep timeout = %ld\n",timeout);
   printk("out __weakup_test_init\n");
return 0;
}

static void __exit __weakup_test_exit(void)
{
   printk("test exit...\n");
}

module_init(__weakup_test_init);
module_exit(__weakup_test_exit);

  Makefile

#
# Made from Makefile.org 
#

obj-m += __wake_up.o

编译脚本make.sh

#/bin/sh
ver=`uname -r`
make -C /lib/modules/$ver/build M=$PWD "$@"


分析:

一、先注释__wake_up函数,insmod __wake_up.ko,实践中这个过程需要大概10s时间才能完成,之后dmesg查看log信息。

[ 2087.345261] __wake_up: loading out-of-tree module taints kernel.
[ 2087.345588] __wake_up: module verification failed: signature and/or required key missing - tainting kernel
[ 2087.347020] test init...
[ 2087.347020] into weak up...
[ 2087.347152] the new thread pid is : 5840
[ 2087.347153] the current pid is: 5839
[ 2087.347224] func_weakup...
[ 2087.347226] this thread pid = 5840
[ 2087.347226] init status, old_task->state = 2
[ 2087.347227] after __weak_up, old_task->state = 2
[ 2128.863258] sleep timeout = 0
[ 2128.863261] out __weakup_test_init

二、放开__wake_up函数,执行相同动作,发现insmod立即完成,同时dmesg查看信息。

[ 2323.877494] test init...
[ 2323.877495] into weak up...
[ 2323.877636] the new thread pid is : 6692
[ 2323.877637] the current pid is: 6691
[ 2323.877643] func_weakup...
[ 2323.877643] this thread pid = 6692
[ 2323.877644] init status, old_task->state = 2
[ 2323.877646] after __weak_up, old_task->state = 0
[ 2323.877659] sleep timeout = 10000
[ 2323.877659] out __weakup_test_init

第一个过程,新进程的初始状态是2,即处于不可中断状态,因为__init中调用了schedule_timeout_uninterruptible,所以insmod过程会有10s的等待。

第二个过程,__wake_up执行之前,进程状态为2,执行之后变为0,说明模块初始化进程被强制唤醒,因而insmod的动作并不会等待10s。


相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页