Ale*_*dro 3 linux multithreading exit linux-kernel printk
为了验证我想要使用的第三方二进制分布式软件的行为,我正在实现一个内核模块,其目标是跟踪该软件生成和终止的每个子项。
目标二进制文件是 Golang 生成的二进制文件,并且它是多线程的。我编写的内核模块在内核函数_do_fork()和 do_exit()上安装了钩子,以跟踪该二进制文件生成和终止的每个进程/线程。
LKM 或多或少是有效的。
然而,在某些情况下,我会遇到无法解释的情况。看起来进程/线程可以在不通过do_exit()的情况下终止。
我通过printk()收集的证据显示了进程创建,但并不表明进程终止。
我知道printk()可能会很慢,而且我也知道在这种情况下消息可能会丢失。
为了防止由于控制台缓慢而导致消息丢失(对于这个特定的应用程序,使用了串行 tty 115200),我尝试实现一个更快的控制台,并使用netconsole收集消息。
所描述的设置似乎确认进程可以终止而无需通过do_exit()函数。
但因为我不确定我的消息不会在printk()基础设施上丢失,所以我决定重复相同的测试,但用ftrace_printk( ) 替换 printk( ) ,这应该是printk()的更精简的替代方案。
仍然是相同的结果,偶尔我看到进程没有通过do_exit(),并验证 PID 当前是否正在运行,我必须面对它没有运行的事实。
另请注意,我将挂钩放在do_exit()内核函数中作为第一条指令,以确保函数流不会在被调用函数内终止。
我的问题如下:
Linux 进程可以在其流程不经过do_exit()函数的情况下终止吗?
如果是这样,有人可以告诉我这种情况会是什么吗?
经过长时间的调试,我终于能够回答我自己的问题了。
\n那不是全部; 我还能够解释为什么我看到了我在场景中描述的奇怪行为。
\n让我们从头开始:监视大量多线程应用程序。我观察到了罕见的情况,即存在突然停止的 PID,而没有观察其流经 Linux 内核do_exit()函数的情况。
\n因为这是我原来的问题:
\nLinux 进程可以在不通过 do_exit() 函数的情况下终止吗?
\n就我目前的知识而言,我现在认为这些知识相当广泛,Linux 进程如果不通过do_exit()函数就无法结束其执行。
\n但这个答案与我的观察相反,导致我提出这个问题的问题仍然存在。
\n这里有人提出,我看到的奇怪行为是因为我的观察有些错误,暗示我的方法不准确,至于我的结论。
\n我的观察是正确的,我观察到的进程没有通过 do_exit ()而是终止了。
\n为了解释这一现象,我想提出另一个问题,我认为互联网搜索者可能会发现它有点有用:
\n两个进程可以共享相同的PID吗?
\n如果你一个月前问我这个问题,我肯定会回答这个问题:“绝对不能,两个进程不能共享相同的 PID。”不过,Linux 更复杂。
\n有一种情况,在Linux系统中,两个不同的进程可以共享相同的PID!
\nhttps://elixir.bootlin.com/linux/v4.19.20/source/fs/exec.c#L1141
\n令人惊讶的是,这种行为并没有伤害任何人;当这种情况发生时,这两个进程之一就是僵尸进程。
\n更新以纠正错误
\n这个重复PID的情况比前面描述的更加复杂。如果线程进程在调用 execve 之前分叉(分叉也会复制线程),则该进程必须刷新先前的 exec 上下文。如果意图使用 execve() 函数执行新文本,则内核必须首先调用flush_old_exec()\xc2\xa0\xc2\xa0 函数,该函数然后为进程中除任务之外的每个线程调用 de_thread() 函数领导者。结果,除了任务领导者之外,所有进程的线程都被消除。每个线程的 PID 都会更改为领导者的 PID,如果它没有立即终止,例如因为它需要等待操作完成,它会继续使用该 PID。
更新结束
\n这就是我所看到的;我正在监视的PID没有通过do_exit (),因为当相应的线程终止时,它不再有启动时的PID,但它有它的领导者。
\n对于非常了解 Linux 内核机制的人来说,这不足为奇;此行为是有意为之,自 2.6.17 以来一直没有改变。\n当前的 5.10.3 仍然是这样。
\n希望这对互联网搜索者有用;我还想补充一点,这也回答了以下问题:
\n| 归档时间: |
|
| 查看次数: |
1172 次 |
| 最近记录: |