从兄弟进程获取pid

Get pid from brother process

我想要一个父进程和三个子进程。我希望这些子进程知道其他子进程的 pids。 问题是,当我执行 fork 然后再次执行时,第二个 fork 也在子进程中执行,创建一个额外的进程(或者我认为)。 我该如何解决?

谢谢。

parent分叉三次,child人不分叉。这样,parent 将知道所有三个 children.

的 pids

分叉后,您将需要某种单独的通信渠道,parent 可以通过该渠道将这些 pids 传达给所有 children。一个简单的方法是在分叉每个 child 之前打开一个管道(参见 pipe(2)),因此 child 继承管道的文件描述符(至少是读取端)和 parent 保持写结束。然后让 parent 将三个 pid 发送到每个管道并关闭它。

示例代码(很长,但这就是 C 的本质):

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#define NUM_CHILDREN 3

/* Entry point for the child processes */
int child_main(int pipe_read_end) {
  pid_t my_pid = getpid();

  /* Read child pids from pipe */
  int child_pids[NUM_CHILDREN];
  unsigned int bytes_read = 0;
  while (bytes_read < sizeof(child_pids)) {
    ssize_t result = read(pipe_read_end, ((unsigned char *) child_pids) + bytes_read, sizeof(child_pids) - bytes_read);
    if (result < 0) {
      perror("error reading from pipe");
      return 1;
    } else if (result == 0) {
      fprintf(stderr, "unexpected end of file\n");
      return 1;
    } else {
      bytes_read += result;
    }
  }
  close(pipe_read_end);

  /* Do something useful with these child pids */
  for (int i = 0; i < NUM_CHILDREN; i++) {
    printf("Child %d received sibling pid %d\n", my_pid, child_pids[i]);
  }

  return 0;
}

/* Entry point for the parent process. */
int main() {
  int child_pids[NUM_CHILDREN];
  int pipe_write_ends[NUM_CHILDREN];
  for (int i = 0; i < NUM_CHILDREN; i++) {
    /* Create the pipe for child i */
    int pipefd[2];
    if (pipe(pipefd)) {
      perror("error creating pipe");
      return 1;
    }
    int pipe_read_end = pipefd[0];
    int pipe_write_end = pipefd[1];

    /* Fork child i */
    pid_t child_pid = fork();
    if (child_pid < 0) {
      perror("error forking");
      return 1;
    } else if (child_pid == 0) {
      printf("Child %d was forked\n", getpid());
      close(pipe_write_end);
      return child_main(pipe_read_end);
    } else {
      printf("Parent forked child %d\n", child_pid);
      close(pipe_read_end);
      pipe_write_ends[i] = pipe_write_end;
      child_pids[i] = child_pid;
    }
  }

  /* Send pids down the pipes for each child */
  for (int i = 0; i < NUM_CHILDREN; i++) {
    unsigned int bytes_written = 0;
    while (bytes_written < sizeof(child_pids)) {
      ssize_t result = write(pipe_write_ends[i], ((unsigned char *) child_pids) + bytes_written, sizeof(child_pids) - bytes_written);
      if (result < 0) {
        perror("error writing to pipe");
        return 1;
      } else {
        bytes_written += result;
      }
    }
    close(pipe_write_ends[i]);
  }

  /* Wait for children to exit */
  for (int i = 0; i < NUM_CHILDREN; i++) {
    if (waitpid(child_pids[i], 0, 0) < 0) {
      perror("error waiting for child");
      return 1;
    }
  }
}

正如@PSkocik 在 中指出的那样,您可能不应该这样做。 Pid 可以被 OS 重用,所以 children 无法知道他们的兄弟 pid 实际上仍然引用他们的兄弟;只有 parent 可以确定,因为它必须 wait 每个 pid 才能被重用。

然而,同样的机制可以用于其他形式的 IPC(inter-process 通信);例如,您可以使用它直接在 children 之间创建管道。

您可以使用共享内存或某种其他类型的 IPC 来传递 PID,但您可能甚至不应该尝试。

PID 会被回收,您只能确定 PID 是否指代您认为它指代的进程是否属于您的 child 进程(因为这样您就可以知道如果您 wait 是否使用过它)。

否则,PID(non-children)是活泼的引用,基本上只能用于 hacky 调试。