我們都曉得所謂的進程就是正在運行的一個程序,它是由正文段,用戶數據段和系統數據段所組成的一個動態實體。系統數據段存放着進程的控制信息。其中包括進程控制塊PCB。
而在linux中每一個進程都由task_struct數據結構來定義(也稱爲任務結構體)。task_struct就是我們通常所說的PCB。它是進程存在的唯一標識,也是Linux進程實體的核心。
當我們調用fork()時,系統會爲我們產生一個task_struct結構,然後從父進程,那裏繼承一些數據, 並把新的進程插入到進程樹中,以待進行進程管理。因此task_struct的結構對於我們理解進程調度有着關鍵作用。
在進行剖析task_struct的定義之前.我們先看一下一個進程基本的要求有哪些:
1,進程狀態,將紀錄進程在等待,運行,或死鎖
2,調度信息,由哪個調度函數調度,怎樣調度等
3,進程的通訊狀況
4,因爲要插入進程樹,必須有聯繫父子兄弟的指針,當然是task_struct型
5,時間信息,比如計算好執行的時間,以便cpu分配
6,標號,決定改進程歸屬
7,可以讀寫打開的一些文件信息
8,進程上下文和內核上下文
9,處理器上下文
10,內存信息
只有這些結構存在了,才能滿足一個進程的所有要求.
然後我們打開/include/linux/sched.h
找到task_struct的定義:
struct task_struct {
/* these are hardcoded - don't touch */這裏是一些硬件設置對程序原來說是透明的.
其中state說明了該進程是否可以執行,還是可以中斷等信息.
Flage是進程號,在調用fork()時給出,
addr_limit是區分內核進程與普通進程在內存存放的位置不同
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
unsigned long flags; /* per process flags, defined below */
int sigpending;
mm_segment_t addr_limit; /* thread address space: 0-0xBFFFFFFF for user-thead 0-0xFFFFFFFF for kernelthread */
struct exec_domain *exec_domain;
long need_resched;
/* various fields */
count是計數器 priorrity是優先級
long counter;
long priority;
cycles_t avg_slice;
/* SMP and runqueue state */ 爲多處理機定義的變量.
int has_cpu;
int processor;
int last_processor;
int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */
爲了在進程樹中排序, 定義的父子,兄弟指針
struct task_struct *next_task, *prev_task;
struct task_struct *next_run, *prev_run;
/* task state */ 定義task運行的狀態,以及信號
struct linux_binfmt *binfmt;
int exit_code, exit_signal;
int pdeath_signal; /* The signal sent when the parent dies */
/* 定義可進程的用戶號,用戶組以及進程組*/
unsigned long personality;
int dumpable:1;
int did_exec:1;
pid_t pid;
pid_t pgrp;
pid_t tty_old_pgrp;
pid_t session;
/* boolean value for session group leader */
是不是進程組的頭文件
int leader;
/*
* pointers to (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with * p->p_pptr->pid)
*/
父子進程的一些指針
struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
/* PID hash table linkage. */ 在調度中用的一些hash表
struct task_struct *pidhash_next;
struct task_struct **pidhash_pprev;
/* Pointer to task[] array linkage. */
struct task_struct **tarray_ptr;
struct wait_queue *wait_chldexit; /* for wait4() 等待隊列 */ struct semaphore *vfork_sem; /* for vfork() */
unsigned long policy, rt_priority;
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;
long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];定義了時間片的大小
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
內存信息
unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap; int swappable:1;
/* process credentials */
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;
struct user_struct *user;
以下英文註釋很清楚
/* limits */
struct rlimit rlim[RLIM_NLIMITS];
unsigned short used_math;
char comm[16]; /* file system info */
int link_count;
struct tty_struct *tty; /* NULL if no tty */
/* ipc stuff */
struct sem_undo *semundo;
struct sem_queue *semsleeping;
/* tss for this task */
struct thread_struct tss;
/* filesystem information */
struct fs_struct *fs;
/* open file information */
struct files_struct *files;
/* memory management info */
struct mm_struct *mm;
/* signal handlers */
spinlock_t sigmask_lock;
/* Protects signal and blocked */
struct signal_struct *sig; sigset_t signal, blocked;
struct signal_queue *sigqueue, **sigqueue_tail;
unsigned long sas_ss_sp;
size_t sas_ss_size;
};
在分析完這個結構之後, 還有很多問題要想要問,也許不能完全理解,但基本的框架要有.要有一個大體的認識,要瞭解到一個task_struct中基本的結構,這對今後學習進程和線程有着舉足輕重的作用。