2018-2019-1 20189218《Linux核心原理與分析》第七週作業
阿新 • • 發佈:2018-11-25
task_struck資料結構
在Linux核心中,通過task_struct這個結構體對程序進行管理,我們可以叫他PCB或者程序描述符。這個結構體定義在include/linux/sched.h
中。
鑑於這個結構體的複雜,本文分成多個部分來分析它。
程序狀態
程序狀態由結構體中的如下程式碼定義:
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
其中state的可取的值如下:
/* * Task state bitmask. NOTE! These bits are also * encoded in fs/proc/array.c: get_task_state(). * * We have two separate sets of flags: task->state * is about runnability, while task->exit_state are * about the task exiting. Confusing, but this way * modifying one set can't modify the other one by * mistake. */ #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 #define __TASK_STOPPED 4 #define __TASK_TRACED 8 /* in tsk->exit_state */ #define EXIT_DEAD 16 #define EXIT_ZOMBIE 32 #define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD) /* in tsk->state again */ #define TASK_DEAD 64 #define TASK_WAKEKILL 128 #define TASK_WAKING 256 #define TASK_PARKED 512 #define TASK_STATE_MAX 1024 ················ #define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE) #define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED) #define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED)
其中,有五個互斥狀態:
- TASK_RUNNING。表示程序要麼正在執行,要麼正要準備執行(已經就緒),正在等待cpu時間片的排程。
- TASK_INTERRUPTIBLE。程序因為等待一些條件而被掛起(阻塞)而所處的狀態。這些條件主要包括:硬中斷、資源、一些訊號……,一旦等待的條件成立,程序就會從該狀態(阻塞)迅速轉化成為就緒狀態TASK_RUNNING。
- TASK_UNINTERRUPTIBLE。意義與TASK_INTERRUPTIBLE類似,除了不能通過接受一個訊號來喚醒以外,對於處於TASK_UNINTERRUPIBLE狀態的程序,哪怕我們傳遞一個訊號或者有一個外部中斷都不能喚醒他們。只有它所等待的資源可用的時候,他才會被喚醒。這個標誌很少用,但是並不代表沒有任何用處,其實他的作用非常大,特別是對於驅動刺探相關的硬體過程很重要,這個刺探過程不能被一些其他的東西給中斷,否則就會讓進城進入不可預測的狀態。
- TASK_STOPPED。程序被停止執行,當程序接收到SIGSTOP、SIGTTIN、SIGTSTP或者SIGTTOU訊號之後就會進入該狀態。
- TASK_TRACED。表示程序被debugger等程序監視,程序執行被除錯程式所停止,當一個程序被另外的程序所監視,每一個訊號都會讓進城進入該狀態。
兩個終止狀態:
- EXIT_ZOMBIE。程序的執行被終止,但是其父程序還沒有使用wait()等系統呼叫來獲知它的終止資訊,此時程序成為殭屍程序。
- EXIT_DEAD。程序的最終狀態。
以及新增的睡眠狀態:
- TASK_KILLABLE。當程序處於這種可以終止的新睡眠狀態中,它的執行原理類似於 TASK_UNINTERRUPTIBLE,只不過可以響應致命訊號。
對於TASK_DEAD
到TASK_STATE_MAX
這五個定義,除了知道TASK_WAKEKILL
是和程序睡眠有關以外,別的都沒有找到具體含義。希望以後用得上的時候能知道。
程序識別符號
sched.h中的以下程式碼定義程序識別符號:
pid_t pid;
pid_t tgid;
Unix系統通過pid來標識程序,linux把不同的pid與系統中每個程序或輕量級執行緒關聯,而unix程式設計師希望同一組執行緒具有共同的pid,遵照這個標準linux引入執行緒組的概念。一個執行緒組所有執行緒與領頭執行緒具有相同的pid,存入tgid欄位,getpid()返回當前程序的tgid值而不是pid的值。
在Linux系統中,一個執行緒組中的所有執行緒使用和該執行緒組的領頭執行緒(該組中的第一個輕量級程序)相同的PID,並被存放在tgid成員中。只有執行緒組的領頭執行緒的pid成員才會被設定為與tgid相同的值。注意,getpid()系統呼叫返回的是當前程序的tgid值而不是pid值。
注意系統中pid的範圍是有限的,