我正在尝试制作一个简单的外壳,并添加了使用&在后台运行进程的功能。
在我的主要方法中,我基本上有:

int main() {
  if (signal(SIGCHLD, handle) == SIG_ERR)
    perror("Cannot catch SIGCHLD");
  pid_t child = fork();
  if (child == 0)
    execvp(command, arguments);
  else {
    if (background == 1) {
       printf("1");
       backgroundList(command, child);
       printf("2"); }
    else
      waitpid(child, NULL, 0);
  }
}


对于我的经理,我有:

void handle(int s) {
  printf("a");
  if (signal(SIGCHLD, handle) == SIG_ERR)
    perror("Cannot catch SIGCHLD");
  pid_t pid;
  printf("b");
  while((pid = waitpid(0, NULL, WNOHANG)) > 0) {
    printf("c");
    rmBackgroundList(pid);
    printf("d");
  }
}


我可以让它在前台运行一个进程。运行“ ls”会将内容打印到屏幕上,然后将“ a”和“ b”打印到SIGCHLD处理程序中,但是由于已经等待,因此不会转到“ c”。

但是,在后台运行某些内容(“ ls&”)将显示“ 1”和“ 2”,让父级返回到提示,然后子级将内容打印到屏幕上,然后出现分段错误。它不会打印处理程序中我拥有的任何字母。

我无法弄清楚为什么SIGCHLD对已经等待的孩子有好处,但是会导致分段错误,甚至对于没有等待的进程也永远不会进入处理程序。

最佳答案

您没有遵循信号处理程序的规则。您不能使用printf()perror()Read the rules on what is safe to do in a signal handler.

另外,signal()的行为也会根据BSD或SysV风格的Unix而变化。 Linux会根据_BSD_SOURCE或_GNU_SOURCE的存在来更改其在glibc中的行为,具体取决于您调用gcc -ansi还是gcc -std=c99gcc -std=gnu99

您确实应该使用sigaction()而不是signal()

10-08 05:40
查看更多