函数原型:
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。