关于如何结束 Execvp 调用的困惑

标签 c process io

我无法获得使用 execvp 调用的程序的完整输出。在这里,我基本上是在尝试用一个可以过滤输入和输出的程序来包装任何程序:

#define BUF_SIZ 8192
int main(int argc, char **argv) {
    int outp[2]; // r, w
    int inp[2];
    pid_t pid;
    char buf[BUF_SIZ];
    fd_set fds;
    struct timeval tv;

    tv.tv_sec = 0;
    tv.tv_usec = 300000;
    if (pipe(outp) < 0 || pipe(inp) < 0) return 1;
    if ((pid = fork()) < 0) return 2;
    else if (pid) {
        close(outp[1]);
        close(inp[0]);
        dup2(outp[0], STDIN_FILENO);
        dup2(inp[1], STDOUT_FILENO);
        execvp(*(argv + 1), argv + 1);
    } else {
        while (1) {
            FD_ZERO(&fds);
            FD_SET(STDIN_FILENO, &fds);
            FD_SET(inp[0], &fds);
            if (select(inp[0] + 1, &fds, NULL, NULL, &tv) < 0) exit(3);
            if (FD_ISSET(STDIN_FILENO, &fds))
                write(outp[1], buf, read(STDIN_FILENO, buf, BUF_SIZ));
            if (FD_ISSET(inp[0], &fds))
                write(STDOUT_FILENO, buf, read(inp[0], buf, BUF_SIZ));
        }
    }

    return 0;
}

如果我使用该程序调用 shell sh,我会得到以下输出(我没有收到提示):

$ ./shell sh    
echo "test"
test
^C

如果我尝试运行 Python;我没有收到任何输出:

$ ./shell python
print "test"
^C

为什么我没有收到(大部分)输出?

最佳答案

问题是,您的 shell 和 python 解释器的标准输入不是终端。在这种情况下,这两个程序的行为有点不同:

  • shell 不发出提示
  • Python 想要首先从标准输入(直到 EOF)读取它的完整脚本

例如,要使 python 脚本正常工作,您必须从您的 stdin 捕获 EOF(读取返回 0),在这种情况下关闭 python 进程的 stdin。然后,您可以通过在终端上按 CTRL+D 来调用 EOF。

if (select(inp[0] + 1, &fds, NULL, NULL, &tv) < 0) exit(3);
if (FD_ISSET(STDIN_FILENO, &fds)) {
    int st = read(STDIN_FILENO, buf, BUF_SIZ));
    if (st > 0)
        write(outp[1], buf, st);
    else {
        close(outp[1]);
    ...

如果您想要一个交互式终端,您必须打开一个新的伪终端,forkpty(3) 将为您完成大部分工作。

关于关于如何结束 Execvp 调用的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35564681/

相关文章:

读入文本文件并显示除所有空行和注释外的每一行的 C 程序

c - 有什么办法可以避免使用break;在 while 循环中,当测试包含 scanf() 时?

c - 在 c 中使用 printf 和\r 创建加载条时,如何保持包含 "moving"代码

java - 在进程关闭之前读取所有进程输出

android - Messenger Service 可以用于跨应用程序 IPC 吗?

java - 无法在新行中写入字符串

c# - 如何防止Directory.GetFiles到 "check"回收站等 "unsafe"地方?

c++ - Win32 函数可以在同一个线程上异步运行吗?

c# - 在 C# 进程中指定参数

performance - 写入操作成本