剖析task_struct 數據結構

                                         粉絲不過W

     在 linux 中每一個進程都由 task_struct 數據結構來定義

     task_struct 就是 PCB。是對進程控制的唯一手段也是最有效的手段

       當我們調用 fork() 時, 系統會爲我們產生一個 task_struct 結構,然後從父進程那裏繼承一些數據, 並把新的進程插入到進程樹中, 以待進行進程管理

     因此瞭解 task_struct 的結構對於我們理解任務調度( 在 linux 中任務和進程是同一概念 )的關鍵

      進行剖析 task_struct 的定義之前,我們先按照我們的理論推一下它的結構

           進程狀態 ,將紀錄進程在等待,運行,死鎖

           調度信息,由哪個調度函數調度,怎樣調度

           進程的通訊狀況

           因爲要插入進程樹,所以有聯繫父子兄弟的指針, 必須是 task_struct 型

           時間信息,如 計算好執行的時間, 以便 cpu 分配

           標號,決定改進程歸屬

           可 讀寫打開的一些文件信息

          進程上下文和內核上下文

          處理器上下文

          內存信息

       因爲每一個 PCB 都是這樣的, 只有這些結構, 才能滿足一個進程的所有要求

struct task_struct
{
    /* -1 unrunnable, 0 runnable, >0 stopped: 
     * 該進程是否可以執行,還是可中斷等信息
     */
    volatile long state;
    //每個任務標誌(PF_*),定義如下
    unsigned long flags;    //進程號,在調用 fork()時給出
    int sigpending;         //進程上是否有待處理的信號
    mm_segment_t addr_limit;/*進程地址空間,區分內核進程與普通進程在內存存放的位置不同
                             *0 - 0xBFFFFFFF for user-thead
                             *0 - 0xFFFFFFFF for kernel-thread
                             */
    //調度標誌,表示該進程是否需要重新調度,若非 0,則當從內核態返回到用戶態,會發生調度
    volatile long need_resched;
    int lock_depth;    //鎖深度
    long nice;        //進程的基本時間片
    //進程的調度策略,有三種,實時進程:SCHED_FIFO,SCHED_RR, 分時進程:SCHED_OTHER
    unsigned long policy;
    struct mm_struct *mm;    //進程內存管理信息
    int processor;
    //若進程未運行, cpus_runnable 的值是 0,否則是 1 這個值在運行隊列被鎖時更新
    unsigned long cpus_runnable, cpus_allowed;
    struct list_head run_list;    //指向運行隊列的指針
    unsigned long sleep_time;    //進程的睡眠時間
    //用於將系統中所有的進程連成一個雙向循環鏈表, 其根是 init_task
    struct task_struct *next_task, *prev_task;
    struct mm_struct *artive_mm;
    struct list_head local_pages;    //指向本地頁面
    unsigned int allocation_order, nr_local_pages;
    struct linx_binfmt *binfmt;    //進程所運行的可執行文件的格式
    int exit_code,exit_signal;
    int pdeath_signal;    //父進程終止是向子進程發送的信號
    unsignal long personality;
    //Linux 可以運行由其他 UNIX 操作系統生成的符合 iBCS2 標準的程序
    int did_exec;
    pid_t pid;    //進程標識符,用來代表一個進程
    pid_t pgrp;    //進程組標識,表示進程所屬的進程組
    pid_t tty_old_pgrp;    //進程控制終端所在的組標識
    pid_t session;    //進程的會話標識
    pid_t tgid;
    int leader;    //進程是否爲會話主管
    struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
    struct list_head thread_group;    //線程鏈表
    struct task_struct *pidhash_next;    //用於將進程鏈入 HASH 表
    struct task_struct **pidhash_pprev;
    wait_queue_head_t wait_chldexit;    //供wait4()使用
    struct completion *vfork_done;    //供fork()使用
    unsigned long rt_priority;    //實時優先級,用它計算實時進程調度時的weight值
    /*
     * it_real_value, it_real_incr 用於 REAL 定時器,單位爲 jiffies, 
     *系統根據 it_real_value設置定時器的第一個終止時間. 在定時器到期時,
     *向進程發送 SIGALRM 信號,同時根據it_real_incr 重置終止時間.
     * it_prof_value, it_prof_incr 用於 Profile 定時器,單位爲 jiffies,
     *當進程運行時,不管在何種狀態下,每個 tick 都使 it_prof_value 值減一,
     *當減到 0 時,向進程發送信號 SIGPROF,並根據 it_prof_incr 重置時間.
     * it_virt_value, it_virt_value 用於 Virtual 定時器,單位爲 jiffies。
     *當進程運行時,不管在何種狀態下,每個 tick 都使 it_virt_value 值減一當減到 0 時,
     *向進程發送信號 SIGVTALRM,根據it_virt_incr 重置初值。
     */
    unsigned long it_real_value, it_prof_value, it_virt_value;
    unsigned long it_real_incr, it_prof_incr, it_virt_incr;
    struct timer_list real_timer;    //指向實時定時器的指針
    struct tms times;    //記錄進程的消耗的時間
    unsigned long start_time;    //進程創建的時間
    //記錄進程在每個 CPU 上所消耗的用戶態時間和核心態時間
    long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
    //內存缺頁和交換信息:
    unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
    //表示進程的虛擬地址空間是否允許換出
    int swappable:1;

    /*
     * 進程認證信息:
     *  uid,gid 爲運行該進程的用戶的用戶標識符和組標識符,通常是進程創建者的 uid,gid
     *  euid, egid 爲有效 uid,gid
     *  fsuid, fsgid 爲文件系統 uid,gid,這兩個 ID 號通常與有效 uid,gid 相等,
     *在檢查對於文件系統的訪問權限時使用他們
     *  suid, sgid 爲備份 uid,gid
     */
    uid_t uid, euid, fsuid;
    gid_t gid, egid, fsgid;
    //記錄進程在多少個用戶組中
    int nproups;
    //記錄進程所在的組
    gid_t groups[NGROUPS];
    //進程的權能,分別是有效位集合,繼承位集合,允許位集合
    kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
    int keep_capabilities:1;
    struct user_struct *user;
    //與進程相關的資源限制信息
    struct rlimit rlim[RLIM_NLIMITS];
    //是否使用 FPU
    unsigned short used_math;
    //進程正在運行的可執行文件名
    char comm[16];

    //文件系統信息
    int link_count, total_link_count;
    //NULL if no tty 進程所在的控制終端,如果不需要控制終端,則該指針爲空
    struct tty_struct *tty;
    unsigned int locks;

    //進程間通信信息
    //進程在信號燈上的所有 undo 操作
    struct sem_undo *semundo;
    //當進程因爲信號燈操作而掛起時,他在該隊列中記錄等待的操作
    struct sem_queue *semsleeping;
    //進程的 CPU 狀態,切換時,要保存到停止進程的 task_struct 中
    struct thread_struct thread;
    //文件系統信息
    struct fs_struct *fs;
    //打開文件信息
    struct files_struct *files;
    //信號處理函數
    spinlock_t sigmask_lock;
    struct signal_struct *sig;
    //進程當前要阻塞的信號,每個信號對應一位
    sigset_t blocked;
    //進程上是否有待處理的信號
    struct sigpending pending;
    unsigned long sas_ss_sp;
    size_t sas_ss_size;
    int(*notifier)(void *priv);
    void *notifier_data;
    sigset_t *notifier_mask;
    u32 parent_exec_id;
    u32 self_exec_id;
    spinlock_t alloc_lock
    void *journal_info;
};

 

 

 

生成結果

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章