• ULK --- Chap3 Processes: Handling Wait Queues


    A new wait queue head may be defined by using the DECLARE_WAIT_QUEUE_HEAD(name) macro,

    which statically declares a new wait queue head variable called name and initializes its lock and

    task_list field. The init_waitqueue_head() function may be used to initialize a wait queue head variable

    that was allocated dynamically.

    The init_waitqueue_entry(q, p) function initializes a wait_queue_t structure q as floowing:

    q->flags = 0;
    q->task = p;
    q->func = default_wake_function;

    The nonexclusive process p will be awaken by default_wak_function(), which is a simple swapper for the

    try_to_wake_up() function.

    Alternatively, the DEFINE_WAIT macro declares a new wait_queue_t variable and initialize it with descriptor

    of the process currently executing on the CPU and the address of autoremove_wake_function() wake up 

    function. This function invokes default_wake_function() to awaken the sleeping process, and then removes

    the wait queue element from the wait queue list. Finally, a kernel developer can define a custom awakening

    function by initializing the wait queue element with the init_waitqueue_func_entry() function.

    Once the element is defined, it must be inserted into a wait queue. The add_wait_queue() function inserts

    a nonexclusive process in the first position of a wait queue list. The add_wait_queue_exclusive() function

    inserts an exclusive process in the last position of a wait queue list. The remove_wait_queue() function removes

    a process from a wait queue list. The waitqueue_active() function checks whether a given wait queue list is

    empty.

    A process waishing to wait for a specific condition can invoke any of the functions shown in the following list.

    The sleep_on() function operates on the current process:

    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);
           schedule();
           remove_wait_queue(wq, &wait);
    }

    The function sets the state of the current process to TASK_UNINTERRUPTIBLE and inserts it into the specified

    wait queue. Then it invokes scheduler, which resumes the execution of another process. When the sleeping

    process is awakened, the scheduler resumes execution of the sleep_on() function, which removes the process

    from the wait queue.

    The interruptible_sleep_on() function is identical to sleep_on(), except that it sets the state of the current 

    process to TASK_INTERRUPTIBLE instead of setting it to TASK_UNINTERRUPTIBLE, so that the process also can

    be awaken up by receiving a signal.

    The sleep_on_timeout() and interruptiblae_sleep_on_timeout() functions are similar to the previous ones, but

    they also allow the caller to define a time interval after the process will be woken up by the kernel. To do this,

    they invoke the schedule_timeout() function instrad of schedule().

    The prepare_to_wait(), prepare_to_wait_exclusive(), and finish_wait() functions, introduced in Linux 2.6, offer

    yet another way to put the current process to sleep in a wait queue,. Typically, they are used as follows:

    DEFINE_WAIT(wait);
    prepare_to_wait_exclusive(&wq, &wait, TASK_INTERRUPTIBLE);
    ......
    if (!condition)
       schedule();
    finish_wait(&wq, &wait);

    The prepare_to_wait() and prepare_to_wait_exclusive() functions set the process state to the value passed 

    as the third parameters, then set the exclusive flag in the wait queue element respectively to 0 (nonexclusive)

    or 1 (exclusive), and finally insert the wait queue element wait into the list of the wait queue head wq.

    As soon as the process is awakened, it executes the finish_wait() function, which sets again the process state

    to TASK_RUNNING (just in case the awaking condition becomes true before invoking schedule()), and removes

    the wait queue element from the wait queue list (unless this has already been done by the waking function).

    The wait_event and wait_event_interruptible macro put the calling process to sleep on a wait queue until a

    given condition is verified. For instance, the wait_event(wq, condition) macro essentialy yields the following

    fragment:

    DEFINE_WAIT(__wait);
    for(;;) {
         prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);
         if (condition)
               break;
         schedule();
    }
    finish_wait(&wq, &__wait);
    }

    A few comments on the function mentioned in the above list: the sleep_on()- like functions cannot be used in the

    common situation where one has to test a condition and atomically put the process to sleep when the condition

    is not verified; therefore, because they are a well-known source of race condition, their use is discouraged.

  • 相关阅读:
    本地安全策略
    windows本地用户及组的区别
    mysql基本命令总结
    常用DOS命令
    AES加密算法详解
    ctf密码学习题总结
    CTF最简单的Web题
    python进阶篇
    JNI开发流程
    JDK中的Timer和TimerTask详解
  • 原文地址:https://www.cnblogs.com/miaoyong/p/4952506.html
Copyright © 2020-2023  润新知