【问题标题】:How to terminate child process when another child process finishes?当另一个子进程完成时如何终止子进程?
【发布时间】:2020-06-23 11:00:17
【问题描述】:

我有一个如下所示的代码段:

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

int main(int argc, char *argv[]) {
  pid_t first, last;

  last = fork();
  if (last == 0) {
    char *args[] = { "./last", NULL };
    char *env[] = { NULL };
    execve("./last", args, env);
    _exit(1);
  } else if (last == -1) {
    fprintf(stderr, "Error: failed to fork last.\n");
    exit(1);
  }

  first = fork();
  if (first == -1) {
    fprintf(stderr, "Error: failed to fork first.\n");
    exit(1);
  } else if (first > 0) {
    int status;
    waitpid(first, &status, 0);
  } else {
    char *args[] = { "./first", NULL };
    char *env[] = { NULL };
    execve("./first", args, env);
    _exit(1);
  }

  return 0;
}

从某种意义上说,这很好用,我可以看到正在调用和运行的进程。但是,我的问题是进程last 有一个无限循环,当进程first 终止时,它仍然保持运行。有没有办法在 C 中强制进程 last 在进程 first 完成时终止?

【问题讨论】:

标签: c linux fork exec


【解决方案1】:

kill() 应该很有趣。来自kill()的手册页:

#include <sys/types.h>
#include <signal.h>

int kill(pid_t pid, int sig);

由于 fork() 在父节点中返回子 PID,您可以使用它来调用 kill()。这是修改后的代码和测试运行。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>  // Modification 1

int main(int argc, char *argv[]) {
  pid_t first, last;

  last = fork();
  if (last == 0) {
    char *args[] = { "./last", NULL };
    char *env[] = { NULL };
    execve("./last", args, env);
    _exit(1);
  } else if (last == -1) {
    fprintf(stderr, "Error: failed to fork last.\n");
    exit(1);
  }

  first = fork();
  if (first == -1) {
    fprintf(stderr, "Error: failed to fork first.\n");
    exit(1);
  } else if (first > 0) {
    int status;
    waitpid(first, &status, 0);
    kill(last, SIGINT);   // Modification 2
  } else {
    char *args[] = { "./first", NULL };
    char *env[] = { NULL };
    execve("./first", args, env);
    _exit(1);
  }

  return 0;
}

终端会话(之前):

$ ls test first last 
first  last  test
$ ./test
$ ps aux | grep last
root      165130  0.0  0.0   2136   752 pts/3    S    16:58   0:00 ./last
root      165135  0.0  0.0   6136   892 pts/3    S+   16:58   0:00 grep last

终端会话(之后):

$ ls test first last 
first  last  test
$ ./test
$ ps aux | grep last
root      165240  0.0  0.0   6136   836 pts/3    S+   17:01   0:00 grep last

关于要传递的信号:默认操作为终止的任何人。您可以从 signal 手册页中找到更多信息。由于我不知道last 可执行文件中到底有什么,我假设没有为SIGINT 注册信号处理程序,因此当last 获取SIGINT 时,程序默认终止。

【讨论】:

    【解决方案2】:

    一种方法是使用函数kill() 向第一个进程发送 SIGTERM 或 SIGKILL 信号

    一个例子:

    kill(first, SIGTERM);
    

    当您发送该信号时,如果您愿意,您可以对该进程进行一些“清理”。为此,您需要捕获并处理信号。在这种情况下,我建议使用 SIGTERM。

    有关信号处理,请查看this

    【讨论】:

    最近更新 更多