核心隨記(三)--同步(2)
2.2、睡眠與喚醒
在作業系統中,睡眠和喚醒原語實際上是作業系統的基本原語,也是實現同步的一種方式,而且它還是實現訊號量的基礎。當程序請求的資源(如記憶體、檔案等)不能得到滿足時,就會主動放棄CPU,進入等待狀態(可中斷等待或者不可中斷等待)。當資源滿足時,就會由別的程序喚醒,從而投入執行。
2.2.1、等待佇列
等待隊列表示一組睡眠的程序,這些程序正在等待特定的事件發生(或者說條件為真),比如,等待足夠的記憶體。等待佇列是一個雙鏈表,每個佇列都有一個佇列頭,其定義如下:
[html] view plaincopyprint?-
//include/linux/wait.h
- //等待佇列頭
- struct __wait_queue_head {
- // 自旋鎖
- spinlock_t lock;
- struct list_head task_list;
- };
- typedef struct __wait_queue_head wait_queue_head_t;
等待佇列連結串列中的元素型別為:
- typedef struct __wait_queue wait_queue_t;
-
//喚醒函式指標
- typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int sync, void *key);
- //預設的喚醒函式
- int default_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
- struct __wait_queue {
- /*取值為WQ_FLAG_EXCLUSIVE(=1)表示互斥程序,由核心有選擇的喚醒.為0時表示非互斥程序,由核心在
-
**事件發生時喚醒所有等待程序.
- **/
- unsigned int flags;
- #define WQ_FLAG_EXCLUSIVE 0x01
- //等待的任務描述符
- struct task_struct * task;
- //喚醒函式,預設為default_wake_function
- wait_queue_func_t func;
- struct list_head task_list;
- };
其典型的結構如下:
等待佇列頭的初始化:
DECLARE_WAIT_QUEUE_HEAD(name);
其定義如下:
- //incude/linux/wait.h
- #define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \
- .lock = SPIN_LOCK_UNLOCKED, \
- .task_list = { &(name).task_list, &(name).task_list } }
- //初始化等待佇列頭
- #define DECLARE_WAIT_QUEUE_HEAD(name) \
- wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
或者如下:
wait_queue_head_t my_queue;
init_waitqueue_head(&my_queue);
等待佇列元素初始化:
//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中仍然支援,但已經過時。這些介面的基本實現如下:
具體程式碼如下:
- //linux/wait.h
- #define wait_event(wq, condition) \
- do { \
- if (condition) //條件發生 \
- break; \
- __wait_event(wq, condition); \
- } while (0)
- #define __wait_event(wq, condition) \
- do { \
- DEFINE_WAIT(__wait); \
- \
- for (;;) { \
- prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
- if (condition) \
- break; \
- schedule();//排程 \
- } \
- finish_wait(&wq, &__wait); \
- } while (0)
- //kernel/wait.c
- void fastcall
- prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state)
- {
- unsigned long flags;
- //非互斥程序
- wait->flags &= ~WQ_FLAG_EXCLUSIVE;
- //關中斷,並請求自旋鎖
- spin_lock_irqsave(&q->lock, flags);
- if (list_empty(&wait->task_list))
- __add_wait_queue(q, wait); //將等待任務加入等待佇列
- /*
- * don't alter the task state if this is just going to
- * queue an async wait queue callback
- */
- if (is_sync_wait(wait))
- set_current_state(state); //設定任務當前的狀態
- //釋放自旋鎖,並恢復處理器狀態
- spin_unlock_irqrestore(&q->lock, flags);
- }
- //等待完成之後,應該設定任務的狀態為執行狀態,並從等待佇列中刪除
- void fastcall finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
- {
- unsigned long flags;
- __set_current_state(TASK_RUNNING); //設定為執行狀態
- if (!list_empty_careful(&wait->task_list)) {
- spin_lock_irqsave(&q->lock, flags);
- list_del_init(&wait->task_list); //從等待佇列中刪除
- spin_unlock_irqrestore(&q->lock, flags);
- }
- }
2.2.3、喚醒(Waking Up)
介面如下:
- //include/inux/wait.h
- #define wake_up(x) __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1, NULL)
- #define wake_up_nr(x, nr) __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr, NULL)
- #define wake_up_all(x) __wake_up(x, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 0, NULL)
- #define wake_up_interruptible(x) __wake_up(x, TASK_INTERRUPTIBLE, 1, NULL)
- #define wake_up_interruptible_nr(x, nr) __wake_up(x, TASK_INTERRUPTIBLE, nr, NULL)
- #define wake_up_interruptible_all(x) __wake_up(x, TASK_INTERRUPTIBLE, 0, NULL)
- #define wake_up_locked(x) __wake_up_locked((x), TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
- #define wake_up_interruptible_sync(x) __wake_up_sync((x),TASK_INTERRUPTIBLE, 1)
具體實現:
- //kernel/sched.c
- void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode,
- int nr_exclusive, void *key)
- {
- unsigned long flags;
- //請求自旋鎖,並關中斷
- spin_lock_irqsave(&q->lock, flags);
- __wake_up_common(q, mode, nr_exclusive, 0, key);
- spin_unlock_irqrestore(&q->lock, flags);
- }
-
相關推薦
核心隨記(三)--同步(2)
2.2、睡眠與喚醒 在作業系統中,睡眠和喚醒原語實際上是作業系統的基本原語,也是實現同步的一種方式,而且它還是實現訊號量的基礎。當程序請求的資源(如記憶體、檔案等)不能得到滿足時,就會主動放棄CPU,進入等待狀態(可中斷等待或者不可中斷等待)。當資源
【演算法隨記三】小半徑中值模糊的急速實現(16MB圖7.5ms實現) + Photoshop中蒙塵和劃痕演算法解讀。
在本人的部落格裡,分享了有關中值模糊的O(1)演算法,詳見:任意半徑中值濾波(擴充套件至百分比濾波器)O(1)時間複雜度演算法的原理、實現及效果 ,這裡的演算法的執行時間和引數是無關的。整體來說,雖然速度也很快,但是在某些特殊情況下我們還是需要更快的速度。特別是對於小半徑的中值,我們有理由去對其
java隨記2
實例 內部 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上。 該文件系統具備高可用和負載均衡特性,還可以動態擴充容量。 此文件系統有兩個服務組成:跟蹤服務和存儲服務,也就是說你必須部署了這兩種服務,這