据我从不同的文章中了解到这里,守护进程具有以下特征:
- 父进程 ID 应为 1。
- 任何终端都不应与该进程关联。
- 进程的进程id、会话id和进程组id应该相等。
它似乎适用于我系统中的某些守护进程。但是,avahi-daemon
我的系统的 PID 为 678,另外两个 id 为 677。为什么会这样呢?
还有其他一些功能也可以识别守护进程吗?
答案1
你的性格太局限了。这里的关键概念是:守护进程是后台进程,因此它不能是终端的控制进程,也不能拥有控制终端。这个简单的“规则”允许守护进程在终端打开/关闭和用户登录/注销时生存。
每个终端都有一个控制会话,即通过该终端生成的一组进程。会话领导者(通常是 shell)是终端的控制进程。该终端被认为是 shell 的控制终端。
因为您将能够阅读这是对我的一个问题的回答,当终端关闭时,它会SIGHUP
向其控制进程(shell)发送信号。这通常会导致附加到该 shell 的所有进程终止,因为 shell 会将其SIGHUP
收到的数据重新传输到其所有作业。
守护进程必须逃离这个链条,因为它们应该在用户登录和注销后继续存在。因此,它们必须脱离父外壳。一种常见的方法是双叉。
- 守护进程生成一个子进程。
- 守护进程退出其“主”/父进程。
- 所有的工作都在孩子身上完成。
由于 shell 不会跟踪它们的子进程,因此它们不会SIGHUP
向守护进程的剩余部分发送 a 。现在,在这个设置中,孙子(守护进程)基本上应该具有:
- 与任何其他进程一样,它有自己的 PID。
- 其现已终止的父级的 PGID。
- 最近的子收割机的 PPID,通常 PID 1。
- 其现在终止的父级的 SID,通常也是 shell 的 SID。
请注意,杀死父进程并不是特别必要:该进程将随其终端一起死亡。但是,为了避免无用的进程,在子进程开始工作之前立即终止父进程会更干净一些。
在这种情况下,流程能被称为守护进程。关闭终端不会杀死它。然而,为守护进程提供一个全新的会话是很常见的。在 API 级别,这是使用setsid
系统调用完成的。一旦使用,该过程应该具有:
- 未更改的 PID。
- 未更改的 PPID(最近的子收割者)。
- 一个全新的SID,通常与其PID相同。
- 一个全新的 GID,因为来自同一组的进程也必须位于同一会话中。
答案2
这仅仅意味着守护进程的父进程(pid 677)启动了新会话,分叉,而子进程(pid 678)继承了该会话并继续运行。
如果使用某些包装器脚本来守护某些内容(并且由于某种原因没有执行其目标 - 可能是为了处理重新启动),或者只是因为进程在进入稳定状态之前选择再次分叉,则可能会发生这种情况。
我想说一个过程是有效地如果 PPID 为 1 并且没有控制终端,则为守护进程。会话 ID/进程组 ID 约束通常也是正确的,但实际上对于守护进程行为来说并不是必需的。