如何撤销父进程对子进程的权限并切断父子进程关联?
如何在fork后切断父子进程的权限关联
要实现fork后让父进程失去对子进程的控制(比如waitpid不再生效),核心是让子进程脱离原父进程的进程树,成为由系统初始化进程(如init或systemd)接管的孤儿进程,常用实现方式有两种:
1. 双重Fork(Double Fork)
这是最经典的实现方案,步骤如下:
- 父进程第一次
fork出子进程A - 子进程A立即再
fork出孙进程B - 子进程A直接退出,此时孙进程B的父进程会被系统自动设置为初始化进程
- 原父进程无法再通过
waitpid等操作控制孙进程B,因为两者已无父子关联
示例代码片段:
pid_t pid1 = fork(); if (pid1 == 0) { // 子进程A pid_t pid2 = fork(); if (pid2 == 0) { // 孙进程B:执行业务逻辑 execve("/path/to/your/program", argv, envp); _exit(1); // exec失败时退出 } _exit(0); // 子进程A退出,孙进程B成为孤儿 } // 原父进程可等待子进程A退出后继续执行 waitpid(pid1, NULL, 0);
2. 子进程创建新会话(Setsid)
子进程调用setsid()函数创建新会话,同时成为新会话的领头进程和新进程组的组长,此时子进程会脱离原父进程的控制:
setsid()会让子进程脱离原终端(如果存在),原父进程不再是它的会话领导者,系统会自动接管该子进程- 注意:若调用
setsid()的进程本身已是进程组组长,函数会失败,因此通常需要先fork一次(确保子进程不是组长)再调用setsid()
示例代码片段:
pid_t pid = fork(); if (pid == 0) { // 子进程 if (setsid() == -1) { perror("setsid failed"); _exit(1); } // 执行业务逻辑,原父进程无法再通过waitpid控制该子进程 execve("/path/to/your/program", argv, envp); _exit(1); } // 原父进程可直接退出或继续执行,无需等待子进程
注意事项
- 一旦子进程脱离原父进程控制,原父进程无法再获取它的退出状态,也无法基于父子权限对子进程进行特殊控制(即使知道PID发送信号,也不属于父子进程专属的权限操作)
- 子进程的资源回收会由系统初始化进程负责,无需原父进程处理
内容的提问来源于stack exchange,提问作者Jonathan Woollett-light
相关产品推荐
相关产品推荐

