返回

如何优雅地获取 Linux 下的子进程 PID?

Linux

优雅地获取 Linux 下的子进程 PID

问题:寻找子进程 PID 的困境

在 Linux 环境中,我们经常需要获取某个进程创建的所有子进程的 PID。传统的方法,如使用 popen()pgrep,既繁琐又可能引入不必要的进程。

解决方案:利用 proc 文件系统

Linux 提供了 proc 文件系统 ,它提供了有关系统和进程信息的伪文件系统。利用 proc 文件系统,我们可以获取子进程的 PID:

  1. 打开 /proc/[pid]/task 目录。
  2. 遍历目录中的子目录,它们的名称就是子进程的 PID。

代码示例

C 语言:

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  if (argc < 2) {
    fprintf(stderr, "用法: %s <pid>\n", argv[0]);
    return EXIT_FAILURE;
  }

  pid_t pid = atoi(argv[1]);
  char path[256];
  snprintf(path, sizeof(path), "/proc/%d/task", pid);

  DIR *dir = opendir(path);
  if (dir == NULL) {
    perror("opendir");
    return EXIT_FAILURE;
  }

  struct dirent *entry;
  while ((entry = readdir(dir)) != NULL) {
    if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
      continue;
    }

    printf("%s\n", entry->d_name);
  }

  closedir(dir);
  return EXIT_SUCCESS;
}

Python:

import os

def get_child_pids(pid):
  path = "/proc/{}/task".format(pid)
  return [int(entry.name) for entry in os.listdir(path) if entry.isdigit()]

优势

使用 proc 文件系统获取子进程 PID 具有以下优点:

  • 简单易行
  • 高效可靠
  • 适用于各种编程语言

常见问题解答

  1. 为什么 popen() 和 pgrep 不适用?
    因为它们会将运行 shell 命令的进程也包括在内。
  2. 使用 proc 文件系统是否安全?
    proc 文件系统是内核的一部分,因此是安全的。
  3. 如何获取所有子孙进程的 PID?
    使用递归算法遍历所有子目录。
  4. 可以获取已结束进程的子进程吗?
    不能,proc 文件系统仅包含正在运行的进程信息。
  5. proc 文件系统还提供了哪些其他信息?
    它提供了有关进程状态、内存使用、线程等各种信息。

结论

proc 文件系统提供了一种简单而优雅的方法来获取 Linux 下的子进程 PID。了解这种方法可以极大地提高你的进程管理能力。