1. 进程创建
在 Linux 中,fork 函数用于从已存在进程中创建一个新进程。新进程为子进程,原进程为父进程。
#include <unistd.h>
pid_t fork(void);
返回值:子进程中返回 0,父进程返回子进程 ID,出错返回 -1。
进程调用 fork 时内核进行以下操作:
- 分配新的内存块和内核数据结构给子进程
- 将父进程部分数据结构内容拷贝至子进程
- 添加子进程到系统进程列表当中
fork返回,开始调度器调度
1.1 fork 的返回值
- 子进程的返回为 0
- 父进程的返回值是对应子进程的 PID
1.2 写时拷贝 (Copy-On-Write)
通常父子代码共享,父子再不写入时,数据也是共享的。当任意一方试图写入,便以写时拷贝的方式各自一份副本。这保持了父子进程的独立性,提高了进程创建效率并减少了内存浪费。
1.3 fork 的常规用法
- 一个父进程希望复制自己,使父子进程同时执行不同的代码段(例如父进程等待客户端请求,生成子进程处理)。
- 一个进程要执行一个不同的程序(子进程从
fork返回后,调用exec函数)。
1.4 fork 调用失败的原因
- 系统中有太多的进程
- 实际用户的进程数超过了限制
2. 进程终止
进程退出主要有三种情况:代码运行完毕结果正确、代码运行完毕结果不正确、代码异常终止。
在 Linux 中,main 函数的返回值通过 _start 函数传递给操作系统。main 函数的返回值通常表明程序的执行情况。
2.1 退出码
退出码(退出状态)表示最后一次执行的命令的状态。程序返回退出代码 0 时表示执行成功,1 或 0 以外的任何代码都被视为不成功。当进程出现异常终止时,其退出码无意义。
在 Linux 中打印最近一个进程的退出码可使用指令:
echo $?
除了使用 return,还可以使用 exit 设置对应进程的退出码。在任何地方调用 exit 都会让对应的进程退出,并将退出码返回给父进程。
2.2 exit 与_exit
exit 是 C 语言提供的函数,而 _exit 是系统调用。
区别:
exit退出时会刷新缓冲区。_exit退出时不会刷新缓冲区。
示例:
#include <stdio.h>
{
();
sleep();
_exit();
;
}


