Appearance
fork()
用来创建子进程,复制当前进程。
c
#include <unistd.h>
pid_t fork(void);成功返回 pid 号,给子进程返回 0,失败返回 -1,重置 errno
fork 后父子进程的区别:
- pid 和 ppid 都不相同;
- fork 的返回值不一样;
- 未决信号和文件锁#互斥锁不继承;
- 资源利用率清零。
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 基本已经弃用。部分系统已经不提供支持,移植性差。