pidfd:进程号会被重用,怎样才能稳定指向一个进程?

TL;DR

Linux pidfd 用文件描述符稳定引用一个进程,避免退出后的 PID 被重用而误操作新进程。本文介绍它的等待、信号用途和版本边界。

Linux pidfd 用文件描述符稳定引用一个进程,避免退出后的 PID 被重用而误操作新进程。本文介绍它的等待、信号用途和版本边界。

pidfd:进程号会被重用,怎样才能稳定指向一个进程?

Linux 用进程 ID(PID)标识进程,但 PID 是会被回收和重新使用的数字。假设一个管理程序记录下 PID 1234,目标进程退出后,系统稍后把 1234 分给另一个进程;如果旧管理程序再按 PID 发信号,它可能误操作新进程。这类“标识被复用”的竞态,正是 pidfd 想缓解的问题。

pidfd 是指向进程的文件描述符。可以把它理解为一张仍指向同一个对象的号码牌,而 PID 更像一段可能再次分配的座位号。文件描述符可以被等待、轮询,也能用于某些进程操作;即使原进程已经结束,它也不会悄悄改指向后来复用该 PID 的另一个进程。管理程序由此能够更稳妥地关联进程生命周期。

例如,服务管理器创建子进程后,可以保留 pidfd 并通过 poll 或 epoll 等机制等待它终止;合适的接口还允许通过 pidfd 向目标发送信号。Linux 提供 pidfd_open 等系统调用,也支持创建进程时取得相应句柄的方式。相比反复读取数字 PID 再执行操作,这种对象句柄模式可以缩小检查与使用之间的竞态窗口。

不过 pidfd 并不是万能的进程管理抽象。不同 pidfd 相关系统调用和标志支持情况,依赖 Linux 内核版本;可执行的操作也有权限检查。它解决的是“稳定引用某个进程”的身份问题,不替代进程树管理、资源限制、信号语义或容器生命周期协调。程序还得在适当时机关闭文件描述符,否则句柄本身会占用进程资源。

pidfd 对 shell 脚本或短命令未必必要,但对长期运行的服务管理器、运行时、容器编排组件和需要严谨处理并发退出的系统程序很有意义。判断是否需要它,可以先问:目标进程退出与 PID 复用之间,是否可能与自己的操作并发?如果可能,用可持有的句柄通常比只保存一个数字更稳妥。

这个设计和文件描述符访问文件的理念相似:程序持有的是内核认可的对象引用,而不是寄希望于一个可能变化的名字始终指向原对象。

来源:Linux pidfd_open(2) 手册

KEEP READING