一、進程狀態轉換基礎
進程是操作系統調度的基本單位,而進程狀態則是描述進程執行過程中狀態的基本概念。進程在其生命周期中會處於不同的狀態,包括新建態、就緒態、運行態、阻塞態和終止態。
新建態是指進程被創建後還未被分配資源的狀態,就緒態是指進程已經獲取到了所有必要資源等待執行的狀態,運行態是指進程正在佔用CPU運行的狀態,阻塞態是指進程等待某些條件滿足或資源釋放的狀態,終止態是指進程執行結束且已經被釋放的狀態。
當進程在不同狀態之間切換的時候,需要進行狀態轉換操作。下面我們以Linux作為例子來介紹進程在狀態之間的轉換操作。
/* 進程狀態 */
enum task_state {
TASK_RUNNING = 0, /* 運行態 */
TASK_INTERRUPTIBLE, /* 可中斷的睡眠態 */
TASK_UNINTERRUPTIBLE, /* 不可中斷的睡眠態 */
TASK_STOPPED, /* 停止態 */
TASK_TRACED, /* 被追蹤態 */
TASK_DEAD, /* 已終止態 */
};
二、進程狀態轉換圖
進程的狀態轉換有多種可能,這裡我們以一種典型的轉換方式為例來說明。下面是進程狀態轉換圖:
+--------+ +----------+ +---------+ +---------+
| 創建態 +------->+ 就緒態 +------>+ 運行態 +------>| 終止態 |
+--------+ +----------+ +---------+ +---------+
^ | ^ |
| | | |
| V | |
+--------------+ +-----------+
| 可中斷的睡眠態 |<--------+ 不可中斷的睡眠態 |
+--------------+ +-----------+
三、進程狀態之間的轉換
下面我們來分別介紹進程狀態之間的轉換方式。
1. 創建態到就緒態
當一個進程被創建時,初始狀態為創建態。當進程被分配到所有必要資源,可以開始執行之前,由創建態轉為就緒態。這個轉換是由系統調度算法決定的,通常是通過進程隊列和調度程序來實現的。
/* 創建一個新進程並將其加入到就緒隊列 */
struct task_struct *init_task(void)
{
/* ...省略其他代碼... */
/* 創建進程 */
p = __alloc_task_struct();
/* 設置進程狀態為就緒態 */
p->state = TASK_RUNNING;
/* 將進程加入到就緒隊列 */
enqueue_task(p, &rq->array[rq->curr]);
return p;
}
2. 就緒態到運行態
當CPU被分配到了進程時,該進程進入運行態。如果此時還有其他進程處於就緒態,則它們將繼續等待CPU資源的分配。
/* 進程從就緒態變為運行態 */
static void __sched __schedule(void)
{
/* ...省略其他代碼... */
/* 獲取就緒隊列里的下一個進程,並將其狀態設置為運行態 */
next = pick_next_task(rq);
next->state = TASK_RUNNING;
/* 切換到下一個進程 */
rq->curr = next;
context_switch(rq, prev, next);
}
3. 運行態到就緒態
當一個進程正在佔用CPU運行時,如果出現IO等等其它需要等待的操作,則該進程從運行態進入阻塞態,然後進入可中斷的睡眠態或者不可中斷的睡眠態,等待IO等操作結束後再轉為就緒態。此時,其他進程有可能獲得CPU使用權。
/* 進程從運行態變為阻塞態 */
void sleep_on(wait_queue_head_t *q)
{
/* ...省略其他代碼... */
//將當前進程的狀態設置為可中斷的睡眠態
current->state = TASK_INTERRUPTIBLE;
//將當前進程加入到等待隊列中
add_wait_queue(q, &wait);
//切換到下一個進程
schedule();
}
4. 阻塞態到就緒態
當阻塞態的進程等待的系統調用返回並且獲得了系統資源時,它從睡眠態或者阻塞態變成就緒態,表示該進程的資源需求已得到滿足,可以開始運行了。
/* 進程從阻塞態變為就緒態 */
void wake_up(wait_queue_head_t *q)
{
/* ...省略其他代碼... */
//將等待隊列中阻塞進程的狀態設置為就緒態
do_each_thread(g, p) {
if (p->state == state &&
(wait == NULL || wait->func(wait, task, mode, key) != 0))
p->state = TASK_RUNNING;
} while_each_thread(g, p);
/* 移除等待隊列中的進程 */
__remove_wait_queue(q, &wait);
/* 切換到下一個進程 */
schedule();
}
5. 運行態到終止態
進程在完成任務後或者出錯時,會從運行態進入終止態。在終止態中,進程進行善後處理和資源釋放。此後,內核將不再管理此進程,以便其它進程使用其資源。
/* 進程從運行態變為終止態 */
asmlinkage void do_exit(long code)
{
/* ...省略其他代碼... */
//設置進程狀態為終止態
current->state = TASK_DEAD;
//從進程表中刪除該進程
del_from_tasklist(current);
/* 切換到下一個進程 */
schedule();
}
結語
進程的狀態轉換是操作系統中非常關鍵的一個概念。我們通過介紹進程的五種狀態和相應的轉換方式,使讀者加深對進程狀態轉換的理解。其實,在Linux系統中還有很多其它的狀態轉換方式,大家可以自行深入學習。
原創文章,作者:BKLI,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/133751.html
微信掃一掃
支付寶掃一掃