analysis of wait_event_interruptible()

1 realted structures
Linux-2.6提供如下关于等待队列的操作:
    (1) 定义"等待队列头",
        wait_queue_head_t my_queue;

defined in linux/wait.h

  50 struct __wait_queue_head {
 51         spinlock_t lock;
52 struct list_head task_list;
53 };
54 typedef struct __wait_queue_head wait_queue_head_t;
        
(2) 初始化"等待队列头"
        init_waitqueue_head(&my_queue);

defined in linux/wait.c header file

 
13 void init_waitqueue_head( wait_queue_head_t *q)
 14 {
15 spin_lock_init(&q->lock);
16 INIT_LIST_HEAD(&q->task_list);
17 }
  



        定义和初始化的快捷方式:
        DECLARE_WAIT_QUEUE_HEAD(my_queue);  

linux/wait.h

 70 #define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                           /
71 .lock = __SPIN_LOCK_UNLOCKED(name.lock), /
72 .task_list = { &(name).task_list, &(name).task_list } }
 74 #define DECLARE_WAIT_QUEUE_HEAD(name) /
75 wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)




    (3) 定义等待队列
        DECLARE_WAITQUEUE(name, tsk);
        定义并初始化一个名为name的等待队列(wait_queue_t);

linux/wait.h
 32 struct __wait_queue {
33 unsigned int flags;
34 #define WQ_FLAG_EXCLUSIVE 0x01
35 void *private;
36 wait_queue_func_t func;
37 struct list_head task_list;
38 };

28 typedef struct __wait_queue wait_queue_t;
 62 #define __WAITQUEUE_INITIALIZER(name, tsk) {                            /
63 .private = tsk, /
64 .func = default_wake_function, /
65 .task_list = { NULL, NULL } }
66
67 #define DECLARE_WAITQUEUE(name, tsk) /
68 wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)


2 specific analysis

wait_event_interruptible()。该函数修改task的状态为TASK_INTERRUPTIBLE,意味着改进程将不会继续运行直到被唤醒,然后被添加到等待队列wq中。

在wait_event_interruptible()中首先判断condition是不是已经满足,如果是则直接返回0,否则调用__wait_event_interruptible(),并用__ret来存放返回值

---------------------------------------------------------------

#define wait_event_interruptible(wq, condition)          /

({                                                       /

    int __ret = 0;                                       /

    if (!(condition))                                    /

        __wait_event_interruptible(wq, condition, __ret);/

    __ret;                                               /

})

wait_event_interruptible() --> __wait_event_interruptible()

__wait_event_interruptible()首先定义并初始化一个wait_queue_t变量__wait,其中数据为当前进程current,并把__wait入队。

   
在无限循环中,__wait_event_interruptible()将本进程置为可中断的挂起状态,反复检查condition是否成立,如果成立
则退出,如果不成立则继续休眠;条件满足后,即把本进程运行状态置为运行态,并将__wait从等待队列中清除掉,从而进程能够调度运行。如果进程当前有
异步信号(POSIX的),则返回-ERESTARTSYS。

----------------------------------------------------------------

#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() --> DEFINE_WAIT(name)



/usr/src/linux-2.6.21.5/include/linux/wait.h

---------------------------------------------------------

#define DEFINE_WAIT(name)                               /

    wait_queue_t name = {                               /

        .private    = current,                          /

        .func       = autoremove_wake_function,         /

        .task_list = LIST_HEAD_INIT((name).task_list), -/

    }





wait_queue_t

---------------------------------------------------------

typedef struct __wait_queue wait_queue_t;



struct __wait_queue {

    unsigned int      flags;

#define WQ_FLAG_EXCLUSIVE   0x01

    void              *private;

    wait_queue_func_t func;

    struct list_head task_list;

};



__wait_event_interruptible() --> prepare_to_wait()

void fastcall
prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
{
    unsigned long flags;
    wait->flags &= ~WQ_FLAG_EXCLUSIVE;
    spin_lock_irqsave(&q->lock, flags);
    if (list_empty(&wait->task_list))
        __add_wait_queue(q, wait);
    if (is_sync_wait(wait))
        set_current_state(state);
    spin_unlock_irqrestore(&q->lock, flags);
}


124 static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
125 {
126 list_add(&new->task_list, &head->task_list);
127 }

here, we can see clearly that that function is just simply to link the variable
wait (type of wait_queue_t) into the variable p(type of wait_queue_head_t).

description of list_add:
that essentially invokes the __list_add(new , head, head->next), which implements the task
of inserting new between head and head->next


104 void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
105 {
106 unsigned long flags;
107
108 __set_current_state(TASK_RUNNING);
109 /*
110 * We can check for list emptiness outside the lock
111 * IFF:
112 * - we use the "careful" check that verifies both
113 * the next and prev pointers, so that there cannot
114 * be any half-pending updates in progress on other
115 * CPU's that we haven't seen yet (and that might
116 * still change the stack area.
117 * and
118 * - all other users take the lock (ie we can only
119 * have _one_ other CPU that looks at or modifies
120 * the list).
121 */
122 if (!list_empty_careful(&wait->task_list)) {
123 spin_lock_irqsave(&q->lock, flags);
124 list_del_init(&wait->task_list);
125 spin_unlock_irqrestore(&q->lock, flags);
126 }
127 }
128 EXPORT_SYMBOL(finish_wait);



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: wait_event_interruptible是Linux内核中一个函数,它用于在进程睡眠时等待某个事件的发生。它会检查等待的条件,如果条件已经满足,则立即返回;否则,进程会被置于睡眠状态,直到条件被满足或者被中断。 ### 回答2: wait_event_interruptible是Linux内核中一个等待事件发生的函数。它可以让当前进程进入睡眠状态,并等待某个事件的发生。 wait_event_interruptible函数的原型如下: int wait_event_interruptible(wait_queue_head_t *queue, int condition); 其中,wait_queue_head_t是等待队列的头部,condition是一个判断条件,当条件为真时,进程会被唤醒。 wait_event_interruptible函数的作用是,如果condition条件不满足,进程将进入可打断睡眠状态,并放入等待队列中,直到有其他进程唤醒它。而如果condition条件成立,表示事件已经发生,进程将不会进入睡眠状态,继续执行后续代码。 在睡眠状态中,如果进程接收到一个信号(如SIGINT),wait_event_interruptible函数就会返回,进程会被唤醒。 wait_event_interruptible函数经常与wake_up_interruptible函数一起使用。wake_up_interruptible函数用于唤醒一个睡眠中的进程,而wait_event_interruptible函数则用于判断是否需要进程进入睡眠状态。 wait_event_interruptible函数的使用可以实现进程之间的同步和通信。例如,一个进程可以等待另一个进程完成某个任务,然后再继续执行。这样可以有效地利用CPU资源,并保证进程之间的协作顺利进行。 总之,wait_event_interruptible函数是Linux内核中用于等待事件发生的函数,它可以让进程进入睡眠状态,并等待某个条件的满足。 ### 回答3: wait_event_interruptible是Linux内核提供的一个函数,用于在内核中等待指定的事件发生。 当一个进程调用wait_event_interruptible时,它进入了睡眠状态,直到指定的事件被触发。这个事件通常是一个条件的变化,如某个标志位被设置、一个信号被发送等。在等待过程中,进程被置于可中断的状态,这意味着如果收到一个信号(如SIGINT或SIGTERM),进程可以被唤醒并执行相应的信号处理函数。 wait_event_interruptible的使用通常需要与wake_up_interruptible配合使用。当事件发生时,需要调用wake_up_interruptible来唤醒等待该事件的进程。唤醒后,被唤醒的进程会检查事件是否已经发生,并根据具体情况采取相应的处理措施,如继续执行或者返回错误码。 wait_event_interruptible函数的作用是可靠地等待事件发生,避免了忙等待(busy-waiting)的情况。在实际应用中,wait_event_interruptible可以提高系统的性能和资源利用率,因为它允许其他任务在某个事件触发之前执行并使用CPU。 总之,wait_event_interruptible是Linux内核提供的一个功能强大的等待事件发生的函数,通过将进程置于睡眠状态,并可中断地等待事件发生,可以实现高效、可靠地等待事件的发生。它在多种应用场景中被广泛使用,如设备驱动、网络协议和文件系统等。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值