Skip to content
On this page

fork(2)


标签:linux/api  

fork()

用来创建子进程,复制当前进程。

c
#include <unistd.h>
pid_t fork(void);

成功返回 pid 号,给子进程返回 0,失败返回 -1,重置 errno

fork 后父子进程的区别:

  1. pid 和 ppid 都不相同;
  2. fork 的返回值不一样;
  3. 未决信号和文件锁#互斥锁不继承;
  4. 资源利用率清零。

init 进程是所有进程的祖先进程(现在是 systemd),所有的进程都是通过 fork 拷贝而来。

getpid()/getppid()

这个函数可以获取当前进程的 pid。

c
#include <sys/types.h>
#include <unistd.h>

pid_t getpid(void);
pid_t getppid(void);

特殊进程

僵尸子进程

子进程结束,父进程未回收资源的进程。zombie 本身不会占用很多资源,但会占用到 pid 号。zombie 的父进程退出的时候(变成孤儿进程),会由 init 接管,被 init 回收。

例如,用 kill 来杀死子进程。

解决办法:用 wait() 函数

孤儿进程

父进程已经结束,而子进程还在运行。子进程会被 init 进程收养。

休眠进程

sleep 函数可以让程序等待 xxx 秒,此时进程会变成休眠进程。

vfork()

vfork 和 fork 一样,但它复制的子进程内存空间虽然和父进程不一样,但是通过虚拟地址的转换,指向的是和父进程一样的物理内存空间。

这个函数只能保证 _exit(2)exec(3)族函数的成功执行,其他函数的执行结果都是未定义行为。比如,关闭 fd(它是地址),那么父线程会关闭吗?这个行为是不知道的。

如今的 fork 已经支持了写时拷贝技术( copy on write, cow),所以vfork 基本已经弃用。部分系统已经不提供支持,移植性差。

Last updated: