成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

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

[[429954]]

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

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

waitqueue (等待隊列) 就是內核用于管理等待資源的進程,當某個進程獲取的資源沒有準備好的時候,可以通過調用 add_wait_queue() 函數把進程添加到 waitqueue 中,然后切換到其他進程繼續執行。當資源準備好,由資源提供方通過調用 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 字段用于保護等待隊列在多核環境下數據被破壞,而 task_list 字段用于保存等待資源的進程列表。

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

  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,表示等待的進程應該獨占資源(解決驚群現象)。

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

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

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

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

  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() 函數把等待進程添加到等待隊列,其實現如下:

  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() 函數的實現很簡單,首先通過調用 spin_lock_irqsave() 上鎖,然后調用 list_add() 函數把節點添加到等待隊列即可。

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

waitqueue

休眠等待進程

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

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

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

喚醒等待隊列

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

  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協議

2025-04-30 09:12:35

2019-08-23 12:12:49

MQ消息隊列

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

2021-11-02 10:53:56

Linux機制CPU

2023-12-22 19:59:15

2021-08-04 16:06:45

DataOps智領云

2021-10-15 14:28:30

React 組件渲染

2018-09-28 14:06:25

前端緩存后端

2022-09-22 09:00:46

CSS單位

2025-04-03 10:56:47

2022-11-06 21:14:02

數據驅動架構數據

2021-02-26 05:24:35

Java垃圾回收

2021-04-30 19:53:53

HugePages大內存頁物理

2024-10-12 09:26:32

線程池系統核心線程

2024-04-10 10:34:34

Cache系統GPU

2021-08-11 10:10:26

Linux定時器數組
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 婷婷综合五月天 | 九九综合 | 99色播| 国产高清在线精品 | 精品伊人 | 久久成人一区二区三区 | 岛国av在线免费观看 | 欧美一区二不卡视频 | 中国三级黄色录像 | 日韩欧美在线播放 | 国产一级片 | 免费污视频 | 欧美手机在线 | 黄色片网站在线观看 | 伊人网91 | 麻豆国产一区二区三区四区 | 日韩在线一区二区 | 久久精品成人 | 久久国产成人 | 久久久久网站 | 欧美日韩专区 | 99精品网| 中文字幕免费在线 | 日本欧美在线观看视频 | 精品美女视频在线观看免费软件 | 欧美午夜一区 | 亚洲精品乱码 | 国产精品视频久久久 | 国产精品久久一区二区三区 | 99精品热视频 | 777毛片| 女同久久另类99精品国产 | 另类视频区 | 久久综合久久久 | 国产精品一区二区三区免费观看 | 91在线视频免费观看 | 国产欧美日韩综合精品一区二区 | 成年人视频在线免费观看 | 日韩播放| 日韩av一区二区在线 | 中文在线日韩 |