进程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
原文地址:https://www.cnblogs.com/likong/p/10466790.html