目录
进程创建
fork函数知识
#include <unistd.h>
pid_t fork(void);
返回值:自进程中返回0,父进程返回子进程id,出错返回-1
进程调用fork,当控制转移到内核中的fork代码后,内核做:
- 分配新的内存块和内核数据结构给子进程。
- 将父进程部分数据结构内容拷贝至子进程。
- 添加子进程到系统进程列表当中。
- fork返回,开始调度器调度。

运行结果如下:

所以,fork之前父进程独立执行,fork之后,父子两个执行流分别执行。注意: fork之后,父进程和子进程谁先执行完全由调度器决定。
fork函数返回值
- 父进程:
fork
函数返回子进程的进程ID(PID)。 - 子进程:
fork
函数返回0。 - 错误:
fork
函数返回-1,并设置errno
以指示错误。
具体来说:
- 如果
fork
成功,系统会在父进程和子进程中分别返回不同的值。- 在父进程中,
fork
返回子进程的 PID,这是一个正整数。 - 在子进程中,
fork
返回 0。
- 在父进程中,
- 如果
fork
失败,则返回 -1,并且不会创建子进程。这通常是由于系统资源不足或达到进程限制等原因引起的。在这种情况下,可以使用perror
或strerror
函数输出错误信息。
fork函数为什么要给子进程返回0,给父进程返回子进程的PID?
一个父进程可以创建多个子进程,而一个子进程只能有一个父进程。因此,对于子进程来说,父进程是不需要被标识的;而对于父进程来说,子进程是需要被标识的,因为父进程创建子进程的目的是让其执行任务的,父进程只有知道了子进程的PID才能很好的对该子进程指派任务。
为什么fork函数有两个返回值?
父进程调用fork函数后,为了创建子进程,fork函数内部将会进行一系列操作,包括创建子进程的进程控制块、创建子进程的进程地址空间、创建子进程对应的页表等等。子进程创建完毕后,操作系统还需要将子进程的进程控制块添加到系统进程列表当中,此时子进程便创建完毕了。
也就是说,在fork函数内部执行return语句之前,子进程就已经创建完毕了,那么之后的return语句不仅父进程需要执行,子进程也同样需要执行,这就是fork函数有两个返回值的原因。
写时拷贝
写时拷贝(Copy-On-Write, COW)是一种优化技术,用于延迟或避免对共享资源的实际复制,直到需要对其进行修改时才执行复制操作。这种技术在进程创建和内存管理中非常常用,尤其是在操作系统实现 fork
函数时。
fork
与写时拷贝
当一个进程调用 fork
创建子进程时,操作系统会创建一个几乎完全相同的进程副本。这包括进程的地址空间、文件描述符等资源。使用写时拷贝技术,父进程和子进程最初共享同一块内存,而不是立即复制所有内存内容。只有在其中一个进程试图修改内存时,系统才会将相应的内存页复制,从而确保每个进程都有自己的内存副本。
这种方法极大地提高了 fork
的效率,尤其是在创建后不久就执行 exec
(执行新程序)的场景,因为在这种情况下几乎不需要复制任何内存。
当子进程刚刚被创建时,子进程和父进程的数据和代码是共享的,即父子进程的代码和数据通过页表映射到物理内