怎样 detach 子进程
通过 fork
创建进程后,父进程可以使用 waitpid
来获取子进程的结束状态。
如果子进程先于父进程退出,而父进程没有调用 waitpid 的话,子进程将一直存续下去以保持结束状态可以被获取。
此时,子进程被称为僵尸进程。
如果子进程没有被调用 waitpid
而父进程退出了,此时子进程被称为孤儿进程,它会被 init进程(PID为1) 领养并调用waitpid
回收。
有时我们并不关心子进程的结束状态,希望像 pthread_detach
一样示释放子进程。有以下两种方法可以实现:
- 父进程调用
fork
创建子进程A并对其调用waitpid
,子进程A再次fork
创建子进程B并退出。
这样一来,子进程A 由父进程回收,子进程B 成为孤儿进程被init进程回收。
- 父进程调用
signal(SIGCHLD, SIG_IGN)
SIGCHLD
是子进程状态发生变化时产生的信号,默认就是忽略的,但是必须显示调用才会释放子进程。
守护进程
上述方法一中创建孤儿进程的方法常被用于创建守护进程。常用步骤如下:
- 调用
fork
创建子进程,然后父进程退出。 - 子调用
setsid
创建新的会话和进程组,从而避免被原先的会话、进程组以及会话终端影响。 - 调用
chdir
设置工作目录。 - 调用
umask
设置文件掩码(通常设为umask(0)
)。 - 关闭不需要的资源(从父进程继承的文件描述符等)。
除第一步外的后续步骤并不是必须的,但大部分情况下是必要的。