• 进程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
  • 相关阅读:
    在Java中,final修饰的类有什么特点
    基于 枚举值 输出 枚举描述的 jackson 自定义注解方法
    基于 r2dbc jpa java reactor流式编程的查询合并
    分组后 排除存在某种情况的 的查询
    基于Mysql 根据输入值 为基础的 环形排序
    时间范围内的按时间统计的每日数据填充
    记一次vue发版,在nginx下不乱码,在IIS下乱码的奇葩经历
    处理webflux 项目 增加 content-path
    java stream 不执行转换 不执行 管道中的操作
    增加一个spring mvc 的枚举转换器
  • 原文地址:https://www.cnblogs.com/likong/p/10466790.html
Copyright © 2020-2023  润新知