壳管工艺集团:ls |猫工作,但ls |更挂?

时间:2018-01-28 23:38:51

标签: c linux shell

我正在实施自己的小外壳。如果我没有为这两个子进程创建新组,ls | catls | more都可以正常工作。

但是,在我为这两个进程创建一个新进程组(第一个ls进程是领导进程)后,只需在父进程中调用setpgid即可。 ls | cat始终有效但ls | more挂起。

看起来我的一个进程陷入dup2系统调用。还有其他我需要考虑的事情吗?如果在ls进程调用setpgid之前more首先终止,会发生什么情况?我是否需要阻止ls进程在execve进程完成setpgid之前不致电more

编辑:

我的代码: 有时会卡住。但是当我尝试添加printf来定位时,它已成功完成。没有错误。

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#define CHECK(syscall, msg) do {                    \
    if ((syscall) == -1) {                          \
      perror(msg);                                  \
      exit(1);                                      \
    }                                               \
  } while(0)

#define SAFE_CLOSE_NOT_STD(fd) do {                                 \
    if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != -1) {    \
      CHECK(close(fd), "close error");                              \
      fd = -1;                                                      \
    }                                                               \
  } while(0)

int main () {
  int ls_pid, more_pid;
  int pipefd[2];
  char *ls_argv[] = { "/bin/ls", NULL };
  char *more_argv[] = { "/usr/bin/more", NULL };

  CHECK(pipe(pipefd), "pipe error");

  CHECK(ls_pid = fork(), "fork error");
  if (!ls_pid) {
    CHECK(dup2(pipefd[1], STDOUT_FILENO), "dup2 error");
    CHECK(close(pipefd[1]), "close error");
    CHECK(execvp(ls_argv[0], ls_argv), "execvp error");
  } else {
    SAFE_CLOSE_NOT_STD(pipefd[1]);
  }
  setpgid(ls_pid, ls_pid);

  CHECK(more_pid = fork(), "fork error");
  if (!more_pid) {
    CHECK(dup2(pipefd[0], STDIN_FILENO), "dup2 error");
    CHECK(close(pipefd[0]), "close error");
    CHECK(execvp(more_argv[0], more_argv), "execvp error");
  } else {
    SAFE_CLOSE_NOT_STD(pipefd[0]);
  }

  setpgid(more_pid, ls_pid); // it works if I remove this line

  CHECK(wait(NULL), "wait error");
  CHECK(wait(NULL), "wait error");

  printf("Finish\n");
}

1 个答案:

答案 0 :(得分:1)

Use _exit(), not exit(), after fork()。 (这不是真正的问题,但你应该解决它。)

这里发生的是more不在当前前台进程组中,因此不允许从终端读取输入并获取SIGTTINUse tcsetpgrp