我试图通过分析strace
的输出来跟踪进程的创建,在分析了几千行之后,我遇到了一个以前从未见过的情况。在下面这个简短的代码片段中,您可以看到PID=501135
的第一次出现:
501133 1677685727.376373 clone(child_stack=0x7fbb38c77000, flags=CLONE_NEWNS|CLONE_NEWIPC|CLONE_NEWUSER|CLONE_NEWPID|SIGCHLD) = 501134
501134 1677685727.377751 openat(AT_FDCWD, "/proc/self/setgroups", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
501134 1677685727.377897 openat(AT_FDCWD, "/proc/self/uid_map", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
501134 1677685727.377998 openat(AT_FDCWD, "/proc/self/gid_map", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
501134 1677685727.378102 openat(AT_FDCWD, "/proc/self/mounts", O_RDONLY|O_CLOEXEC) = 3
501134 1677685727.378926 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fbb38c78a10) = 2
501135 1677685727.380065 execve("/bin/true", ["/bin/true"], []) = 0
501135 1677685727.388634 openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
501135 1677685727.388742 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
501135 1677685727.389288 +++ exited with 0 +++
正如您所看到的,PID=501135
突然出现,并且没有vfork
、clone
、clone3
或任何指示其创建的内容。
此外,在第一次出现之前的最后一行中,有一个clone()
返回2
而不是PID,所以我怀疑它是clone
,* 应该 * 返回501135
。
我知道unfinished ...
和... resumed
行可以暂时隐藏PID的创建,直到相应的... resumed
行显示出来。我已经在处理这个问题了,grep
在完整的日志中除了我粘贴的行之外没有显示501135
。
我错过了什么?是否有机会使用strace
可靠地跟踪每个PID(或替代方法,我不知道任何..)
- 更新**:
多亏了@tkausl关于CLONE_NEWPID
标志的提示,我成功地解决了许多以前失败的PID查找问题。
- 保持Map
pid_offset
:PID-〉初始PID - 每次
CLONE_NEWPID
在clone()
标志中时更新Map:
if "CLONE_NEWPID" in clone.flags:
pid_offset[strace.result] = strace.pid
- 每次使用
pid_offset
中Map的PID执行clone()
时,我都会根据clone()
的结果和偏移量重新计算"实际" PID:
new_pid = strace.result_nr
if strace.pid in pid_offset:
new_pid = strace.result + pid_offset[strace.pid]
pid_offset[new_pid] = pid_offset[strace.pid]
奇怪的是,这适用于大多数情况,但不是所有情况。下面是一个我仍然偶然遇到的情况(剥离到clone()
的相关调用。我没有跟踪的PID是501376
:
# Here is a case which actually works:
# PID 501133 creates 501134 with CLONE_NEWPID and as a result
# 501134 successfully creates 501135:
#
501133 1677685727.376373 clone(child_stack=0x7fbb38c77000, flags=CLONE_NEWNS|CLONE_NEWIPC|CLONE_NEWUSER|CLONE_NEWPID|SIGCHLD) = 501134
+++ CLONE_NEWPID for clone() with PID=501133: 501133
501134 1677685727.378926 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fbb38c78a10) = 2
+++ clone_PID: 501134, new_PID = PID_offset=501133 + result=2 = 501135
# Now comes a long chain of `clone()` calls starting with
# 501149 cloning with CLONE_NEWPID, working in the beginning:
#
501149 1677685727.761916 clone(child_stack=0x7f24b72cc000, flags=CLONE_NEWNS|CLONE_NEWIPC|CLONE_NEWUSER|CLONE_NEWPID|CLONE_NEWNET|SIGCHLD) = 501150
+++ CLONE_NEWPID for clone() with PID=501149: 501149
501150 1677685727.776125 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24b72cda10) = 2
+++ clone_PID: 501150, new_PID = PID_offset=501149 + result=2 = 501151
501151 1677685727.838544 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f0d7075aa10) = 3
+++ clone_PID: 501151, new_PID = PID_offset=501149 + result=3 = 501152
... here the PIDS 501152..501373 get created successfully
501161 1677685728.487811 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f28da126ad0) = 225
+++ clone_PID: 501161, new_PID = PID_offset=501149 + result=225 = 501374
501161 1677685728.488968 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f28da126ad0) = 226
+++ clone_PID: 501161, new_PID = PID_offset=501149 + result=226 = 501375
501376 1677685728.489090 execve("/opt/bin/touch", [CMD..], [ENV...]) = -1 ENOENT (No such file or directory)
最后一行显示PID = 501376
,我不知道它是在哪里创建的,也不知道如何计算值501376
。
我怀疑有一个错误,但是简单地在某个地方添加+ 1
只会导致在其他地方出现未知的PID。
我哪里做错了?
1条答案
按热度按时间2q5ifsrm1#
这是正确的,第二个克隆确实创建了PID,但仍然正确地返回了PID 2。这是因为第一个克隆创建了一个新的PID命名空间(
CLONE_NEWPID
),它在新命名空间内获得PID 1。下一个克隆 * 来自该命名空间 *,在该命名空间内获得PID 2,并在父命名空间中获得PID 501135。