日期:2014-05-16  浏览次数:21021 次

DEFINE_WAIT(__wait)这宏把__wait变量定义在了进程的内核堆栈中,则另一进程使用wake_up时,是如何访问到__wait变量的呢?
#define__wait_event_interruptible(wq, condition, ret) \

do{ \

DEFINE_WAIT(__wait);/×新建一个”等待“,把current加入其中。×/ \

\

for (;;){ \

/×把__wait加入wq(WaitQueue)×/

prepare_to_wait(&wq,&__wait, TASK_INTERRUPTIBLE); \

if(condition) //条件成立,则跳出循环。 \

break; \

if(!signal_pending(current)) { //当前进程有信号,则也跳出,这是interruptible的特有的处理。\

schedule();/休眠,主动让出CPU,/ \

continue; \

} \

ret =-ERESTARTSYS; \

break; \

} \

finish_wait(&wq,&__wait);//离开这个等待队列 \

} while(0)

#define DEFINE_WAIT_FUNC(name, function) \
wait_queue_t name = { \
.private = current, \
.func = function, \
.task_list = LIST_HEAD_INIT((name).task_list), \
}

#define DEFINE_WAIT(name) DEFINE_WAIT_FUNC(name, autoremove_wake_function)

以上宏都是在函数中使用,当宏被展开时,DEFINE(__wait); 这个__wait是作为一个局部变量只在函数内部有效吗?
schedule之后,另外一个进程使用的wake_up中,一定得用到这个变量。但是它是如何变成全局变量的呢?

以下是我的推测,但没证实。
那这与内核的内存操作有关,当schedule之后,其实这个进程就暂停在了schedule之前的环境中,它的内核堆栈也保持不变。当调度之后,其实它的内核堆栈的内核不变。只是esp和ebp的内容变成了新进程的内核堆栈了。此时,当新的进程要使用wake_up时,要访问wait_queue中的每一个wait项,此时如果使用物理地址,或是内核的虚拟地址,也是可以找到旧进程的堆栈中的一个数据的。这样解释对吗?

------解决方案--------------------
把__wait加入wq(WaitQueue)

通过这个等待队列得到.

------解决方案--------------------
只要能拿到地址就好了,kernel都是公用一个页表
参见__wake_up的实现