0

有人可以dup2在检查 if 后解释使用的fd[0] != STDIN_FILENO原因吗,因为据我了解fd[0] != STDIN_FILENO会失败并且dup2仍然会返回其他内容STDIN_FILENO,只是试图理解一些示例代码谢谢,如果有人可以为我解释 execlp 的使用那将是真棒。

int fd[2];
pid_t pid;

if(argc != 2) {
        fprintf(stderr, "Must be specify exactly 1 file\n");
        exit(0);
    }

    if(pipe(fd) < 0)
        exit(1);./ 

    pid = fork();

    switch (pid) {
        case -1:
            exit(1);
        case 0:
            close(fd[1]);
                        //here
            if(fd[0] != STDIN_FILENO) {
                if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
                    exit(3);
                close(fd[0]);
            }
            if(execlp("tr", "tr", "[a-z]", "[A-Z]", (char *) 0) < 0)
                exit(4);
            break;

        default:
            close(fd[0]);
                        // and here
            if(fd[1] != STDIN_FILENO) {
                if(dup2(fd[1], STDIN_FILENO) != STDIN_FILENO)
                    exit(5);
                close(fd[1]);
            }
            if(execlp("cat", "cat", argv[1], (char *) 0) < 0)
                exit(4);
            break;
    }
    return 0;
4

4 回答 4

3

目的是使标准输入(STDIN_FILENO,即 0)指向 fd[0] 指向的文件(管道的读取端)。首先检查它们是否已经不同......如果它们是相同的,代码会将 0 复制到 0,然后关闭 0 - 不好。如果它们不相同,请使用 dup2 使 STDIN_FILENO 指向 fd[0] 指向的位置。如果 dup2 成功,它返回它的第二个参数,因此如果 dup2 失败,则通过调用 exit 来进行检查。

你写

据我了解 fd[0] != STDIN_FILENO 会失败

完全不清楚你为什么“理解”这一点。仅当 fd[0] 包含 STDIN_FILENO(即 0)时它才会失败,但它不太可能因为它包含调用分配的文件描述符pipe

dup2 仍会返回除 STDIN_FILENO 以外的其他内容

如果成功,则 dup2 返回其第二个参数。除非失败,否则它不会返回除 STDIN_FILENO 以外的其他内容——为什么会这样?-- 在这种情况下它返回-1。

于 2013-03-28T09:06:57.383 回答
1

execlp基本上执行一个程序。该程序将从STDIN_FILENO(换句话说,fd 0)读取其输入。dup2close系统调用用于将或fd[0]文件描述符fd[1]移动到该数字。

于 2013-03-28T08:58:56.790 回答
1

检查是一种防御性编程实践,因为通常标准输入和标准输出之前已经打开,尽管如果它们在您进行调用fd[0] != STDIN_FILENO之前都已关闭,则会将两个描述符分配给管道(注意当管道是创建后,用于管道两端的文件描述符是下一个编号最小的描述符),因此检查将变得有意义。pipe()pipe()

于 2013-03-28T09:23:04.287 回答
0

该程序将在父进程中运行 cat,在子进程中运行 tr,它希望 cat 的输出被 tr 读取。

开始时,它打开一个管道,parent 将写入 fd[1],child 将从 fd[0] 读取,以便 parent 可以向 child 写入数据。

在父级中,它将 fd[1] 复制到标准输入;在子进程中,它将 fd[0] 复制到标准输入。

在child中,execlp运行tr,tr将从stdin读取,并且由于stdin已经被dup为fd[0],所以它实际上从管道中读取了cat的输出。

execlp()在当前进程中运行一个新的可执行文件。你可以man execlp为它的论点详细。

于 2013-03-28T08:57:01.697 回答