一、進程狀態轉換基礎
進程是操作系統調度的基本單位,而進程狀態則是描述進程執行過程中狀態的基本概念。進程在其生命周期中會處於不同的狀態,包括新建態、就緒態、運行態、阻塞態和終止態。
新建態是指進程被創建後還未被分配資源的狀態,就緒態是指進程已經獲取到了所有必要資源等待執行的狀態,運行態是指進程正在佔用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-hk/n/133751.html