内核中使用wait_event_interruptible和wake_up_interruptible接口函数,来实现内核两个进程之间的交互。
代码实现:
/* 声明一个工作队列入等待*/
static DECLARE_WAIT_QUEUE_HEAD(my_wq);
static volatile int wq_condition = 0;
void thread1()
{
for(;;){
/*进入休眠等待*/
wait_event_interruptible(my_wq, wq_condition );
}
}
void thread2()
{
wq_condition = 1;
/*唤醒休眠的进程*/
wake_up_interruptible(&my_wq);
}
DECLARE_WAIT_QUEUE_HEAD宏定义解析:
1. 功能:创建以个等待队列头
2. 函数原型
#define DECLARE_WAIT_QUEUE_HEAD (name) /
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
#define __WAIT_QUEUE_HEAD_INITIALIZER (name) { /
.lock = __SPIN_LOCK_UNLOCKED(name.lock), /
.task_list = { &(name).task_list, &(name).task_list } }
typedef struct __wait_queue_head wait_queue_head_t ;
struct __wait_queue_head {
spinlock_t lock;
struct list_head task_list;
};
wake_up_interruptible 函数解析:
功能:唤醒注册到等待队列上的进程
原型:
#include
void wake_up_interruptible (wait_queue_head_t *q);
说明:
唤醒 q 指定的注册在等待队列上的进程。该函数不能直接的立即唤醒进程,而是由调度程序转换上下文,调整为可运行状态。
变量:
q : 等待队列变量指针
wait_event_interruptible函数解析:
功能:将当前进程挂起,从运行态队列移出,进入休眠态
原型:
#define wait_event_interruptible(wq, condition) \
({ \
int __ret = 0; \
if (!(condition)) \
__wait_event_interruptible(wq, condition, __ret);\
__ret; \
})
#define __wait_event_interruptible(wq, condition, ret) \
do { \
DEFINE_WAIT(__wait); \
\
for (;;) { \
prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \
if (condition) \
break; \
if (!signal_pending(current)) { \
schedule(); \
continue; \
} \
ret = -ERESTARTSYS; \
break; \
} \
finish_wait(&wq, &__wait); \
} while (0)
wait_event_interruptible()这个函数先将当前进程的状态设置成TASK_INTERRUPTIBLE,然后调用schedule(),而schedule()会将位于TASK_INTERRUPTIBLE状态的当前进程从runqueue队列中删除。从runqueue队列中删除的结果是,当前这个进程将不再参
与调度,除非通过其他函数将这个进程重新放入这个runqueue队列中,这就是wake_up()的作用了。
由于这一段代码位于一个由condition控制的for(;;)循环中,所以当由shedule()返回时(当然是被wake_up之后,通过其他进程的schedule()而再次调度本进程),如果条件condition不满足,本进程将自动再次被设置为TASK_INTERRUPTIBLE状态,接下来执行schedule()的结果是再次被从runqueue队列中删除。这时候就需要再次通过wake_up重新添加到runqueue队列中。
如此反复,直到condition为真的时候被wake_up.
可见,成功地唤醒一个被wait_event_interruptible()的进程,需要满足:
1)condition为真的前提下,2) 调用wake_up()。
2. 关于wait_event_interruptible的返回值
根据 wait_event_interruptible 的宏定义知:
1) 条件condition为真时调用这个函数将直接返回0,而当前进程不会
被 wait_event_interruptible和从runqueue队列中删除。
2) 如果要被wait_event_interruptible的当前进程有nonblocked pending
signals, 那么会直接返回-ERESTARTSYS(i.e. -512),当前进程不会
被wait_event_interruptible 和从runqueue队列中删除。
3) 其他情况下,当前进程会被正常的wait_event_interruptible,并从
runqueue队列中删除,进入TASK_INTERRUPTIBLE状态退出运行调度,
直到再次被唤醒加入runqueue队列中后而参与调度,将正常返回0。
参考文章:
1.