天天看點

PCB task_struct 資料結構 (轉:http://blog.csdn.net/jurrah/article/details/3965437)



在linux 中每一個程序都由task_struct 資料結構來定義. task_struct就是我們通常所說的pcb.她是對程序控制的唯一手段也是最有效的手段. 當我們調用fork() 時, 系統會為我們産生一個task_struct結構。然後從父程序,那裡繼承一些資料, 并把新的程序插入到程序樹中, 以待進行程序管理。是以了解task_struct的結構對于我們了解任務排程(在linux 中任務和程序是同一概念)的關鍵。

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

1、程序狀态 ,将紀錄程序在等待,運作,或死鎖

2、排程資訊, 由哪個排程函數排程,怎樣排程等

3、程序的通訊狀況

4、因為要插入程序樹,必須有聯系父子兄弟的指針, 當然是task_struct型

5、時間資訊, 比如計算好執行的時間, 以便cpu 配置設定

6、标号 ,決定改程序歸屬

7、可以讀寫打開的一些檔案資訊

8、 程序上下文和核心上下文

9、處理器上下文

10、記憶體資訊

因為每一個pcb都是這樣的, 隻有這些結構, 才能滿足一個程序的所有要求。打開/include/linux/sched.h可以找到task_struct 的定義

struct task_struct {

volatile long state; /*說明了該程序是否可以執行,還是可中斷等資訊*/

unsigned long flags; /*flage 是程序号,在調用fork()時給出*/

int sigpending; /*程序上是否有待處理的信号*/

mm_segment_t addr_limit;

/**********************************************************/

/**程序位址空間,區分核心程序與普通程序在記憶體存放的位置不同*/

/****0-0xbfffffff for user-thead    ***********************/

/****0-0xffffffff for kernel-thread ***********************/

volatile long need_resched;

/**********排程标志,表示該程序是否需要重新排程,************/

/**********若非0,則當從核心态傳回到使用者态,會發生排程*******/

int lock_depth; /*********************鎖深度***************/

long nice; /*************程序的基本時間片******************/

unsigned long policy;

/*程序的排程政策,有三種************************************/

/*實時程序:sched_fifo,sched_rr*****************************/

/*分時程序:sched_other*************************************/

struct mm_struct *mm; //程序記憶體管理資訊

int processor;

/*若程序不在任何cpu上運作,

/*cpus_runnable 的值是0,否則是1。

/*這個值在運作隊列被鎖時更新.*/

unsigned long cpus_runnable, cpus_allowed;

struct list_head run_list; /****指向運作隊列的指針*********/

unsigned long sleep_time; /*****程序的睡眠時間*************/

struct task_struct *next_task, *prev_task;

/*用于将系統中所有的程序連成一個雙向循環連結清單*/

/*其根是init_task.*/

struct mm_struct *active_mm;

struct list_head local_pages;/**指向本地頁面***************/

unsigned int allocation_order, nr_local_pages;

struct linux_binfmt *binfmt;/*程序所運作的可執行檔案的格式*/

int exit_code, exit_signal;

int pdeath_signal;/*父程序終止是向子程序發送的信号*********/

unsigned long personality;

/*linux可以運作由其他unix作業系統生成的符合ibcs2标準的程式*/

int did_exec:1;

/*按posix要求設計的布爾量,區分程序正在執行從***************/

/*父程序中繼承的代碼,還是執行由execve裝入的新程式代碼******/

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表pidhash

struct task_struct **pidhash_pprev;

wait_queue_head_t wait_chldexit; /*供wait4()使用***********/

struct completion *vfork_done; /* 供vfork() 使用***********/

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重置初值。

real定時器根據系統時間實時更新,不管程序是否在運作

virtual定時器隻在程序運作時,根據程序在使用者态消耗的時間更新

profile定時器在程序運作時,根據程序消耗的時

(不管在使用者态還是核心态)更新*****************************/

unsigned long it_real_value, it_prof_value, it_virt_value;

unsigned long it_real_incr, it_prof_incr, it_virt_value;

struct timer_list real_timer;//指向實時定時器的指針

struct tms times; //記錄程序消耗的時間,

unsigned long start_time;//程序建立的時間

long per_cpu_utime[nr_cpus], per_cpu_stime[nr_cpus]; //記錄程序在每個cpu上所消耗的使用者态時間和核心态時間

/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */

//記憶體缺頁和交換資訊:

//min_flt, maj_flt累計程序的次缺頁數(copy on write頁和匿名頁)和主缺頁數(從映射檔案或交換裝置讀入的頁面數);

//nswap記錄程序累計換出的頁面數,即寫到交換裝置上的頁面數。

//cmin_flt, cmaj_flt, cnswap記錄本程序為祖先的所有子孫程序的累計次缺頁數,主缺頁數和換出頁面數。在父程序

//回收終止的子程序時,父程序會将子程序的這些資訊累計到自己結構的這些域中

unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;

int swappable:1; //表示程序的虛拟位址空間是否允許換出

/* process credentials *////程序認證資訊

//uid,gid為運作該程序的使用者的使用者辨別符群組辨別符,通常是程序建立者的uid,gid //euid,egid為有效uid,gid

//fsuid,fsgid為檔案系統uid,gid,這兩個id号通常與有效uid,gid相等,在檢查對于檔案系統的通路權限時使用他們。

//suid,sgid為備份uid,gid

uid_t uid,euid,suid,fsuid;

gid_t gid,egid,sgid,fsgid;

int ngroups; //記錄程序在多少個使用者組中

gid_t groups[ngroups]; //記錄程序所在的組

kernel_cap_t cap_effective, cap_inheritable, cap_permitted;//程序的權能,分别是有效位集合,繼承位集合,允許位集合

int keep_capabilities:1;

struct user_struct *user;

/* limits */

struct rlimit rlim[rlim_nlimits]; //與程序相關的資源限制資訊

unsigned short used_math; //是否使用fpu

char comm[16]; //程序正在運作的可執行檔案名

/* file system info *///檔案系統資訊

int link_count, total_link_count;

struct tty_struct *tty; /* null if no tty 程序所在的控制終端,如果不需要控制終端,則該指針為空*/

unsigned int locks; /* how many file locks are being held */

/* ipc stuff *///程序間通信資訊

struct sem_undo *semundo; //程序在信号燈上的所有undo操作

struct sem_queue *semsleeping; //當程序因為信号燈操作而挂起時,他在該隊列中記錄等待的操作

/* cpu-specific state of this task *///程序的cpu狀态,切換時,要儲存到停止程序的

task_struct中

struct thread_struct thread;

/* filesystem information檔案系統資訊*/

struct fs_struct *fs;

/* open file information *///打開檔案資訊

struct files_struct *files;

/* signal handlers *///信号處理函數

spinlock_t sigmask_lock; /* protects signal and blocked */

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;/* thread group tracking */

u32 parent_exec_id;

u32 self_exec_id;

/* protection of (de-)allocation: mm, files, fs, tty */

spinlock_t alloc_lock;

void *journal_info;/* journalling filesystem info */

};

繼續閱讀