:::danger 先把一些筆記寫下來,尚未好好整理或翻譯! ::: --- 待查: cross compiler schedule(); 參考網站: [Linux kernel - wait queue.](https://huenlil.pixnet.net/blog/post/25190567) [Waitqueue in Linux – Linux Device Driver Tutorial Part 10](https://embetronicx.com/tutorials/linux/device-drivers/waitqueue-in-linux-device-driver-tutorial/) [Zombie Process In Linux](https://totozhang.github.io/2016-01-16-linux-zombieprocess/) --- ### ==Waitqueue in Linux – Linux Device Driver Tutorial 筆記== There are 3 important steps in Waitqueue. 1. Initializing Waitqueue 2. Queuing (Put the Task to sleep until the event comes) 3. Waking Up Queued Task #### ==Initializing Waitqueue== There are two ways to initialize the waitqueue. 1. Static method ```clike= DECLARE_WAIT_QUEUE_HEAD(wq); ``` Where the “wq” is the name of the queue on which task will be put to sleep. 2. Dynamic method ```clike= wait_queue_head_t wq; init_waitqueue_head (&wq); ``` #### ==Queuing== There are several macros are available for different uses. 1. **wait_event** ```clike wait_event(wq, condition); ``` 2. **wait_event_timeout** ```clike wait_event_timeout(wq, condition, timeout); ``` 3. **wait_event_cmd** ```clike wait_event_cmd(wq, condition, cmd1, cmd2); ``` 4. **wait_event_interruptible** ```clike wait_event_interruptible(wq, condition); ``` 5. **wait_event_interruptible_timeout** ```clike wait_event_interruptible_timeout(wq, condition, timeout); ``` 6. **wait_event_killable** ```clike wait_event_killable(wq, condition); ``` :::info **wq** – the waitqueue to wait on **condition** – a C expression for the event to wait for **timeout** – timeout, in jiffies **cmd1** – the command will be executed before sleep **cmd2** – the command will be executed after sleep ::: - 最基本: - ==sleep (TASK_UNINTERRUPTIBLE)== until a condition gets true - The condition is checked each time the waitqueue wq is woken up. - interruptible: - ==sleep (TASK_INTERRUPTIBLE)== - return - **-ERESTARTSYS** - if it was interrupted by a signal - **0** - if condition evaluated to true. - timeout - sleep until the condition evaluates to true or timeout elapses. - return - **0** - if the condition evaluated to false after the timeout elapsed - **1** - if the condition evaluated to true after the timeout elapsed - **the remaining jiffies (at least 1)** - if the condition evaluated to true before the timeout elapsed. - killable - sleep (TASK_KILLABLE) until the condition evaluates to true or a signal is received. :::success Old kernel versions used the functions ==sleep_on()== and ==interruptible_sleep_on()==, but those two functions can **introduce bad race conditions** and **should not be used**. ::: #### ==Waking Up Queued Task== we can use the below function to wake up those tasks. 1. **wake_up** wakes up ==only one process== from the wait queue which is in ==non-interruptible sleep==. ```clike wake_up(&wq); ``` 2. **wake_up_all** wakes up ==all the processes== on the wait queue ```clike wake_up_all(&wq); ``` 3. **wake_up_interruptible** wakes up ==only one process== from the wait queue that is in ==interruptible sleep== ```clike wake_up_interruptible(&wq); ``` 4. **wake_up_sync and wake_up_interruptible_sync** ```clike wake_up_sync(&wq); wake_up_interruptible_sync(&wq); ``` Normally, a wake_up call can cause an immediate reschedule to happen, meaning that other processes might run before wake_up returns. The “synchronous” variants instead make any awakened processes runnable but do not reschedule the CPU. This is used to avoid rescheduling when the current process is known to be going to sleep, thus forcing a reschedule anyway. Note that awakened processes could run immediately on a different processor, so these functions should not be expected to provide mutual exclusion. :::info **wq** – the waitqueue to wake up :::