Linux 进程控制 ---- fork 函数

文章目录

        • 一、fork 函数
        • 二、文件共享

一、fork 函数

  1. 作用: 创建新进程
  2. 函数原型: pid_t fork(void);
    需要包含头文件
  3. 返回值:
    子进程返回 0
    父进程返回子进程 ID
    若出错,返回 -1
  1. fork 函数被调用一次,但返回两次
  2. 将子进程 ID 返回给父进程的理由是:一个进程的子进程可以有多个,并且没有一个函数使一个进程可以获得其所有子进程的进程 ID
  3. fork 使子进程得到返回值 0 的理由是:一个进程只会有一个父进程,所以子进程可以通过调用 getppid 函数,来获得其父进程的进程 ID
  4. 进程 ID 0 总是由内核交换进程使用,所以一个子进程的进程 ID 不可能为 0
  5. fork 之后进程的动作:子进程和父进程继续执行 fork 调用之后的指令。
  6. 子进程是父进程的副本。fork 之后,子进程获得父进程数据空间、堆和栈的副本。注意:这是子进程所拥有的副本。父进程和子进程并不共享这些存储空间部分。父进程和子进程共享正文段
  7. 其实创建子进程,就是把父进程的 PCB 拷贝过来,稍加修改,例如,修改子进程的进程 ID(肯定不能和父进程一样), 就变成子进程的 PCB 了。
  8. 进程调度:父进程和子进程谁先被执行,完全由进程调度器决定,谁先调度,是不确定的。
  1. 父进程的很多其他属性都被子进程继承,包括:
  • 实际用户 ID 、实际组 ID 、有效用户 ID、有效组 ID
  • 附属组 ID
  • 进程组 ID
  • 回话 ID
  • 控制终端
  • 设置用户 ID 标志和设置组 ID 标志
  • 当前工作目录
  • 根目录
  • 文件模式创建屏蔽字
  • 信号屏蔽和安排
  • 对任一打开文件描述符的执行时关闭(close-on-exe) 标志
  • 环境
  • 连接的共享存储段
  • 存储映像
  • 资源限制
  1. 父进程和子进程之间的区别如下。
  • fork 的返回值不同
  • 进程 ID 不同
  • 这两个进程的父进程 ID 不同: 子进程的父进程 ID 是创建它的进程 ID ,而父进程的父进程 ID 不变
  • 子进程的 tms_utime、tms_stime、 tms_cutime 和 tms_ustime 的值设置为 0 。 ---- 进程时间
  • 子进程不继承父进程设置的文件锁
  • 子进程的未处理闹钟被清除
  • 子进程的未处理信号设置为空集
  1. fork 失败的两个主要原因是:
    (1) 系统中已经有太多的进程
    (2) 该实际用户 ID 的进程总数超过了系统限制,CHILD_MAX 规定了每个实际用户 ID 在任一时刻可拥有的最大进程数。
  2. fork 的用法
    (1) 一个父进程希望复制自己,使父进程和子进程同时执行不同的代码段。
    (2) 一个进程要执行不同的程序,在这种情况下,子进程从 fork 返回之后立即调用 exec 系列

二、文件共享

  1. 在重定向父进程的标准输出时,子进程的标准输出也被重定向,实际上,fork 的一个特性是父进程所有打开的文件描述符都被复制到子进程中

  2. 父进程和子进程每个相同的打开描述符共享一个文件表项,见下图:Linux 进程控制 ---- fork 函数_第1张图片

  3. 一个进程具有 3 个不同的打开文件,他们是标准输入,标准输出,标准错误。在 fork 返回时,结构如下图:

Linux 进程控制 ---- fork 函数_第2张图片

  1. 父进程和子进程共享同一个文件偏移量

为啥要共享呢?我们考虑以下情况:
一个进行 fork 子进程,然后等待子进程终止。假定,最为普通处理的一部分,父进程和子进程都向标准输出进行写操作。如果父进程的标准输出已重定向,那么子进程进行写到标准输出时,它将更新与父进程共享的该文件的偏移量。当父进程等待子进程时,子进程写到标准输出;而在子进程终止后,父进程也写到标准输出上,并且知道其输出会追加到子进程所写数据之后。如果父子进程不共享同一文件偏移量,又没有任何形式的同步,当父子进程写同一描述符指向的文件,那么他们的输出就会相互混淆。

  1. 在 fork 之后处理文件描述符有以下两种常见的情况。
    (1) 父进程等待子进程完成,在这种情况下,父进程无需对其描述符做任何处理。当子进程终止后,它曾进行过读、写操作的任一共享描述符的偏移量已做了相应更新。
    (2) 父进程和子进程各自执行不同的程序段,在这种情况下,在 fork 之后,父进程和子进程各自关闭他们不需使用的文件描述符,这样就不会干扰对方使用的文件描述符。

你可能感兴趣的:(Linux)