1. 程式人生 > >核心隨記(三)--同步(2)

核心隨記(三)--同步(2)

2.2、睡眠與喚醒

在作業系統中,睡眠和喚醒原語實際上是作業系統的基本原語,也是實現同步的一種方式,而且它還是實現訊號量的基礎。當程序請求的資源(如記憶體、檔案等)不能得到滿足時,就會主動放棄CPU,進入等待狀態(可中斷等待或者不可中斷等待)。當資源滿足時,就會由別的程序喚醒,從而投入執行。

2.2.1、等待佇列

等待隊列表示一組睡眠的程序,這些程序正在等待特定的事件發生(或者說條件為真),比如,等待足夠的記憶體。等待佇列是一個雙鏈表,每個佇列都有一個佇列頭,其定義如下:

[html] view plaincopyprint?
  1. //include/linux/wait.h  
  2. //等待佇列頭  
  3. struct __wait_queue_head {  
  4.       // 自旋鎖  
  5.     spinlock_t lock;  
  6.     struct list_head task_list;  
  7. };  
  8. typedef struct __wait_queue_head wait_queue_head_t;  

等待佇列連結串列中的元素型別為:

[html] view plaincopyprint?
  1. typedef struct __wait_queue wait_queue_t;  
  2. //喚醒函式指標  
  3. typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int sync, void *key);  
  4. //預設的喚醒函式  
  5. int default_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);  
  6. struct __wait_queue {  
  7.     /*取值為WQ_FLAG_EXCLUSIVE(=1)表示互斥程序,由核心有選擇的喚醒.為0時表示非互斥程序,由核心在  
  8.     **事件發生時喚醒所有等待程序.  
  9.     **/  
  10.     unsigned int flags;  
  11. #define WQ_FLAG_EXCLUSIVE    0x01  
  12.     //等待的任務描述符  
  13.     struct task_struct * task;  
  14.     //喚醒函式,預設為default_wake_function  
  15.     wait_queue_func_t func;  
  16.     struct list_head task_list;  
  17. };  

其典型的結構如下:


等待佇列頭的初始化:
DECLARE_WAIT_QUEUE_HEAD(name);
其定義如下:

[html] view plaincopyprint?
  1. //incude/linux/wait.h  
  2. #define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                \  
  3.     .lock        = SPIN_LOCK_UNLOCKED,                \  
  4.     .task_list    = { &(name).task_list, &(name).task_list } }  
  5. //初始化等待佇列頭  
  6. #define DECLARE_WAIT_QUEUE_HEAD(name) \  
  7.     wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)  

或者如下:
wait_queue_head_t my_queue; 
init_waitqueue_head(&my_queue);

等待佇列元素初始化:

//linux/wait.h
//wait_queue_t初始化static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
{
    q
->flags =0;
    q
->task = p;
    q
->func = default_wake_function;
}

2.2.2、等待事件(Waiting on the Event)
核心提供的等待介面包括wait_event(), wait_event_ interruptible(), 和wait_event_interruptible_timeout()。此外sleep_on(), sleep_on_timeout(), 和interruptible_sleep_on()在2.6中仍然支援,但已經過時。這些介面的基本實現如下:

具體程式碼如下:

[html] view plaincopyprint?
  1. //linux/wait.h  
  2. #define wait_event(wq, condition)                     \  
  3. do {                                    \  
  4.     if (condition)    //條件發生                         \  
  5.         break;                            \  
  6.     __wait_event(wq, condition);                    \  
  7. } while (0)  
  8. #define __wait_event(wq, condition)                     \  
  9. do {                                    \  
  10.     DEFINE_WAIT(__wait);                        \  
  11.                                     \  
  12.     for (;;) {                            \  
  13.         prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);    \  
  14.         if (condition)                        \  
  15.             break;                        \  
  16.         schedule();//排程                        \  
  17.     }                                \  
  18.     finish_wait(&wq, &__wait);                    \  
  19. } while (0)  
  20. //kernel/wait.c  
  21. void fastcall  
  22. prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)  
  23. {  
  24.     unsigned long flags;  
  25.     //非互斥程序  
  26.     wait->flags &= ~WQ_FLAG_EXCLUSIVE;  
  27.     //關中斷,並請求自旋鎖  
  28.     spin_lock_irqsave(&q->lock, flags);  
  29.     if (list_empty(&wait->task_list))  
  30.         __add_wait_queue(q, wait);  //將等待任務加入等待佇列  
  31.     /*  
  32.      * don't alter the task state if this is just going to  
  33.      * queue an async wait queue callback  
  34.      */  
  35.     if (is_sync_wait(wait))  
  36.         set_current_state(state);  //設定任務當前的狀態  
  37.     //釋放自旋鎖,並恢復處理器狀態  
  38.     spin_unlock_irqrestore(&q->lock, flags);  
  39. }  
  40. //等待完成之後,應該設定任務的狀態為執行狀態,並從等待佇列中刪除  
  41. void fastcall finish_wait(wait_queue_head_t *q, wait_queue_t *wait)  
  42. {  
  43.     unsigned long flags;  
  44.     __set_current_state(TASK_RUNNING); //設定為執行狀態  
  45.     if (!list_empty_careful(&wait->task_list)) {  
  46.         spin_lock_irqsave(&q->lock, flags);  
  47.         list_del_init(&wait->task_list);    //從等待佇列中刪除  
  48.         spin_unlock_irqrestore(&q->lock, flags);  
  49.     }  
  50. }  

2.2.3、喚醒(Waking Up)
介面如下:

[html] view plaincopyprint?
  1. //include/inux/wait.h  
  2. #define wake_up(x)            __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1, NULL)  
  3. #define wake_up_nr(x, nr)        __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr, NULL)  
  4. #define wake_up_all(x)            __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 0, NULL)  
  5. #define wake_up_interruptible(x)    __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL)  
  6. #define wake_up_interruptible_nr(x, nr)    __wake_up(x, TASK_INTERRUPTIBLE, nr, NULL)  
  7. #define wake_up_interruptible_all(x)    __wake_up(x, TASK_INTERRUPTIBLE, 0, NULL)  
  8. #define    wake_up_locked(x)        __wake_up_locked((x), TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)  
  9. #define wake_up_interruptible_sync(x)   __wake_up_sync((x),TASK_INTERRUPTIBLE, 1)  

具體實現:

[html] view plaincopyprint?
  1. //kernel/sched.c  
  2. void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode,  
  3.                 int nr_exclusive, void *key)  
  4. {  
  5.     unsigned long flags;  
  6.     //請求自旋鎖,並關中斷  
  7.     spin_lock_irqsave(&q->lock, flags);  
  8.     __wake_up_common(q, mode, nr_exclusive, 0, key);  
  9.     spin_unlock_irqrestore(&q->lock, flags);  
  10. }  
  11. 相關推薦

    核心()--同步(2)

    2.2、睡眠與喚醒 在作業系統中,睡眠和喚醒原語實際上是作業系統的基本原語,也是實現同步的一種方式,而且它還是實現訊號量的基礎。當程序請求的資源(如記憶體、檔案等)不能得到滿足時,就會主動放棄CPU,進入等待狀態(可中斷等待或者不可中斷等待)。當資源

    【演算法】小半徑中值模糊的急速實現(16MB圖7.5ms實現) + Photoshop中蒙塵和劃痕演算法解讀。

      在本人的部落格裡,分享了有關中值模糊的O(1)演算法,詳見:任意半徑中值濾波(擴充套件至百分比濾波器)O(1)時間複雜度演算法的原理、實現及效果 ,這裡的演算法的執行時間和引數是無關的。整體來說,雖然速度也很快,但是在某些特殊情況下我們還是需要更快的速度。特別是對於小半徑的中值,我們有理由去對其

    java2

    實例 內部 out 類構造 能力 必須 ret sta pan 1、Arrays java8裏新添加了parallelSort等parallel開頭的方法,表示利用cpu並行的能力 2.面向對象 如果繼承樹裏的某個類要被初始化時,系統將會同時初始化該類的所有父類 子類不會獲

    Vue 2.0

    lis info col pan 百度翻譯 技術分享 clas opened view 1、watch 中,immediate的用法:   immediate -->百度翻譯 立即的 new Vue({ el: ‘#app-7‘,

    Java第四天——核心技術第章(2

    繼續第三章的學習。。。 運算子 運算子+、-、*、/表示加、減、乘、除運算 %求餘操作 /運算 兩個運算元都是整數時,表示整數除法;否則,表示浮點數除法 例:15/2=7 15%2=1 15.0/2=7.5 整數被0除會產生

    oracle 資料庫密碼生產同步模擬環境 ,常用命令

      1、檢視當前open使用者 select username,account_status,expiry_date,profile from dba_users; 2、檢視目前的密碼過期策略 select * from dba_profiles s where s

    工作2-前端開發常見報錯處理(不定時更新)

    1、頁面有空的src屬性(src = "")報錯資訊:GET http://xxxx.com/xxx/ 403 (Forbidden)   :formatted:181 2、ios事件代理on()不起作用 $(document).on("click", ".submitBt

    2017——5月

    ubunt 註意 tro 音頻 機器學習實戰 電腦 人的 其他 優勢 記錄一:2017/05/05   以前看到交換空間的欄目,裏邊的用戶不同地區的人互換住宅,包括如今的嘀嘀打車、甚至代碼的開源,都是資源利用走向開放的應用。聯想到以前看到微軟的全息眼鏡,能不能這樣呢?我在

    2017-05-06:基礎命令和符號

    基礎命令2017-05-06基礎命令:1.mkdir 創建目錄 make directory -p 遞歸創建2.ls 顯示目錄中的內容,列表 list -l (小寫字母L) 顯示詳細的信息 3.pwd 顯示當前你所在的位置

    vue2入坑(一)

    change 奇怪 變量 ble 全局 ole 獲取 cit push 都說Vue2簡單,上手容易,但小馬過河,自己試了才曉得,除了ES6語法和webpack的配置讓你感到陌生,重要的是思路的變換,以前隨便拿全局變量和修改dom的錘子不能用了,變換到關註數據本身。vue的

    ()php高並發

    php 高並發 文件鎖 最近在做一個課程的購買功能,微信支付,以後可能會做團購或者拼團等功能,所以今天想找一找有關秒殺高並發的問題。我理解的方法如下:用另外的單進程處理隊列,下單請求都放到隊列中,一個一個的處理在更新數據庫中庫存數的時候,根據update的結果來判斷,where 庫存 > 0

    php學習3

    split 表達 集合 修飾符 界定 出現 call 大寫字母 popu <?php #正則表達式 #就是一種描寫敘述字符串結構的語法規則 #是一個特定的格式化模式 #1. 行定位符 /* 1) ^行首 2)$行尾 tm

    Sublime使用

    pri http opener read exists proxy .com print 使用 1、安裝 Package Control Ctrl+` 打開命令行,執行如下代碼: 適用於 Sublime Text 3: import urllib.request,os;

    vue2入坑(二) -- 自定義動態組件

    blank -1 reat files 但是 name define 構建 prototype 學習了Vue全家桶和一些UI基本夠用了,但是用元素的方式使用組件還是不夠靈活,比如我們需要通過js代碼直接調用組件,而不是每次在頁面上通過屬性去控制組件的表現。下面講一下如何定

    SQL(四)

    class tput false ica raise output 完整 not delet 1.for loop 循環 格式:for index in lower .. upper     loop     end loop; for i in 1 .. g_desc

    My SQL 002 登陸

    img log 到你 nbsp 結束 分享 mysql5.7 lin 啟動 如何啟動MySQL服務 Step1  我的電腦右鍵屬性找到 控制面板 選擇 系統和安全 Step2  管理工具中找到服務 Step3  找到你的MySQL啟動服務 如何通過黑窗口登陸退出 My

    centos7安裝magento

    nts oar open -i release 錯誤 simple centos pen 在centos7通過yum安裝PHP7,首先在終端運行:rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rp

    html5 01

    水平 北京昌平 轉換 外部 分享 eight html屬性 有序列表 文件信息 一 HTML 是一種制作網站的標記語言 二、HTML基本語法 HTML 標簽 html標簽是html中的最基本單位 也是最重要的部分 通常使用尖角號 開始”<

    html5 02

    畫面 lan 要去 email地址 文字 命名 壓縮 表鏈 html HTML 02 全局通用屬性 id name class style 一、 圖像標簽 標簽名:<img /> 常用屬性: Alt

    FastDFS了解

    log 可用 fast std inux 文件系統 fastdfs 兩種 跟蹤 FastDFS是一個文件系統,可以部署在Linux上。 該文件系統具備高可用和負載均衡特性,還可以動態擴充容量。 此文件系統有兩個服務組成:跟蹤服務和存儲服務,也就是說你必須部署了這兩種服務,這