【发布时间】:2017-01-22 12:11:37
【问题描述】:
上下文:
我在学术上对跟踪/识别 UNIX 进程很感兴趣,这种方法可以证明是针对 PID wraparound 的。要开始通过 PID 跟踪进程,我需要能够在系统上最终识别它。
因此,我需要一个函数get_identity,它接受一个 PID,并且只有在确定该 PID 的系统范围的唯一标识后才返回。该功能应适用于所有或大多数符合 POSIX 的系统。
我知道的进程表中唯一不可变的值是 PID 和开始时间。但是,以下情况会带来问题:
- 用户致电
get_identity(pid) -
get_identity读取pid的开始时间in seconds-since-the-epoch,如果它存在,并返回希望唯一的元组[pid, starttime](这就是优秀的psutilPython 库认为“足够独特”,因此它应该非常健壮)。 -
在调用的一秒内,系统上会发生 PID 回绕,
pid被回收。 -
[pid, starttime]元组现在指的是与调用get_identity时不同的进程。
虽然 PID 环绕发生并在其被识别后的一秒钟内重新使用选定的 PID 是非常不可能,但它并非不可能。 . .对吧?
问题:
- 在 UNIX/POSIX 兼容系统上,是否保证 PID 的开始时间在重复使用相同 PID 值时会有所不同?
- 如果不是,我如何才能唯一地标识易环绕系统上的进程?
我的尝试:
- 在检查目标进程后,我可以简单地
sleep一秒钟。如果在sleep之后的开始时间以秒为单位相同,那么它要么是我开始观看的同一进程,要么 PID 已经绕到另一个进程,但系统无法区分。如果开始时间改变了,我可以返回错误,或者重新开始。但是,这需要我的识别功能等待最多 1 秒才能返回,这并不理想。 -
times()返回时钟滴答的值,我可以将其转换为秒。假设进程的 starttime-in-seconds 基于times使用的相同时钟,并假设所有 UNIX 使用相同的舍入逻辑从clock ticks -> fractional seconds -> whole seconds转换,理论上我可以使用此信息来减少持续时间上述解决方法中的sleep到下一个“根据进程表的完整秒边界”的时间。但是,最坏情况下的睡眠时间仍然接近 1 秒,因此并不理想。 - 在 Linux 上,我可以从
/proc/$pid/stat文件中以 jiffies(或 CPU 滴答声,对于旧的 Linux)获得开始时间。有了这些信息,我的程序可以稍等片刻(即?),再次检查开始时间,如果相同,则确定身份。这正确地解决了我的问题(1 jiffy + 开销是足够快的运行时),但仅在 Linux 上;其他 UNIX 平台可能没有/proc。在 BSD 上,该信息是 available via thekvmsubsystem or viasysctls。在其他 Unix 上。 . .谁知道?我需要开发多个特定于平台的实现来收集这些数据——我希望避免这样做。
【问题讨论】:
-
坦率地说,我认为你已经被灌输了。如果进程以每秒超过 2^16 的速率生成,我绝对希望 PID+starttime 冲突是可能的。内核人员必须有一个具体的理由来扭曲 starttime 值以使 PID+starttime 独一无二,我希望 starttime 准确性被认为更重要。
-
@zwol 不同意您的总体结论,但请记住,PID 环绕发生的频率可能远高于每秒 2^16 次。当然,这仍然不太可能,但考虑一个已经有 2^16-4 个长期运行进程的系统 - 然后每 4 个分叉就会发生 PID 环绕...
-
@twalberg 哦,好点,我什至没有想到。
-
您应该查看Proc connector。有了它,您可以订阅系统上发生的所有进程事件,包括
fork()和exec()。 -
proc 连接器看起来超级有用,谢谢!不幸的是,它仅适用于 Linux。知道这样的跨平台吗?