在C编程中,可以使用tee将FIFO重定向到标准输出吗?

4
我想将一个FIFO重定向到标准输出,我阅读了文档http://man7.org/linux/man-pages/man2/tee.2.html
文档中写道tee(int fd_in, int fd_out,...),但是当我将FIFO文件描述符作为第一个参数传递时,它会报无效错误。
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
int main() {
    int num = 0, fd;
    char fifo[] = "/tmp/tmpfifo";

    fd = open(fifo, O_RDONLY, 0644);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }
    num = tee(fd, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
    if (num < 0) {
        perror("tee");
        exit(EXIT_FAILURE);
    }
    fprintf(stderr,"%d\n", num);
    return 0;
}

控制台显示:tee:无效参数。第一个参数应该是stdin吗?

1
我认为你想要使用dup2函数。 - Some programmer dude
顺便问一下,你确定传递给 open 的标志没问题吗?应该只有 O_RDONLYO_WRONLY 吧?你的程序是否要与自身通信?你是如何创建 FIFO 的? - Some programmer dude
如果我仍然使用tee()系统调用,那么这是否有效? - code_worker
我将RDWR修复为RDONLY,但它再次无法工作。 如果我按照文档下面的示例,它可以工作。该示例将STDIN和STDOUT放在前两个参数中。 - code_worker
@Jean-BaptisteYunès 我应该像下面这样将STDOUT_FILENO设置为管道 - code_worker
显示剩余2条评论
2个回答

2
确保你的 stdout 是一个管道。
rm -f /tmp/tmpfifo
mkfifo /tmp/tmpfifo
echo hello world > /tmp/tmpfifo & 
./a.out | cat #ensure that the program's stdout is a pipe

这个命令(其中 a.out 是你的程序)对我来说可行。


1
它可以工作。我原以为 STDOUT_FILENO 会在控制台上打印。 - code_worker

1

tee()的手册页面:

tee()函数将从文件描述符fd_in所引用的管道中复制最多len个字节的数据到文件描述符fd_out所引用的管道中。

因此,两个文件描述符都必须引用管道。

在调用tee()时:

tee(fd, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);

fd 是一个先进先出(FIFO)管道,而这个管道本身也是一个管道,但 STDOUT_FILENO 可能不是一个管道。

STDIN_FILENOSTDOUT_FILENO 不一定是管道。


如果你想让STDOUT_FILENO指向一个管道,你可以在shell命令行中以以下方式运行你的程序:

yourProgram | cat

FIFO不是管道吗? - code_worker
@code_worker 但 STDOUT_FILENO 不一定是一个管道。 - JFMR
我知道。但是我打开了一个FIFO,而这个FIFO是一个管道。所以我认为把FIFO放到第一个参数应该是正确的,对吗? - code_worker
1
@code_worker 你可以将程序执行为 ./myProgram | cat,这时 STOUT_FILENO 就指向一个管道。 - JFMR
实际上,shell 创建了管道,你的程序只是继承了一个文件描述符,该描述符对应于该管道。 - JFMR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接