【问题标题】:How does python determine the PID seemingly without normal system calls in Linux?python如何在Linux中看似没有正常系统调用的情况下确定PID?
【发布时间】:2018-09-18 04:24:52
【问题描述】:

运行以下命令时

strace -f python3 -c 'import os; print(os.getpid())'

我注意到 strace 没有捕捉到对getpid(2) 系统调用的调用。我首先认为这是由于 glibc 缓存了 pid,但是如果没有至少一个真正的系统调用,就不应该有一个 pid 供 libc 缓存。然后我认为可能是 vdso 是罪魁祸首,但是运行通过 libc 进行此系统调用的 C 程序在跟踪时会显示 getpid 调用。终于放弃了,查了一下os.getpidpython模块的源码,貌似是在Modules/posixmodule.c中定义的。令我惊讶的是(以及随后的困惑),它正常调用getpid!

所以我的问题是:python如何确定os.getpid的结果?如果确实通过调用getpid 获得了这样的值,那么该调用实际上是如何进行的?

【问题讨论】:

  • strace -e trace=getpid -f python3 -c 'import os; print(os.getpid())' 在我测试时显示了对 getpid 系统调用的两次调用。
  • @Shawn:很奇怪。我刚刚在两个不同的系统上使用额外的trace=getpid 测试了 strace(不幸的是,两者都是相同版本的 ubuntu,16.04)。两者都打印 PID,但没有显示对 getpid 的调用;只有 '+++ 以 0 +++ 退出'。
  • @Shawn:你用的是什么系统?是否启用了 vdso?
  • Arch 和 ubuntu 18.04。
  • @jww:也许吧,但从github.com/torvalds/linux/blob/v3.19/include/uapi/linux/… 看来,系统似乎没有将PID 作为辅助向量值公开给用户。 x86 值似乎也不包括 PID...它也没有解释为什么 ubuntu 18.04 进行调用而 16.04 没有:/

标签: python linux system-calls strace vdso


【解决方案1】:

The way the vdso works 是将特定于进程的变量映射到 vdso 函数知道如何读取的用户空间。其中之一是当前进程 ID,因此 gettimeofday 无需进行系统调用即可访问该信息。

现在,专门针对getpid,它实际上不是 VDSO 调用。在 2.25 之前的 glibc 中,该库会缓存调用,并且由于部分 Python 运行时调用 getpid,因此在第一次之后不会再调用它。从 2.25 开始,该库不再缓存进程 ID,因此每个 getpid 调用都会导致一个系统调用。

【讨论】:

  • 能否请您扩展您的答案以包括为什么据报道getpid 出现在 18.04 和其他系统上? ptrace 是否获得了跟踪 vdso 调用的能力,还是 python 以某种方式颠覆了 vdso 并直接进行调用?
  • 有趣。事实证明,18.04 中的 glibc 更改删除了缓存,因此每个 getpid 调用都会导致系统调用。我已经更新了答案。谢谢!
  • 这引发的问题比它回答的要多(为什么我的测试 C 程序在跟踪时显示getpid)但这个答案似乎是最有可能的。我稍后会进一步调查。谢谢你的回答,我的 unix 人!
  • 我认为改变的仍然是 PID 缓存。 C 运行时根本不会调用 getpid,而 Python 会调用,因此 C 程序将显示第一个 getpid 调用以及所有库版本中的每个后续调用,而 Python 只会显示所有版本中的第一个调用,并且随后的调用仅在 glibc 2.25 和更新版本中。具有多个 getpid 调用的 C 程序也可能很有趣。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 2011-02-23
  • 2012-02-26
相关资源
最近更新 更多