偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

一文讀懂Linux延時隊列工作原理

系統(tǒng) Linux
當進程要獲取某些資源(例如從網卡讀取數據)的時候,但資源并沒有準備好(例如網卡還沒接收到數據),這時候內核必須切換到其他進程運行,直到資源準備好再喚醒進程。

[[429954]]

本文轉載自微信公眾號「Linux內核那些事」,作者songsong001 。轉載本文請聯(lián)系Linux內核那些事公眾號。

當進程要獲取某些資源(例如從網卡讀取數據)的時候,但資源并沒有準備好(例如網卡還沒接收到數據),這時候內核必須切換到其他進程運行,直到資源準備好再喚醒進程。

waitqueue (等待隊列) 就是內核用于管理等待資源的進程,當某個進程獲取的資源沒有準備好的時候,可以通過調用 add_wait_queue() 函數把進程添加到 waitqueue 中,然后切換到其他進程繼續(xù)執(zhí)行。當資源準備好,由資源提供方通過調用 wake_up() 函數來喚醒等待的進程。

等待隊列初始化

要使用 waitqueue 首先需要聲明一個 wait_queue_head_t 結構的變量,wait_queue_head_t 結構定義如下:

  1. struct __wait_queue_head { 
  2.     spinlock_t lock; 
  3.     struct list_head task_list; 
  4. }; 

waitqueue 本質上是一個鏈表,而 wait_queue_head_t 結構是 waitqueue 的頭部,lock 字段用于保護等待隊列在多核環(huán)境下數據被破壞,而 task_list 字段用于保存等待資源的進程列表。

可以通過調用 init_waitqueue_head() 函數來初始化 wait_queue_head_t 結構,其實現(xiàn)如下:

  1. void init_waitqueue_head(wait_queue_head_t *q) 
  2.     spin_lock_init(&q->lock); 
  3.     INIT_LIST_HEAD(&q->task_list); 

初始化過程很簡單,首先調用 spin_lock_init() 來初始化自旋鎖 lock,然后調用 INIT_LIST_HEAD() 來初始化進程鏈表。

向等待隊列添加等待進程

要向 waitqueue 添加等待進程,首先要聲明一個 wait_queue_t 結構的變量,wait_queue_t 結構定義如下:

  1. typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int sync, void *key); 
  2.  
  3. struct __wait_queue { 
  4.     unsigned int flags; 
  5.     void *private; 
  6.     wait_queue_func_t func; 
  7.     struct list_head task_list; 
  8. }; 

下面說明一下各個成員的作用:

flags: 可以設置為 WQ_FLAG_EXCLUSIVE,表示等待的進程應該獨占資源(解決驚群現(xiàn)象)。

private: 一般用于保存等待進程的進程描述符 task_struct。

func: 喚醒函數,一般設置為 default_wake_function() 函數,當然也可以設置為自定義的喚醒函數。

task_list: 用于連接其他等待資源的進程。

可以通過調用 init_waitqueue_entry() 函數來初始化 wait_queue_t 結構變量,其實現(xiàn)如下:

  1. static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p) 
  2.     q->flags = 0; 
  3.     q->private = p; 
  4.     q->func = default_wake_function; 

也可以通過調用 init_waitqueue_func_entry() 函數來初始化為自定義的喚醒函數:

  1. static inline void init_waitqueue_func_entry(wait_queue_t *q, wait_queue_func_t func) 
  2.     q->flags = 0; 
  3.     q->private = NULL
  4.     q->func = func; 

初始化完 wait_queue_t 結構變量后,可以通過調用 add_wait_queue() 函數把等待進程添加到等待隊列,其實現(xiàn)如下:

  1. void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) 
  2.     unsigned long flags; 
  3.  
  4.     wait->flags &= ~WQ_FLAG_EXCLUSIVE; 
  5.     spin_lock_irqsave(&q->lock, flags); 
  6.     __add_wait_queue(q, wait); 
  7.     spin_unlock_irqrestore(&q->lock, flags); 
  8.  
  9. static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new) 
  10.     list_add(&new->task_list, &head->task_list); 

add_wait_queue() 函數的實現(xiàn)很簡單,首先通過調用 spin_lock_irqsave() 上鎖,然后調用 list_add() 函數把節(jié)點添加到等待隊列即可。

wait_queue_head_t 結構與 wait_queue_t 結構之間的關系如下圖:

waitqueue

休眠等待進程

當把進程添加到等待隊列后,就可以休眠當前進程,讓出CPU給其他進程運行,要休眠進程可以通過一下方式:

  1. set_current_state(TASK_INTERRUPTIBLE); 
  2. schedule(); 

代碼 set_current_state(TASK_INTERRUPTIBLE) 可以把當前進程運行狀態(tài)設置為 可中斷休眠 狀態(tài),調用 schedule() 函數可以使當前進程讓出CPU,切換到其他進程執(zhí)行。

喚醒等待隊列

當資源準備好后,就可以喚醒等待隊列中的進程,可以通過 wake_up() 函數來喚醒等待隊列中的進程。wake_up() 最終會調用 __wake_up_common(),其實現(xiàn)如下:

  1. static void __wake_up_common(wait_queue_head_t *q,  
  2.     unsigned int mode, int nr_exclusive, int sync, void *key
  3.     wait_queue_t *curr, *next
  4.  
  5.     list_for_each_entry_safe(curr, next, &q->task_list, task_list) { 
  6.         unsigned flags = curr->flags; 
  7.  
  8.         if (curr->func(curr, mode, sync, key) && 
  9.                 (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive) 
  10.             break; 
  11.     } 

可以看出,喚醒等待隊列就是變量等待隊列的等待進程,然后調用喚醒函數來喚醒它們。

 

責任編輯:武曉燕 來源: Linux內核那些事
相關推薦

2022-05-12 10:53:42

keepalivevrrp協(xié)議

2019-08-23 12:12:49

MQ消息隊列

2025-04-30 09:12:35

2021-12-16 14:45:09

https架構服務端

2020-10-22 09:35:11

線程池核心線程阻塞隊列

2017-08-21 10:00:23

遺傳算法Python生物學

2023-01-09 08:14:08

GoHttpServer

2023-12-22 19:59:15

2021-08-04 16:06:45

DataOps智領云

2021-11-02 10:53:56

Linux機制CPU

2021-10-15 14:28:30

React 組件渲染

2024-10-12 09:26:32

線程池系統(tǒng)核心線程

2021-02-26 05:24:35

Java垃圾回收

2021-04-30 19:53:53

HugePages大內存頁物理

2024-04-10 10:34:34

Cache系統(tǒng)GPU

2018-09-28 14:06:25

前端緩存后端

2022-09-22 09:00:46

CSS單位

2022-11-06 21:14:02

數據驅動架構數據

2025-04-03 10:56:47

2021-08-11 10:10:26

Linux定時器數組
點贊
收藏

51CTO技術棧公眾號