进程PCB
1 struct task_struct { 2 volatile long state; //说明了该进程是否可以执行,还是可中断等信息 3 unsigned long flags; //Flage 是进程号,在调用fork()时给出 4 intsigpending; //进程上是否有待处理的信号 5 mm_segment_taddr_limit; //进程地址空间,区分内核进程与普通进程在内存存放的位置不同 6 //0-0xBFFFFFFF foruser-thead 7 //0-0xFFFFFFFF forkernel-thread 8 //调度标志,表示该进程是否需要重新调度,若非0,则当从内核态返回到用户态,会发生调度 9 volatilelong need_resched; 10 int lock_depth; //锁深度 11 longnice; //进程的基本时间片 12 //进程的调度策略,有三种,实时进程:SCHED_FIFO 1 先进先出,SCHED_RR 2 基于优先权的轮转法,分时进程:SCHED_OTHER 0 用基于优先权的轮转法 13 unsigned long policy; 14 struct mm_struct *mm; //进程内存管理信息 15 int processor; 16 //若进程不在任何CPU上运行, cpus_runnable 的值是0,否则是1这个值在运行队列被锁时更新 17 unsigned long cpus_runnable, cpus_allowed; 18 struct list_head run_list; //指向运行队列的指针 19 unsigned longsleep_time; //进程的睡眠时间 20 //用于将系统中所有的进程连成一个双向循环链表,其根是init_task 21 struct task_struct *next_task, *prev_task; 22 struct mm_struct *active_mm; 23 struct list_headlocal_pages; //指向本地页面 24 unsigned int allocation_order, nr_local_pages; 25 struct linux_binfmt *binfmt; //进程所运行的可执行文件的格式 26 int exit_code, exit_signal; 27 intpdeath_signal; //父进程终止是向子进程发送的信号 28 unsigned longpersonality; 29 //Linux可以运行由其他UNIX操作系统生成的符合iBCS2标准的程序 30 intdid_exec:1; 31 pid_tpid; //进程标识符,用来代表一个进程 32 pid_tpgrp; //进程组标识,表示进程所属的进程组 33 pid_t tty_old_pgrp; //进程控制终端所在的组标识 34 pid_tsession; //进程的会话标识 35 pid_t tgid; 36 intleader; //表示进程是否为会话主管 37 struct task_struct*p_opptr,*p_pptr,*p_cptr,*p_ysptr,*p_osptr; 38 struct list_head thread_group; //线程链表 39 struct task_struct*pidhash_next; //用于将进程链入HASH表 40 struct task_struct**pidhash_pprev; 41 wait_queue_head_t wait_chldexit; //供wait4()使用 42 struct completion*vfork_done; //供vfork()使用 43 unsigned long rt_priority; //实时优先级,用它计算实时进程调度时的weight值 44 45 //it_real_value,it_real_incr用于REAL定时器,单位为jiffies,系统根据it_real_value 46 //设置定时器的第一个终止时间.在定时器到期时,向进程发送SIGALRM信号,同时根据 47 //it_real_incr重置终止时间,it_prof_value,it_prof_incr用于Profile定时器,单位为jiffies。 48 //当进程运行时,不管在何种状态下,每个tick都使it_prof_value值减一,当减到0时,向进程发送 49 //信号SIGPROF,并根据it_prof_incr重置时间. 50 //it_virt_value,it_virt_value用于Virtual定时器,单位为jiffies。当进程运行时,不管在何种 51 //状态下,每个tick都使it_virt_value值减一当减到0时,向进程发送信号SIGVTALRM,根据 52 //it_virt_incr重置初值。 53 unsigned long it_real_value, it_prof_value, it_virt_value; 54 unsigned long it_real_incr, it_prof_incr, it_virt_value; 55 struct timer_listreal_timer; //指向实时定时器的指针 56 struct tmstimes; //记录进程消耗的时间 57 unsigned longstart_time; //进程创建的时间 58 //记录进程在每个CPU上所消耗的用户态时间和核心态时间 59 longper_cpu_utime[NR_CPUS],per_cpu_stime[NR_CPUS]; 60 //内存缺页和交换信息: 61 //min_flt, maj_flt累计进程的次缺页数(Copyon Write页和匿名页)和主缺页数(从映射文件或交换 62 //设备读入的页面数);nswap记录进程累计换出的页面数,即写到交换设备上的页面数。 63 //cmin_flt, cmaj_flt,cnswap记录本进程为祖先的所有子孙进程的累计次缺页数,主缺页数和换出页面数。 64 //在父进程回收终止的子进程时,父进程会将子进程的这些信息累计到自己结构的这些域中 65 unsignedlong min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap; 66 int swappable:1; //表示进程的虚拟地址空间是否允许换出 67 //进程认证信息 68 //uid,gid为运行该进程的用户的用户标识符和组标识符,通常是进程创建者的uid,gid 69 //euid,egid为有效uid,gid 70 //fsuid,fsgid为文件系统uid,gid,这两个ID号通常与有效uid,gid相等,在检查对于文件 71 //系统的访问权限时使用他们。 72 //suid,sgid为备份uid,gid 73 uid_t uid,euid,suid,fsuid; 74 gid_t gid,egid,sgid,fsgid; 75 int ngroups; //记录进程在多少个用户组中 76 gid_t groups[NGROUPS]; //记录进程所在的组 77 //进程的权能,分别是有效位集合,继承位集合,允许位集合 78 kernel_cap_tcap_effective, cap_inheritable, cap_permitted; 79 int keep_capabilities:1; 80 struct user_struct *user; 81 struct rlimit rlim[RLIM_NLIMITS]; //与进程相关的资源限制信息 82 unsigned shortused_math; //是否使用FPU 83 charcomm[16]; //进程正在运行的可执行文件名 84 //文件系统信息 85 int link_count, total_link_count; 86 //NULL if no tty进程所在的控制终端,如果不需要控制终端,则该指针为空 87 struct tty_struct*tty; 88 unsigned int locks; 89 //进程间通信信息 90 struct sem_undo*semundo; //进程在信号灯上的所有undo操作 91 struct sem_queue *semsleeping; //当进程因为信号灯操作而挂起时,他在该队列中记录等待的操作 92 //进程的CPU状态,切换时,要保存到停止进程的task_struct中 93 structthread_struct thread; 94 //文件系统信息 95 struct fs_struct *fs; 96 //打开文件信息 97 struct files_struct *files; 98 //信号处理函数 99 spinlock_t sigmask_lock; 100 struct signal_struct *sig; //信号处理函数 101 sigset_t blocked; //进程当前要阻塞的信号,每个信号对应一位 102 struct sigpendingpending; //进程上是否有待处理的信号 103 unsigned long sas_ss_sp; 104 size_t sas_ss_size; 105 int (*notifier)(void *priv); 106 void *notifier_data; 107 sigset_t *notifier_mask; 108 u32 parent_exec_id; 109 u32 self_exec_id; 110 111 spinlock_t alloc_lock; 112 void *journal_info; 113 };
1 struct task_struct 2 { 3 volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ 4 /* 5 表示进程的当前状态: 6 TASK_RUNNING:正在运行或在就绪队列run-queue中准备运行的进程,实际参与进程调度。 7 TASK_INTERRUPTIBLE:处于等待队列中的进程,待资源有效时唤醒,也可由其它进程通过信号(signal)或定时中断唤醒后进入就绪队列run-queue。 8 TASK_UNINTERRUPTIBLE:处于等待队列中的进程,待资源有效时唤醒,不可由其它进程通过信号(signal)或定时中断唤醒。 9 TASK_ZOMBIE:表示进程结束但尚未消亡的一种状态(僵死状态)。此时,进程已经结束运行且释放大部分资源,但尚未释放进程控制块。 10 TASK_STOPPED:进程被暂停,通过其它进程的信号才能唤醒。导致这种状态的原因有二,或者是对收到SIGSTOP、SIGSTP、SIGTTIN或SIGTTOU信号的反应,或者是受其它进程的ptrace系统调用的控制而暂时将CPU交给控制进程。 11 TASK_SWAPPING: 进程页面被交换出内存的进程。 12 */ 13 unsigned long flags; //进程标志,与管理有关,在调用fork()时给出 14 int sigpending; //进程上是否有待处理的信号 15 mm_segment_t addr_limit; //进程地址空间,区分内核进程与普通进程在内存存放的位置不同 16 /*用户线程空间地址: 0..0xBFFFFFFF。 17 内核线程空间地址: 0..0xFFFFFFFF */ 18 19 struct exec_domain *exec_domain; //进程执行域 20 volatile long need_resched; //调度标志,表示该进程是否需要重新调度,若非0,则当从内核态返回到用户态,会发生调度 21 unsigned long ptrace; 22 int lock_depth; //锁深度 23 long counter; //进程的基本时间片,在轮转法调度时表示进程当前还可运行多久,在进程开始运行是被赋为priority的值,以后每隔一个tick(时钟中断)递减1,减到0时引起新一轮调 度。重新调度将从run_queue队列选出counter值最大的就绪进程并给予CPU使用权,因此counter起到了进程的动态优先级的作用 24 long nice; //静态优先级 25 unsigned long policy; //进程的调度策略,有三种,实时进程:SCHED_FIFO,SCHED_RR,分时进程:SCHED_OTHER 26 //在Linux 中, 采用按需分页的策略解决进程的内存需求。task_struct的数据成员mm 指向关于存储管理的mm_struct结构。 27 struct mm_struct *mm; //进程内存管理信息 28 int has_cpu, processor; 29 unsigned long cpus_allowed; 30 struct list_head run_list; //指向运行队列的指针 31 unsigned long sleep_time; //进程的睡眠时间 32 //用于将系统中所有的进程连成一个双向循环链表,其根是init_task 33 //在Linux 中所有进程(以PCB 的形式)组成一个双向链表,next_task和prev_task是链表的前后向指针 34 struct task_struct *next_task, *prev_task; 35 struct mm_struct *active_mm; //active_mm 指向活动地址空间。 36 struct linux_binfmt *binfmt; //进程所运行的可执行文件的格式 37 int exit_code, exit_signal; 38 int pdeath_signal; //父进程终止是向子进程发送的信号 39 unsigned long personality; 40 int dumpable:1; 41 int did_exec:1; 42 pid_t pid; //进程标识符,用来代表一个进程 43 pid_t pgrp; //进程组标识,表示进程所属的进程组 44 pid_t tty_old_pgrp; //进程控制终端所在的组标识 45 pid_t session; //进程的会话标识 46 pid_t tgid; 47 int leader; //表示进程是否为会话主管 48 <br> //指向最原始的进程任务指针,父进程任务指针,子进程任务指针,新兄弟进程任务指针,旧兄弟进程任务指针。 49 struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr; 50 struct list_head thread_group; //线程链表 51 <br> //用于将进程链入HASH表,系统进程除了链入双向链表外,还被加入到hash表中 52 struct task_struct *pidhash_next; 53 struct task_struct **pidhash_pprev; 54 wait_queue_head_t wait_chldexit; //供wait4()使用 55 struct semaphore *vfork_sem; //供vfork()使用 56 unsigned long rt_priority; //实时优先级,用它计算实时进程调度时的weight值 57 <br> //it_real_value,it_real_incr用于REAL定时器,单位为jiffies,系统根据it_real_value 58 //设置定时器的第一个终止时间.在定时器到期时,向进程发送SIGALRM信号,同时根据 59 //it_real_incr重置终止时间,it_prof_value,it_prof_incr用于Profile定时器,单位为jiffies。 60 //当进程运行时,不管在何种状态下,每个tick都使it_prof_value值减一,当减到0时,向进程发送信号SIGPROF,并根据it_prof_incr重置时间. 61 //it_virt_value,it_virt_value用于Virtual定时器,单位为jiffies。当进程运行时,不管在何种 62 //状态下,每个tick都使it_virt_value值减一当减到0时,向进程发送信号SIGVTALRM,根据it_virt_incr重置初值 63 unsigned long it_real_value, it_prof_value, it_virt_value; 64 unsigned long it_real_incr, it_prof_incr, it_virt_incr; 65 struct timer_list real_timer; //指向实时定时器的指针 66 struct tms times; //记录进程消耗的时间 67 unsigned long start_time; //进程创建的时间 68 long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];//记录进程在每个CPU上所消耗的用户态时间和核心态时间 69 //内存缺页和交换信息: 70 //min_flt, maj_flt累计进程的次缺页数(Copyon Write页和匿名页)和主缺页数(从映射文件或交换 71 //设备读入的页面数);nswap记录进程累计换出的页面数,即写到交换设备上的页面数。 72 //cmin_flt, cmaj_flt,cnswap记录本进程为祖先的所有子孙进程的累计次缺页数,主缺页数和换出页面数。 73 //在父进程回收终止的子进程时,父进程会将子进程的这些信息累计到自己结构的这些域中 74 unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap; 75 int swappable:1; //表示进程的虚拟地址空间是否允许换出 76 //进程认证信息 77 //uid,gid为运行该进程的用户的用户标识符和组标识符,通常是进程创建者的uid,gid,euid,egid为有效uid,gid 78 //fsuid,fsgid为文件系统uid,gid,这两个ID号通常与有效uid,gid相等,在检查对于文件系统的访问权限时使用他们。 79 //suid,sgid为备份uid,gid 80 uid_t uid,euid,suid,fsuid; 81 gid_t gid,egid,sgid,fsgid; 82 int ngroups; //记录进程在多少个用户组中 83 gid_t groups[NGROUPS]; //记录进程所在的组 84 kernel_cap_t cap_effective, cap_inheritable, cap_permitted;//进程的权能,分别是有效位集合,继承位集合,允许位集合 85 int keep_capabilities:1; 86 struct user_struct *user; //代表进程所属的用户 87 struct rlimit rlim[RLIM_NLIMITS]; //与进程相关的资源限制信息 88 unsigned short used_math; //是否使用FPU 89 char comm[16]; //进程正在运行的可执行文件名 90 //文件系统信息 91 int link_count; 92 struct tty_struct *tty; //进程所在的控制终端,如果不需要控制终端,则该指针为空 93 unsigned int locks; /* How many file locks are being held */ 94 //进程间通信信息 95 struct sem_undo *semundo; //进程在信号量上的所有undo操作 96 struct sem_queue *semsleeping; //当进程因为信号量操作而挂起时,他在该队列中记录等待的操作 97 struct thread_struct thread; //进程的CPU状态,切换时,要保存到停止进程的task_struct中 98 struct fs_struct *fs; //文件系统信息,fs保存了进程本身与VFS(虚拟文件系统)的关系信息 99 struct files_struct *files; //打开文件信息 100 //信号处理函数 101 spinlock_t sigmask_lock; /* Protects signal and blocked */ 102 struct signal_struct *sig; //信号处理函数 103 sigset_t blocked; //进程当前要阻塞的信号,每个信号对应一位 104 struct sigpending pending; //进程上是否有待处理的信号 105 unsigned long sas_ss_sp; 106 size_t sas_ss_size; 107 int (*notifier)(void *priv); 108 void *notifier_data; 109 sigset_t *notifier_mask; 110 /* Thread group tracking */ 111 u32 parent_exec_id; 112 u32 self_exec_id; 113 spinlock_t alloc_lock; //用于申请空间时用的自旋锁。自旋锁的主要功能是临界区保护 114 115 };
进程PCB的组织方式:线性表、索引表、链接表
二,进程控制块(PCB)
进程控制块包括:
进程描述信息:
- 进程标识符用于唯一的标识一个进程(pid,ppid)。
进程控制信息:
- 进程当前状态
- 进程优先级
- 程序开始地址
- 各种计时信息
- 通信信息
资源信息:
- 占用内存大小及管理用数据结构指针
- 交换区相关信息
- I/O设备号、缓冲、设备相关的数结构
- 文件系统相关指针
现场保护信息(cpu进行进程切换时):
- 寄存器
- PC
- 程序状态字PSW
- 栈指针
进程标识:PID
- 每个进程都会分配到一个独一无二的数字编号,我们称之为“进程标识”(process identifier),或者就直接叫它PID.
- 是一个正整数,取值范围从2到32768
可以通过:cat /proc/sys/kernel/pid_max 查看系统支持多少进程
- 当一个进程被启动时,它会顺序挑选下一个未使用的编号数字做为自己的PID
- 数字1一般为特殊进程init保留的
init进程实际上是用户进程,它是一个程序,在/sbin/init,linux启动的第一个进程
实际上linux中还存在0号进程(内核进程),它是一个空闲进程,它进行空闲资源的统计及交换空间的换入换出,1(init)进程是由0号进程创建的。
三,进程创建
- 不同的操作系统所提供的进程创建原语的名称和格式不尽相同,但执行创建进程原语后,操作系统所做的工作却大致相同,都包括以下几点:
- 给新创建的进程分配一个内部标识(pcb),在内核中建立进程结构。
- 复制父进程的环境
- 为进程分配资源, 包括进程映像所需要的所有元素(程序、数据、用户栈等),
- 复制父进程地址空间的内容到该进程地址空间中。
- 置该进程的状态为就绪,插入就绪队列。
四,进程撤销
进程终止时操作系统做以下工作:
- 关闭软中断:因为进程即将终止而不再处理任何软中断信号;
- 回收资源:释放进程分配的所有资源,如关闭所有已打开文件,释放进程相应的数据结构等;
- 写记帐信息:将进程在运行过程中所产生的记帐数据(其中包括进程运行时的各种统计信息)记录到一个全局记帐文件中;
- 置该进程为僵死状态:向父进程发送子进程死的软中断信号,将终止信息status送到指定的存储单元中;
- 转进程调度:因为此时CPU已经被释放,需要由进程调度进行CPU再分配。
五,终止进程的五种方法
- 从main函数返回:从return返回,执行完毕退出
- 调用exit:C函数库,实际上也是调用系统调用_exit完成的,在任何一个函数调用exit函数都可使得进程撤销
- 调用_exit:系统调用
- 调用abort:调用abort()函数使得进程终止,实际上该函数是产生一个SIGABRT信号,
- 由信号终止:发送一些信号如SINGINT等信号
Talk is cheap,show me your code