Skip to content

Latest commit

 

History

History
66 lines (46 loc) · 4.76 KB

2014-04-09-process-relationship.md

File metadata and controls

66 lines (46 loc) · 4.76 KB
layout title category description tags
post
进程之间的关系
进程
进程之间的关系...
父进程 子进程 写时复制 fork vfork pidhash

进程之间除了ID连接的关系之外,内核还负责管理建立在UNIX进程创建模型之上的『家族关系』。

system 进程之间的关系

如果进程A分支形成进程B,进程A称之为父进程,而进程B称之为子进程。如果进程A分支若干次形成几个子进程B、C、D,则这几个子进程之间称为兄弟关系。

下面简单的列举了进程描述符中相关亲属关系的描述,进程描述符结构可以看《进程描述符》,进程数据结构可以看《进程链表》

字段名 说明
real_parent 指向创建了P的进程描述符,如果P的父进程不存在,就指向进程init的描述符
parent 指向P的当前父进程,当此进程终止时,必须向父进程发信号
children 链表的头部,链表中的所有元素都是P创建的子进程
sibling 指向兄弟进程链表中的下一个元素或前一个元素的指针,这些兄弟进程的父进程都是P

建立非亲属关系的进程描述符字段有:

字段名 说明
group_leader P所在进程组的组长的描述符指针
signal->pgrp P所在进程组的组长的PID
tgid P所在线程组的组长的PID
signal->session P的登录会话组长的PID
ptrace_children 链表的头,该聊表包含所有被debugger程序跟踪的P的子进程
ptrace_list 指向锁跟踪进程的实际父进程链表的前一个和下一个元素

pidhash表及链表

系统调用提供服务的时候会发生如下情况,当进程P1希望向另一个进程P2发送一个信号时,P1调用kill()系统调用,其参数为P2的PID,内核从这个PID导出其对应的进程描述符,然后从P2的进程描述符中取出记录挂起信号的数据结构指针。顺序扫描进程描述符的pid字段是相当低效的,为了加速查找,引入了4个散列表,分别为:

Hash表的类型 说明
PIDTYPE_PID 进程的PID
PIDYTPE_TGID 进程组的组长的PID
PIDTYPE_PGID 进程组的组长的PID
PIDTYPE_SID 会话组长的PID

内核初始化期间动态地为4个散列表分配空间,并把它们的地址存入pid_hash数据组,一个散列表的长度依赖于可用的RAM的容量。用pid_hashfn把PID转换为表索引。pid_hash函数并不一定能保证与表的索引一一对应,不同的PID可能会存在相同的key,就会发生冲突。Linux利用链表来处理冲突。

进程复制

传统的UNIX中用于复制进程的系统调用是fork,但它并不是Linux为此实现的唯一调用,Linux实现了3个。

(1) fork是重量级调用,因为它建立了父进程的一个完整副本,然后作为子进程。

(2) vfork1类似于fork,但并不创建父进程数据的副本,相反,父子进程共享数据,节省了大量的CPU。vfork设计用于子进程形成后立即执行execve系统调用,在子进程退出或开始新程序之前,父进程处于堵塞状态。

(3) clone用于产生线程,可以堆父子进程之间的共享、复制进行精确控制。

所有的3个fork机制最终都调用了kernel/fork.c中的do_fork函数,在do_fork中,大多数工作都是由copy_process函数完成的。

写时复制

内核使用了写时复制(Copy-On-Write, COW)技术,为防止在fork执行时将父进程的所有数据复制到子进程。因为这样的操作使用的很长的时间,并且耗费了大量的内存。如果应用程序在进程复制之后使用exec立即加载新程序,那么就表明之前的操作完全时没有必要的,因为拷贝了父进程的数据,但立即刷出内存用于新程序。所以内核不复制进程的整个地址空间,而是只复制其页表,这样就建立了虚拟地址空间和物理内存页之间的联系。

当父子进程不允许修改彼此的页,只能够共享的读取数据,则可以共享内存区域。如果任意一个进程试图向复制的内存页中写入数据,那么处理器会向内核报告访问错误,这类错误通常会被视作缺页异常。内核然后查看额外的内存管理数据结构,检查该页是否可以用读写模式访问。如果该页只能以只读模式访问,则向应用程序报告段错误,如果是可写的,内核会创建该页专用于当前进程的副本,并与父进程独立开。

Footnotes

  1. 由于写时复制技术,现在不推荐使用vfork。