深入Linux内核架构-进程管理和调度(四)

一、进程管理相关的系统调用

讨论 fork 和 exec 函数族(用来用指定的程序替换当前进程的所有内容)系统调用的实现。通常这些调用不是由应用程序直接发出
的,而是通过一个中间层调用,即负责与内核通信的C标准库。

从用户状态切换到核心态的方法,依不同的体系结构而各有不同。用于在这两种状态之间切换的机制,并解释了用户空间和内核空间之间如何交换参数。就目前而言,将内核视为由C标准库使用的“程序库”即可。

1、进程复制

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

(1) fork 是重量级调用,因为fork建立了父进程的一个完整副本,然后作为子进程执行。为减少与该调用相关的工作量,Linux使用写时复制(copy-on-write)技术。

(2) vfork 类似于 fork ,但vfork 并不创建父进程数据的副本。相反,父子进程之间共享数据。这节省了大量CPU时间(如果一个进程操纵共享数据,则另一个会自动注意到)。

vfork 设计用于子进程形成后立即执行 exec 系统调用加载新程序的情形。在子进程退出或开始新程序之前,内核保证父进程处于堵塞状态。由于 fork 使用了写时复制技术, vfork 在速度方面不再有优势,因此应该避免使用 vfork 。

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

2、写时复制

内核使用了写时复制(Copy-On-Write,COW)技术,以防止在 fork 执行时将父进程的所有数据复制到子进程。该技术利用了下述事实:进程通常只使用了其内存页的一小部分。在调用 fork 时,内核通常对父进程的每个内存页,都为子进程创建一个相同的副本。这有两种很不好的负面效应。

(1) 使用了大量内存。

(2) 复制操作耗费很长时间。

如果应用程序在进程复制之后使用 exec 立即加载新程序,那么负面效应会更严重。这实际上意味着,此前进行的复制操作是完全多余的,因为进程地址空间会重新初始化,复制的数据不再需要了。

内核可以使用技巧规避该问题。并不复制进程的整个地址空间,而是只复制其页表。建立了虚拟地址空间和物理内存页之间的联系。因此, fork 之后父子进程的地址空间指向同样的物理内存页。

父子进程不能允许修改彼此的页,这也是两个进程的页表对页标记了只读访问的原因,即使在普通环境下允许写入也是如此。

假如两个进程只能读取其内存页,那么二者之间的数据共享就不是问题,因为不会有修改。

只要一个进程试图向复制的内存页写入,处理器会向内核报告访问错误(此类错误被称作缺页异常)。内核然后查看额外的内存管理数据结构,检查该页是否可以用读写模式访问,还是只能以只读模式访问。如果是后者,则必须向进程报告段错误。缺页异常处理程序的实际实现要复杂得多,因为还必须考虑其他方面的问题,例如换出的页。

如果页表项将一页标记为“只读”,但通常情况下该页应该是可写的,内核可根据此条件来判断该页实际上是COW页。因此内核会创建该页专用于当前进程的副本,也可以用于写操作。

写时复制(COW)机制使得内核可以尽可能延迟内存页的复制,更重要的是,在很多情况下不需要复制。这节省了大量时间。

3、执行系统调用

fork 、 vfork 和 clone 系统调用的入口点分别是 sys_fork 、 sys_vfork 和 sys_clone 函数。其定义依赖于具体的体系结构,因为在用户空间和内核空间之间传递参数的方法因体系结构而异。上述函数的任务是从处理器寄存器中提取由用户空间提供的信息,调用体系结构
无关的 do_fork 函数,后者负责进程复制。该函数的原型如下:

kernel/fork.c

long do_fork(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs,
      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值