c - 在使用 dup2() 重定向标准输入后调用 execve() 时发生了什么?

标签 c linux shell

我正在模拟一个迷你版的 shell。当谈到用管道执行程序时,有些事情让我感到困惑。我学习了 fork()、execve()、pipe() 和 dup2()。我想我可以调用 pipe() 来构建一个未命名的管道,然后调用 fork(),然后使用 dup2() 将标准输出重定向到管道的写入端,使用 execve() 运行目标程序。当涉及到第二个程序时,我可以将标准输入重定向到管道的读取端,并输出回原始标准输出,然后使用 execve() 运行目标。但实际上,当我使用“ls -l”作为第一个程序,使用“wc -l”作为第二个程序时,它失败了。但是,如果第二个是“猫”,它就会正常工作。那么,当我在使用 dup2() 重定向标准输入后调用 execve() 时发生了什么?还是我的程序有其他问题?

更新:我发布了一些用于验证我的想法的代码。就这个。 更重要的是,我没有使用 waitpid() 来确保这些东西按顺序运行。

int fd[2];

int main(int argc, char **argv, char **envp) {
    int fd[2];
    pipe(fd);
    int sfd[2];
    sfd[1] = dup(STDOUT_FILENO);
    sfd[0] = dup(STDIN_FILENO);
    int pid;

    pid = fork();
    if (pid == 0) {
        // child
        dup2(fd[1], STDOUT_FILENO);
        close(fd[0]);
        close(fd[1]);
        char *cmd[] = {
            "/usr/bin/ls", "-l", NULL
        };
        execve("/usr/bin/ls", cmd, envp);
    } else {
        // parent
        int status;
        waitpid(pid, &status, 0);
    }

    pid = fork();
    if (pid == 0) {
        // child
        //dup2(fd[1], STDOUT_FILENO);
        dup2(fd[0], STDIN_FILENO);
        close(fd[0]);
        close(fd[1]);
        char *cmd[] = {
            "/usr/bin/wc", "-l", NULL
        };
        execve("/usr/bin/wc", cmd, envp);
    } else {
        // parent
        int status;
        //waitpid(pid, &status, 0);
    }

    /*pid = fork();
    if (pid == 0) {
        // child
        dup2(fd[0], STDIN_FILENO);
        close(fd[0]);
        close(fd[1]);
        char *cmd[] = {
            "/usr/bin/wc", "-l", NULL
        };
        execve("/usr/bin/wc", cmd, envp);
    } else {
        // parent
        int status;
        //waitpid(pid, &status, 0);
    }*/


    return 0;
}

最佳答案

“失败”是什么意思?

如果我尝试我得到:

/usr/bin/wc: standard input: Input/output error
1

那是因为 ls 不在我系统的 /usr/bin 中:

$ which wc cat ls
/usr/bin/wc
/bin/cat
/bin/ls

如果我解决了这个问题,我会得到:

10

作为我的输出。

关于c - 在使用 dup2() 重定向标准输入后调用 execve() 时发生了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33943402/

相关文章:

macos - 在 Mac 上,在 shell 中,我如何知道我有一个 GUI?

bash - 带空格的 Shell 变量,引用单个命令行选项

python - 量化文件更改

c++ - (unsigned char)str 与 str + 0xff 或 (unsigned int)value 与 value + 0xffff 哪个是更快的首选方法?

c - 在压缩的 PE 中,数据部分的虚拟大小必须与原始大小匹配吗?

linux - 删除包含字符串后跟 x 个数字的行

指向结构的指针的 C typedef

linux - 使用 valgrind 查找不断增长的 realloc

arrays - 如何索引函数中的输出

shell - 将 ANSI 彩色代码文本发送到 3 个输出 : screen, 文件和文件过滤 ANSI 代码