setsid的核心作用是创建新会话,使进程成为新会话和新进程组的领头进程(sid=pgid=pid),并彻底脱离原有控制终端与会话关联。

进程组和会话不是并列概念,而是嵌套层级关系:一个会话可包含多个进程组,每个进程组又包含若干进程。setsid 的核心作用,就是打破这种继承链,让进程脱离原有会话与终端控制,形成独立的运行单元。
进程组:以任务为单位的协作集合
进程组是操作系统对“协同完成同一任务”的一组进程的逻辑分组。它的关键特征包括:
- PGID(进程组 ID)默认等于该组首个进程的 PID,这个进程称为组长;
- 管道命令如 ls | grep .c | wc -l 中的三个进程共享同一个 PGID,属于同一进程组;
- 用 kill -9 -PGID 可一次性终止整个组,比逐个 kill 更高效;
- 前台/后台切换本质是终端将控制权授予某一个进程组,其他组被挂起或忽略输入。
会话:用户级生命周期的边界容器
会话是更高一层的组织单位,通常对应一次登录行为(比如打开一个终端窗口)。它决定了进程能否持续运行、是否响应终端信号:
- 每个会话有唯一 SID(会话 ID),通常等于其首进程(如 bash)的 PID;
- 会话可拥有至多一个控制终端(TTY/PTS),所有前台进程组的 I/O 都经由它;
- 用户退出登录时,内核会向该会话发送 SIGHUP,导致多数子进程终止;
- 守护进程必须脱离会话,否则无法在用户登出后继续存活。
setsid:创建新会话的强制断连机制
setsid 不是简单地“后台运行”,而是调用内核函数重建进程归属关系。它生效的前提和效果如下:
- 调用者不能是当前进程组的组长(否则 setsid 失败,返回 -1);
- 成功后,进程获得全新 SID 和 PGID(都等于自身 PID);
- 自动脱离原控制终端,不再接收 SIGHUP、SIGINT 等终端信号;
- 常见用法:setsid ./myserver & 或在 C 程序中 fork + setsid 组合使用。
进程树视角下的典型结构变化
假设从终端启动一个服务,默认结构是:
bash (SID=1000, PGID=1000) → ./myserver (SID=1000, PGID=1000)
执行 setsid ./myserver 后变为:
bash (SID=1000, PGID=1000) └── ./myserver (SID=2001, PGID=2001)
此时 myserver 已自成一个会话,与 bash 完全解耦,不再受终端关闭影响。











