萬盛學電腦網

 萬盛學電腦網 >> Linux教程 >> 讀核日記(三)

讀核日記(三)

class="21789">

在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 {

/* 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 kernel-thread

*/

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 tas74k_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;

};

在分析完 這個結構之後, 還有很多問題要想, 也許不能讀 但框架要搞好.需要向的問題有以下幾個

1,在task_struct 中用的常量在那裡定義呢, 如最大進程個數, 最多支持的cpu 個數,等等

2,在調用fork() 時, 系統是分配一塊內存 會是這樣麼

malloc(1,sizeof(struct task_struck))

拷貝一些變量,還是和服進程公用一部分內存.malloc 函數怎麼實現(在內存管理那一部分,但此處我認為不能不想)

3,.對於線程來說, 又如何實現呢?

4, 調度策略函數 schedul()

有幾種形勢, 時間片輪轉, 搶占式,優先級搶占式, 多級反饋制.除了時間片輪轉外都要對進程樹進行遍歷,(對於實時進程

的fifo機制不用)linux 是怎樣保證了高效呢?如果把最大線成數修改, 效率會不會降低

5, 進程通訊用到的管道,信

copyright © 萬盛學電腦網 all rights reserved