Kernel中进程的管理和调度
进程ID的类型
内核中的进程ID类型用pid_type来描述,定义在include/linux/pid.h
1 | enum pid_type |
pid内核中唯一区分每个进程的标识,在使用fork或clone系统调用时产生一个新的进程时,均会由内核分配一个新的唯一PID值。
用户空间通过getpid()获取的进程号并不是这个PID值
TGID线程组(轻量级进程)的标识。如果以CLONE_THREAD标志来调用clone建立一个进程,就是该进程的一个线程,它们属于一个线程组。线程组的ID,就是TGID。线程组的主线程TGID与PID相同。
PGID,独立的进程可以组成进程组(setpgrp系统调用),进程组可以简化组内进程发送信号的操作。如管道连接的进程处在同一个进程组内,进程组的ID就叫PGID。
SID,几个进程可以合并成一个会话组(setsid调用),可用于终端程序设计。会话组中所有进程都有相同的SID,保存在task_struct的session成员中。
task_ struct->signal->__session表示全局SID,
而全局PGID则保存在task_struct->signal->__pgrp。
辅助函数set_task_session和set_task_pgrp可用于修改这些值。
PID命名空间
pid_namespace定义在include/linux/pid_namespace.h中:
1 | struct pid_namespace { |
child_reaper:指向的是当前命名空间的init进程,每个命名空间都有一个作用相当于全局init进程的进程level:代表当前命名空间的等级,初始命名空间的level为0,它的子命名空间level为1,依次递增,而且子命名空间对父命名空间是可见的。从给定的level设置,内核即可推断进程会关联到多少个ID。parent:指向父命名空间的指针
PID结构
pid与upid
pid是内核对pid的内部表示。upid表示特定的命名空间中可见的信息。
upid定义如下:
1 | struct upid { |
nr:ID具体的值ns:执行命名空间的指针
所有的upid都会保存在一个散列表中
pid定义如下:
1 | struct pid |
count:指使用该PID的task的数目;level:可以看到该PID的命名空间的数目,也就是包含该进程的命名空间的深度。tasks[PIDTYPE_MAX]:每个数组项都是一个散列表头,分别对应三种类型:PIDTYPE_PID,PIDTYPE_PGID,PIDTYPE_SID(PIDTYPE_MAX表示PID类型的数目)。所有共享同一给定的ID的task实例,都通过该散列表连接起来。numbers[1]:一个upid的实例数组,每个数组项代表一个命名空间,用来表示一个PID可以属于不同的命名空间,该元素放在末尾,可以向数组添加附加的项。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ansore!



