内核程序通过进程表对进程进行管理,每个进程在进程表中占有一项。在Linux 系统中,进程表项是一个task_struct 任务结构指针。任务数据结构定义在头文件include/linux/sched.h 中。有些书上称其为进程控制块PCB(Process Control Block)或进程描述符PD(Processor Descriptor)。其中保存着用于控制和管理进程的所有信息。主要包括进程当前运行的状态信息、信号、进程号、父进程号、运行时间累计值、正在使用的文件和本任务的局部描述符以及任务状态段信息。该结构每个字段的具体含义如下所示
struct task_struct {
long state; //任务的运行状态(-1 不可运行,0 可运行(就绪),>0 已停止)
long counter; //任务运行时间计数(递减)(滴答数),运行时间片。
long priority; //运行优先数。任务开始运行时counter=priority,越大运行越长。
long signal; //信号。是位图,每个比特位代表一种信号,信号值=位偏移值+1。
struct sigaction ;
struct sigaction[32]; //记录每个信号的安装的信号处理函数的数组,具体作用参见sys_signal()或sys_sigaction(),http://blog.youkuaiyun.com/r21nn/article/details/64128764;
long blocked; // 进程信号屏蔽码(对应信号位图)。
int exit_code; // 任务执行停止的退出码,其父进程会取
unsigned long start_code; //代码段地址。
unsigned long end_code; //代码长度(字节数)
unsigned long end_data; //代码长度 + 数据长度(字节数)
unsigned long brk; //总长度(字节数)
unsigned long start_stack; //堆栈段地址。 long pid; //进程标识号(进程号)。
long father; //父进程号。
long pgrp; //父进程组号。
long session; //会话号。
long leader; //会话首领
unsigned short uid; //用户标识号(用户id)
unsigned short euid; //有效用户id。
unsigned short suid; //保存的用户id。
unsigned short gid; //组标识号(组id)
unsigned short egid; //有效组id
unsigned short sgid; //保存的组id
long alarm; //报警定时值(滴答数)
long utime; //用户态运行时间(滴答数)
long stime; //系统态运行时间(滴答数)
long cutime; //子进程用户态运行时间。
long cstime; //子进程系统态运行时间
long start_time; //进程开始运行时刻。
unsigned short used_math; //标志:是否使用了协处理器。
int tty; //进程使用tty 的子设备号。-1 表示没有使用
unsigned short umask; //文件创建属性屏蔽位。
struct m_inode * pwd; //当前工作目录i 节点结构。
struct m_inode * root; //根目录i 节点结构。
struct m_inode * executable;//执行文件i 节点结构
unsigned long close_on_exec;//执行时关闭文件句柄位图标志
struct file * filp[NR_OPEN];//文件结构指针表,最多32 项。表项号即是文件描述符的值
struct desc_struct ldt[3]; //任务局部描述符表。0-空,1-代码段cs,2-数据和堆栈段ds& ss struct tss_
struct tss; //进程的任务状态段信息结构
};
当一个进程在执行时,CPU 的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。当内核需要切换(switch)至另一个进程时,它就需要保存当前进程的所有状态,也即保存当前进程的上下文,以便在再次执行该进程时,能够恢复到切换时的状态执行下去。在Linux 中,当前进程上下文均保存在进程的任务数据结构中。在发生中断时,内核就在被中断进程的上下文中,在内核态下执行中断服务例程。但同时会保留所有需要用到的资源,以便中断服务结束时能恢复被中断进程的执行。