概述
文章目录
- 一、fork 函数
- 二、文件共享
一、fork 函数
- 作用: 创建新进程
- 函数原型: pid_t fork(void);
需要包含头文件 <unistd.h> - 返回值:
子进程返回 0
父进程返回子进程 ID
若出错,返回 -1
- fork 函数被调用一次,但返回两次
- 将子进程 ID 返回给父进程的理由是:一个进程的子进程可以有多个,并且没有一个函数使一个进程可以获得其所有子进程的进程 ID
- fork 使子进程得到返回值 0 的理由是:一个进程只会有一个父进程,所以子进程可以通过调用 getppid 函数,来获得其父进程的进程 ID
- 进程 ID 0 总是由内核交换进程使用,所以一个子进程的进程 ID 不可能为 0
- fork 之后进程的动作:子进程和父进程继续执行 fork 调用之后的指令。
- 子进程是父进程的副本。fork 之后,子进程获得父进程数据空间、堆和栈的副本。注意:这是子进程所拥有的副本。父进程和子进程并不共享这些存储空间部分。父进程和子进程共享正文段
- 其实创建子进程,就是把父进程的 PCB 拷贝过来,稍加修改,例如,修改子进程的进程 ID(肯定不能和父进程一样), 就变成子进程的 PCB 了。
- 进程调度:父进程和子进程谁先被执行,完全由进程调度器决定,谁先调度,是不确定的。
- 父进程的很多其他属性都被子进程继承,包括:
- 实际用户 ID 、实际组 ID 、有效用户 ID、有效组 ID
- 附属组 ID
- 进程组 ID
- 回话 ID
- 控制终端
- 设置用户 ID 标志和设置组 ID 标志
- 当前工作目录
- 根目录
- 文件模式创建屏蔽字
- 信号屏蔽和安排
- 对任一打开文件描述符的执行时关闭(close-on-exe) 标志
- 环境
- 连接的共享存储段
- 存储映像
- 资源限制
- 父进程和子进程之间的区别如下。
- fork 的返回值不同
- 进程 ID 不同
- 这两个进程的父进程 ID 不同: 子进程的父进程 ID 是创建它的进程 ID ,而父进程的父进程 ID 不变
- 子进程的 tms_utime、tms_stime、 tms_cutime 和 tms_ustime 的值设置为 0 。 ---- 进程时间
- 子进程不继承父进程设置的文件锁
- 子进程的未处理闹钟被清除
- 子进程的未处理信号设置为空集
- fork 失败的两个主要原因是:
(1) 系统中已经有太多的进程
(2) 该实际用户 ID 的进程总数超过了系统限制,CHILD_MAX 规定了每个实际用户 ID 在任一时刻可拥有的最大进程数。 - fork 的用法
(1) 一个父进程希望复制自己,使父进程和子进程同时执行不同的代码段。
(2) 一个进程要执行不同的程序,在这种情况下,子进程从 fork 返回之后立即调用 exec 系列
二、文件共享
-
在重定向父进程的标准输出时,子进程的标准输出也被重定向,实际上,fork 的一个特性是父进程所有打开的文件描述符都被复制到子进程中。
-
父进程和子进程每个相同的打开描述符共享一个文件表项,见下图:
-
一个进程具有 3 个不同的打开文件,他们是标准输入,标准输出,标准错误。在 fork 返回时,结构如下图:
- 父进程和子进程共享同一个文件偏移量
为啥要共享呢?我们考虑以下情况:
一个进行 fork 子进程,然后等待子进程终止。假定,最为普通处理的一部分,父进程和子进程都向标准输出进行写操作。如果父进程的标准输出已重定向,那么子进程进行写到标准输出时,它将更新与父进程共享的该文件的偏移量。当父进程等待子进程时,子进程写到标准输出;而在子进程终止后,父进程也写到标准输出上,并且知道其输出会追加到子进程所写数据之后。如果父子进程不共享同一文件偏移量,又没有任何形式的同步,当父子进程写同一描述符指向的文件,那么他们的输出就会相互混淆。
- 在 fork 之后处理文件描述符有以下两种常见的情况。
(1) 父进程等待子进程完成,在这种情况下,父进程无需对其描述符做任何处理。当子进程终止后,它曾进行过读、写操作的任一共享描述符的偏移量已做了相应更新。
(2) 父进程和子进程各自执行不同的程序段,在这种情况下,在 fork 之后,父进程和子进程各自关闭他们不需使用的文件描述符,这样就不会干扰对方使用的文件描述符。
最后
以上就是沉默玉米为你收集整理的Linux 进程控制 ---- fork 函数的全部内容,希望文章能够帮你解决Linux 进程控制 ---- fork 函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复