进程叉开shell,然后整个程序被停止?

问题描述 投票:0回答:1

我有一个从man页中复制的pipe(2)程序,经过修改后,子程序将fork掉一个shell,父程序从stdin读取命令,并将命令发送给子程序执行。 这对第一条命令来说是可行的,但是在那条命令运行之后,我收到了一条消息,说程序已经停止,我被返回到顶层的shell。

为什么会发生这种情况,我怎样才能停止它?

signal(7)说。

   SIGTTIN      P1990      Stop    Terminal input for background process

但它不应该是一个后台进程,为什么要停止?

下面是一个终端会话,有完整的源代码,gcc -Wall的结果,并尝试运行程序。 正如你所看到的,我给了命令 "date",然后我被送回调用的shell,然后子shell执行 "date "并出现输出,然后出现一个 "exit"。 "fg "让我回到pipe_shell程序,"uptime "被发送到shell并运行,然后我可以做一个 "echo",然后我被送回顶层shell,再出现 "exit"。

sh-5.0$ cat pipe_shell.c
/* pipe_shell.c - learn about pipes
 *
 * Modified from the man page for pipe(2).
 */

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

int main(int argc, char *argv[])
{
    int   pipefd[2];
    pid_t cpid;

    if (argc != 1) {
        fprintf(stderr, "Usage: %s\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    cpid = fork();
    if (cpid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (cpid == 0) { // Child reads from pipe

        close(pipefd[1]);              // Close unused write end of pipe
        close(STDIN_FILENO);           // shut off standard input
        dup2(pipefd[0], STDIN_FILENO); // pipe output is standard input
        close(pipefd[0]);              // close pipe output

        execl("/bin/bash", "bash",
              "--norc",
              "-i",
              (char *) 0);

        perror("exec");

    } else { // Parent writes to pipe
        close(pipefd[0]);    // Close unused read end

        char line[256];      // we take input from keyboard
        while ( fgets(line, 255, stdin) != NULL ) {
            write(pipefd[1], line, strlen(line));
        }

        close(pipefd[1]);    // Reader will see EOF
        wait(NULL);          // Wait for child
        exit(EXIT_SUCCESS);
    }
}
sh-5.0$ gcc -Wall pipe_shell.c -o pipe_shell
sh-5.0$ ./pipe_shell
bash-5.0$ date

date
[1]+  Stopped(SIGTTIN)        ./pipe_shell
sh-5.0$ Wed 10 Jun 2020 12:16:28 PM EDT
bash-5.0$ exit
There are stopped jobs.
sh-5.0$ fg
./pipe_shell
uptime
uptime
 12:16:52 up 154 days, 23:32,  5 users,  load average: 0.04, 0.05, 0.07
bash-5.0$ echo "foo"

[1]+  Stopped(SIGTTIN)        ./pipe_shell
echo "foo"
sh-5.0$ foo
bash-5.0$ exit
exit
c linux bash fork exec
1个回答
1
投票

试着运行你的程序而不使用 -i 的选择 bash,虽然你不会看到提示。

过于简单的说,SIGTTIN的问题涉及到了 read(),一个控制TTY,和过程组。 对于细节,一个不错的起点是google.com的搜索词。linux SIGTTIN有一些文章深入研究了read tty pgrp.

要运行一个类似于你的小程序的交互式shell,并可能解决你的大程序的问题,你可以利用masterlave伪设备。 有一个相关的lib服务 forkpty(). 另外,有一个UNIXlinux实用程序,名为 script 记录交互式shell会话到一个常规文件中的源码。script 是一个很好的例子,读者+写手进程,主从伪设备,以及一个交互式的外壳。

© www.soinside.com 2019 - 2024. All rights reserved.