1. 程式人生 > >2018-2019-1 20189218《Linux核心原理與分析》第七週作業

2018-2019-1 20189218《Linux核心原理與分析》第七週作業

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_DEADTASK_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的範圍是有限的,