Chinaunix首页 | 论坛 | 博客
  • 博客访问: 493080
  • 博文数量: 41
  • 博客积分: 4007
  • 博客等级: 中校
  • 技术积分: 725
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-30 15:43
文章分类

全部博文(41)

文章存档

2011年(13)

2010年(14)

2009年(2)

2008年(12)

分类:

2010-05-11 19:06:01

3.2.4.2 处理等待队列
DECLARE_WAIT_QUEUE_HEAD用于静态声明一个等待队列的头变量,并初始化lock和task_list分量,init_waitqueue_head用于初始化动态分配的等待队列头变量。
init_waitqueue_entry(q, p)初始化等待队列中的元素(wait_queue_t)
    q->flags = 0;
    q->task = p;
    q->func = default_wake_function;
default_wake_function是TRy_to_wake_up()函数的包裹函数

另外,DEFINE_WAIT宏用于声明一个wait_queue_t变量,并使用当前CPU中运行的进程的进程描述符初始化task分量,以及使用autoremove_wake_function初始化func函数指针。
autoremove_wake_function函数调用default_wake_function来唤醒正在睡眠的进程,然后将被唤醒的进程从等待队列中删除。

一个wait_queue_t元素被定义后,即被插入到等待队列中,add_wait_queue函数将一个非独占资源进程插入到等待队列的头部,add_wait_queue_exclusive函数将一个独占资源进程插入到等待队列的尾部,
remove_wait_queue将一个进程从等待队列中移除,waitqueue_active检查一个给定的等待队列是否为空。

当一个进程希望等待一个特定的条件时,可以调用下列几个函数:
1、sleep_on(),作用于当前进程:
    void sleep_on(wait_queue_head_t *wq)
    {
        wait_queue_t wait;
        init_waitqueue_entry(&wait, current);
        current->state = TASK_UNINTERRUPTIBLE;
        add_wait_queue(wq,&wait); /*  wq points to the wait queue head  */
        schedule( );
        remove_wait_queue(wq, &wait);
    }
    该函数将当前进程的状态设置为TASK_UNINTERRUPTIBLE,并将其插入到某个等待队列中,然后调用调度器,将CPU控制权转移到其他进程中,
    当该睡眠进程被唤醒后,调度器重新回到sleep_on的执行,然后将该进程从等待队列中移除。
2、interruptible_sleep_on(),与sleep_on()相同,除了它将当前进程设置为TASK_INTERRUPTIBLE,这样的话该进程也可以被信号唤醒了。
3、sleep_on_timeout()和interruptible_sleep_on_timeout(),与前面的相似,但他们也允许调用者设置一个时间间隔,当达到时间间隔后,进程会被内核唤醒,通过调用schedule_timeout实现。
4、prepare_to_wait()、prepare_to_wait_exclusive()、finish_wait(),2.6内核引入,提供了另外一种方式使当前进程进入等待队列,典型用法如下:
    DEFINE_WAIT(wait);
    prepare_to_wait_exclusive(&wq, &wait, TASK_INTERRUPTIBLE);
                                /* wq is the head of the wait queue */
    ...
    if (!condition)
        schedule();
    finish_wait(&wq, &wait);
    这两个函数都是通过第三个参数将进程状态设置,然后设置独占标志,然后插入到等待队列中。当条件成立时,就会执行finish_wait函数,该函数将当前进程设置为TASK_RUNNING,并且从等待队列中移除。
5、The wait_event and wait_event_interruptible macros put the calling process to sleep on a wait queue until a given condition is verified. For instance, the wait_event(wq,condition) macro essentially yields the following fragment:

    DEFINE_WAIT(_ _wait);
    for (;;) {
        prepare_to_wait(&wq, &_ _wait, TASK_UNINTERRUPTIBLE);
        if (condition)
            break;
        schedule( );
    }
    finish_wait(&wq, &_ _wait);
阅读(1253) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~