1

如何获得execve()可以运行“vi”等的分叉子进程并将所有 IO 重定向到父进程?

我正在尝试将 shell 从嵌入式 Linux 进程传递到通过网络连接的 PC 软件接口。shell 进程的 IO 被打包到特定于应用程序的消息中,以便通过我们现有的协议进行网络传输。

首先,我只是简单地使用pipe2()fork()dup2()和重定向 IO execve()。这在远程端没有给我一个 tty,所以screen, etc. 没有用。

现在我正在使用forkpty,并且screen大部分都可以使用,但许多其他的却没有(vi,stty等)。看来当前的问题是子进程不控制 tty。

我一直在尝试 TIOCSCTTY,但运气不佳。

这或多或少是我所拥有的:

bool ExternalProcess::launch(...)
{
    ...

    winsize winSize;

    winSize.ws_col = 80;
    winSize.ws_row = 25;
    winSize.ws_xpixel = 10;
    winSize.ws_ypixel = 10;

    _pid = forkpty(&_stdin, NULL, NULL, &winSize);

    //ioctl(_stdin, TIOCNOTTY, NULL);

    if (!_pid && (_pid != -1))
    {
        // this is the child process
        char tty[4096];
        strncpy(tty, ttyname(STDIN_FILENO), sizeof(tty));
        tty[sizeof(tty)-1]=0;

        FILE* fp = fopen("debug.txt", "wt");    // no error checking - temporary test code
        fprintf(fp, "slave TTY %s", tty);

        //if (ioctl(_stdin, TIOCSCTTY, NULL) < 0)
        if (ioctl(STDIN_FILENO, TIOCSCTTY, NULL) < 0)
        {
            fprintf(fp, "ioctl() TIOCSCTTY %s\n", strerror(errno));
            fflush(fp);
        }
        else
        {
            fprintf(fp, "SET CONTROLLING TTY!");
            fflush(fp);
        }

        fclose(fp);

        // command, args, env populated elsewhere
        execve(command, args, env);

        ...

        // fail path
        _exit(-1);
        return false;
    }

    _stdout = _stdin;

    ...

    // enter select() loop reading/writing _stdin, _stdout
}

我在调试文件中得到结果,例如:

slave TTY /dev/pts/5
SET CONTROLLING TTY!

但仍有许多应用程序因tcsetattr()错误而失败。我是否认为这是一个控制 tty 问题?我如何解决它?

编辑

小修正。当我在 STDIN_FILENO 上执行 ioctl TIOCSCTTY 时,它就像在上面的调试文件中一样工作,但是返回父进程的 IO 重定向被中断。

编辑 2

好吧,我开始更好地理解这一点。查看 tcsetattr() 后面的 ioctl 的内核源代码,我正在调用的进程在尝试更改 tty 时被发送 SIGTTIN 和 SIGTTOU。

只有前台进程可以做到这一点,并且它们就像后台进程一样运行。我尝试在分叉之后和 execve() 之前将这些信号设置为 SIG_IGN,但这不起作用。我理解这个的语义,但是在我的重定向场景中,execve() 的进程就像它们是前台进程一样是安全的。问题是……如何做到这一点?我将继续在内核代码中寻找线索。

4

1 回答 1

1

啊! 它是 bash,我用 execve() 调用的 shell。

如果它检测到 stderr 没有附加到 tty,那么它会进入这种特殊模式,其中子进程会导致 SIGTTOU。

我发现这里提到了这个问题

当我停止从 tty 重定向 stderr 时,它现在似乎按计划工作。

于 2013-03-05T04:02:27.983 回答