1、PCB进程控制块--->task_struct
广义上,所有的进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
每个进程在内核中都有一个进程控制块来维护进程的相关信息,Linux内核的进程控制块是task_struct结构体,task_struct主要包含了以下内容:
1.调度数据成员
① volatile long state ;
表示进程的当前状态:
? TASK_RUNNING:正在运行或在就绪队列run-queue中准备运行的进程,实际参与进程调度。
? TASK_INTERRUPTIBLE:处于等待队列中的进程,待资源有效时唤醒,也可由其它进程通过信号(signal)或定时中断唤醒后进入就绪队列run-queue。
? TASK_UNINTERRUPTIBLE:处于等待队列中的进程,待资源有效时唤醒,不可由其它进程通过信号(signal)或定时中断唤醒。
? TASK_ZOMBIE:表示进程结束但尚未消亡的一种状态(僵死状态)。此时,进程已经结束运行且释放大部分资源,但尚未释放进程控制块。
?TASK_STOPPED:进程被暂停,通过其它进程的信号才能唤醒。导致这种状态的原因有二,或者是对收到SIGSTOP、SIGSTP、SIGTTIN或SIGTTOU信号的反应,或者是受其它进程的ptrace系统调用的控制而暂时将CPU交给控制进程。
? TASK_SWAPPING: 进程页面被交换出内存的进程。
②unsigned long flags;
Flage 是进程号,在调用fork()时给出,表示进程标志:
?PF_ALIGNWARN 打印“对齐”警告信息。
?PF_PTRACED 被ptrace系统调用监控。
?PF_TRACESYS 正在跟踪。
?PF_FORKNOEXEC 进程刚创建,但还没执行。
?PF_SUPERPRIV 超级用户特权。
?PF_DUMPCORE dumped core。
?PF_SIGNALED 进程被信号(signal)杀出。
?PF_STARTING 进程正被创建。
?PF_EXITING 进程开始关闭。
?PF_USEDFPU 该进程使用FPU(SMP only)。
?PF_DTRACE delayed trace (used on m68k)。
③long priority;
表示进程优先级
Priority的值给出进程每次获取CPU后可使用的时间(按jiffies计)。优先级可通过系统调用sys_setpriorty改变(在kernel/sys.c中)。
④unsigned long rt_priority;
给出实时进程的优先级
rt_priority+1000给出进程每次获取CPU后可使用的时间(同样按jiffies计)。实时进程的优先级可通过系统 调用sys_sched_setscheduler()改变(
见kernel/sched.c)。
⑤ long counter;
轮转法调度时表示进程当前还可运行多久
在进程开始运行是被赋为priority的值,以后每隔一个tick(时钟中断)递减1,减到0时引起新一轮调 度。重新调度将从run_queue队列选出counter值最
大的就绪进程并给予CPU使用权,因此counter起到了进程的动态优先级的作用 (priority则是静态优先级)。
⑥unsigned long policy;
该进程的进程调度策略
可以通过系统调用sys_sched_setscheduler()更改(见kernel/sched.c)。调度策略有:
?SCHED_OTHER 0 非实时进程,基于优先权的轮转法(round robin)。
?SCHED_FIFO 1 实时进程,用先进先出算法。
?SCHED_RR 2 实时进程,用基于优先权的轮转法。
2.信号处理
① unsigned long signal;
进程接收到的信号。每位表示一种信号,共32种。置位有效。
②unsigned long blocked;
进程所能接受信号的位掩码。置位表示屏蔽,复位表示不屏蔽。
③struct signal_struct *sig;
因为signal和blocked都是32位的变量,Linux最多只能接受32种信号。对每种信号,各进程可以由PCB的sig属性选择使用自定义的处理函数,或是系统的缺省处理函数。指派各种信息处理函数的结构定义在include/linux/sched.h中。对信号的检查安排在系统调用结束后,以及“慢速型”中断服务程序结束后。
3.进程队列指针
①struct task_struct *next_task,*prev_task;
所有进程(以PCB的形式)组成一个双向链表。next_task和就是链表的前后指针。链表的头和尾都是init_task(即0号进程)。
②struct task_struct *next_run,*prev_run;
由正在运行或是可以运行的,其进程状态均为TASK_RUNNING的进程所组成的一个双向循环链表,即run_queue就绪队列。该链表的前后向指针用next_run和prev_run,链表的头和尾都是init_task(即0号进程)。
③ struct task_struct *p_opptr,*p_pptr;和struct task_struct *p_cptr,*p_ysptr,*p_osptr;
以上分别是指向原始父进程(original parent)、父进程(parent)、子进程(youngest child)及新老兄弟进程(younger sibling,older sibling)的指针。
4.进程标识
①unsigned short uid,gid;
uid和gid是运行进程的用户标识和用户组标识。
② int groups[NGROUPS];
与多数现代UNIX操作系统一样,Linux允许进程同时拥有一组用户组号。在进程访问文件时,这些组号可用于合法性检查。
③unsigned short euid,egid;
euid 和egid又称为有效的uid和gid。出于系统安全的权限的考虑,运行程序时要检查euid和egid的合法性。通常,uid等于euid,gid等于 egid。有时候,系统会赋予一般用户暂时拥有root的uid和gid(作为用户进程的euid和egid),以便于进行运作。
④ unsigned short fsuid,fsgid;
fsuid 和fsgid称为文件系统的uid和gid,用于文件系统操作时的合法性检查,是Linux独特的标识类型。它们一般分别和euid和egid一致,但在 NFS文件系统中NFS服务器需要作为一个特殊的进程访问文件,这时只修改客户进程的fsuid和fsgid。
⑤unsigned short suid,sgid;
suid和sgid是根据POSIX标准引入的,在系统调用改变uid和gid时,用于保留真正的uid和gid。
⑥ int pid,pgrp,session;
进程标识号、进程的组织号及session标识号,相关系统调用(见程序kernel/sys.c)有sys_setpgid、sys_getpgid、sys_setpgrp、sys_getpgrp、sys_getsid及sys_setsid几种。
⑦ int leader;