(一)睡眠和喚醒
休眠(被阻塞)的程序處於乙個特殊的不可執行狀態。無論什麼原因,導致程序進入休眠狀態,核心的操作都是相同的:程序把自己標誌成休眠狀態,從可執行紅黑樹中移出,放入等待佇列,然後呼叫schedule()選擇和執行乙個其他程序。喚醒的過程正好相反,程序把自己標誌成可執行狀態,然後再從等待佇列中移到可執行紅黑樹中。
1:等待佇列
休眠通過等待佇列程序處理,等待佇列是由等待某些事件的發生的程序組成的簡單鍊錶。核心使用wake_queue_head_t來代表等待佇列。等待佇列可以通過declare_waitqueue靜態建立,也可以由init_wakequeue_head()動態建立。
程序通過下面幾個步驟,將自己加入到乙個等待佇列中:
?1:呼叫巨集define_wait()建立乙個等待佇列的項。 ?
?2:呼叫add_wait_queue()將自己加入到佇列中。該佇列會在程序等待的條件滿足時喚醒他。當然,這需要編寫**,當事件滿足時,對等待佇列執行wake_up()操作。
?3:呼叫prepare_to_wait()方法將程序的狀態變更為task_interruptible或task_uninterruptible,而且該函式如果有必要的話會將程序加入到等待佇列,這是在接下來的迴圈遍歷中所需要的。
?4:如果狀態被設定為task_interruptible,則訊號喚醒程序,這就是所謂的偽喚醒(喚醒不是因為事件的發生),因此檢查並處理訊號。
?5:當程序被喚醒的時候,他會再次檢查條件是否為真。如果是,他就會退出迴圈;如果不是,他會再次呼叫schedule()並一直重複這步操作。
?6:當條件滿足後,程序將自己設定為task_running並呼叫finish_wait()函式把自己移出等待佇列。現在我們考慮一下是否會發生競爭的現象:當程序在開始休眠之前條件就已經達成了,那麼迴圈會退出,程序不會再錯誤的進入睡眠的傾向。注意:程序在進入迴圈之前,需要完成一些其他的任務:包括呼叫schedule()之前需要釋放掉鎖,而在這以後再重新獲取他們,或者相應其他事件。
函式inotify_read(),位於fs/notify/inotify/inotify_user.c檔案中,負責從通知檔案描述符中讀取資訊,他的實現是等待佇列的乙個比較典型的用法。
下面我們通過這個函式來體會一下,程序進入休眠狀態的過程:
static ssize_t inotify_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
ret = -eagain;
if (file->f_flags & o_nonblock)
break;
ret = -eintr;
if (signal_pending(current))
break;
if (start != buf)
break;
schedule();
}finish_wait(&group->notification_waitq, &wait);
if (start != buf && ret != -efault)
ret = buf - start;
return ret;
}2:喚醒
喚醒操作通過函式wake_up()進行,他會喚醒指定的等待佇列上的所有程序。他呼叫函式try_to_wake_up(),該函式負責將程序設定為task_running狀態,呼叫enqueue_task()將此程序放入紅黑樹中,如果被喚醒的程序比當前正在執行的程序的優先順序高,還要設定need_resched標誌。
程序排程三 程序排程介紹
一 程序排程介紹 1 程序排程的產生 程序從使用資源方面可以分為如下兩類,不管是i o還是cpu受限類的程序,cpu都希望再盡可能短的時間 完成更多的工作,但另一方面,又希望盡可能的減少資源 i o或cpu 的消耗,這兩則之間存在矛盾,所以程序 的排程管理就是來協調兩者之間的衝突。型別別稱 描述示例...
程序排程(三)
一 睡眠和喚醒 休眠 被阻塞 的程序處於乙個特殊的不可執行狀態。無論什麼原因,導致程序進入休眠狀態,核心的操作都是相同的 程序把自己標誌成休眠狀態,從可執行紅黑樹中移出,放入等待佇列,然後呼叫schedule 選擇和執行乙個其他程序。喚醒的過程正好相反,程序把自己標誌成可執行狀態,然後再從等待佇列中...
實驗三程序排程
1.1.實驗目的 用高階語言完成乙個程序排程程式,以加深對程序的概念及程序排程演算法的理解。1.2.實驗要求 1.2.1例題 設計乙個有 n個程序併發執行的程序排程模擬程式。程序排程演算法 採用最高優先順序優先的排程演算法 即把處理機分配給優先順序最高的程序 和先來先服務 若優先順序相同 演算法。1...