【问题标题】:How to find all child processes?如何找到所有子进程?
【发布时间】:2010-11-03 19:38:43
【问题描述】:

在我正在处理的基于 Linux 的项目中,我需要能够找到我的所有子进程。每次启动都记录下来是不可行的——需要事后才能找到。这需要是纯 C 语言,我想在不阅读 /proc 的情况下这样做。有谁知道怎么做?

【问题讨论】:

  • 通过“纯 C”,我有点包括“不解析命令输出”。
  • 为什么不可行?这是迄今为止最干净、最有效的方法。
  • 您是否反对编写将覆盖其中一个未使用的系统调用的 LKM?如果是这样,编写一个小型系统调用来为您完成它是微不足道的。
  • LKM 实际上是一个不错的主意。我想我遗漏了——这是一个非常低级的程序,当它是引导系统上唯一起作用的东西之一时,它必须能够获取此信息。这就是为什么我不想叫'ps'。不太确定我对阅读 /proc 的厌恶是什么;我会尝试 LKM 和阅读 /proc 看看哪个效果更好。
  • @Duck Jun:我想获取当前进程的父进程的所有子进程(像ps那样横向所有进程),这种情况下是不可行的。确实,在这个问题中,取决于 my child processes 的含义:当前进程的子进程,或当前用户拥有的任意进程的子进程。在这个问题中听起来更像是前者。

标签: c linux process


【解决方案1】:

每次启动子进程时记录子进程通常是完全可行的。方便的是,父进程将子进程的 pid 值作为创建它的 fork 调用的返回值传递给父进程。

正如手册页所说:

pid_t fork(void);

如果您能告诉我们您认为它不可行的原因会有所帮助。

【讨论】:

  • 我认为他有充分的理由。但你是对的。获取这些信息通常很简单。
【解决方案2】:

我发现您的评论认为记录进程的创建是不可行的很奇怪,但如果您真的不能(可能是因为您不知道将创建多少并且不想必须保留reallocing 内存),那么我可能会打开所有与glob /proc/[1-9]*/status 匹配的文件,并查找显示PPid: <num> 的行,其中<num> 是我的进程ID。

【讨论】:

  • 然后他/她接受了我的回答,所以我猜他/她在看到它有多容易后改变了主意。
  • 您可能无法记录每个子进程的创建的一个完全合理的原因是:如果您知道某个库分叉了进程,但它没有给您它们的 PID。
  • 你能详细说明你的答案吗?我要得到特定进程的孩子吗??
  • 评论没那么奇怪。如果您的进程是子收割机(PR_SET_CHILD_SUBREAPER)并且您的孙辈被提升为子辈,则记录进程的创建是不可行的。您可以使用 ptrace 跟踪创建它,但性能损失可能会很大。
【解决方案3】:

你可以使用 popen

类似的东西。 (希望语法足够接近)

#include #include #include int main(int argc, char *argv[]) { FILE *fp = popen("ps -C *您的程序名称在这里* --format '%P %p'" , "r"); 如果(fp == NULL) { printf("错误!\n"); } 字符父ID[256]; 字符进程ID[256]; while (fscanf(fp, "%s %s", parentID, processID) != EOF) { printf("PID: %s Parent: %s\n", processID, parentID); // 检查 parentID 以查看它是否属于您的进程 } 关闭(fp); 返回 1; }

【讨论】:

  • bleh,和 sangretu 的答案一样。
  • 拜伦,我投票给你是因为你可能对现在的问题有最好的答案,因为 ps 不是一个选项。不过,我确实希望你没有投票给我 b/c 我的答案与 sangretu 的相同,但更详细。我们相隔 2 分钟,我花了一些时间来编写最初的伪代码。此后,我进行了编辑以提供更详细的有效代码。
【解决方案4】:

你可以试试这个

#include<string.h>
#include <sys/types.h>
#include <unistd.h>

char str[50] = "ps -o pid --ppid ";
char ppid [7];
sprintf(ppid,"%d",getpid());
strcat(str,ppid);
system(str);

注意:这段代码需要在父进程中

基本上ps -o pid --ppid &lt;parent_id&gt; 给出了其父进程的PID 为&lt;parent_id&gt; 的所有子进程的PID。现在,我们可以使用getpid()获取父进程的PID,它返回pid_t并隐式转换为整数。 sprintf() 将其转换为字符串,我们将结果与str 连接以获得由system() 执行的完整命令。

【讨论】:

  • system(str) 是否在控制台显示输出?我也想在数组中显示所有 id
  • 请注意,ps -o pid --ppid 也会返回自己的 pid 作为列表中的最后一个 pid。
【解决方案5】:

您可以解析包含父进程 ID 的进程列表(ps -ax?)。这可以通过一个简单的 shell 脚本来完成。

【讨论】:

  • 他说的是纯 c ;)。不过,我已经成功地做到了。
  • 如果你从它执行一个shell命令,它仍然算作纯C吗?
  • @sangretu 否 - 即使它是 C shell。 ;)
【解决方案6】:

如果您试图获取所有子进程以等待它们退出的特定目的,则可以使用 waitpid(-1, ...):

while (true) {
  // Wait for any child exiting
  int child_status;
  const int child_pid = waitpid(-1, &child_status, 0);
  // check child_status
}

【讨论】:

  • 我可以使用您的解决方案在我的 shell 中显示后台进程的状态。但是,什么时候循环中断?
【解决方案7】:

如果您想跟踪 fork 事件并提取子 pid 以进行调试,有多种方法可以做到这一点,包括:

  • 使用 GDB
  • 使用 strace
  • 使用 systemtap
  • 使用内核事件连接器(不确定它们到底是什么)

【讨论】:

    【解决方案8】:

    需要调整此存储库中的代码以使用纯 C 编写以满足您的要求,如果您同意这样做,如果您从项目中的存储库中删除所有未使用的功能,则不应该很难翻译成普通的 C。

    但这对于希望支持多个平台和/或喜欢 C++ 的人更有用。

    查看函数 pids_from_ppid(ppid) https://github.com/time-killer-games/enigma-dev/blob/548dc16e96a2a32f8ad9045a4ee18b0206516e62/ENIGMAsystem/SHELL/Universal_System/Extensions/ProcInfo/procinfo.h#L101

    返回一个字符串,其中每个子进程 ID 由管道“|”分隔字符作为分隔符。

    Ubuntu 和 debian 用户需要安装 libprocps-dev 以防止缺少标头。

    sudo apt-get install libprocps-dev libx11-dev

    libx11-dev 依赖项是可选的,因为源代码中的所有 X11 代码都可以省略,这里的问题仍然会得到解答,所以如果您需要 Wayland 而没有 X11 支持,您应该删除 X11 相关代码,因为它与此问题无关无论如何。

    对于那些真正喜欢/需要 X11 和/或 C++ 的人来说,这将在 Windows、Mac、Linux 和 FreeBSD 上开箱即用。由于依赖于 libutil 依赖项,对其他 BSD 的支持并不那么容易实现。但它只是在内部使用 sysctl(),所以理论上你应该能够在 FreeBSD 的 github 存储库中提供的其他 BSD 上编译 libutil 的源代码,然后在构建后链接到它。

    【讨论】:

      猜你喜欢
      • 2016-02-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-02
      • 2017-05-27
      • 2020-12-19
      • 2012-01-17
      • 1970-01-01
      相关资源
      最近更新 更多