| vs < 对于标准输入和标准输出,在 C 中使用 splice、pipe 和 tee 命令

| vs < for stdin and stdout with splice, pipe and tee command in C

#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h> 
#include <stdio.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
int main(int argc, char ** argv) {
    int fd[2];
    int len,slen,len_out,slen_out;
    pipe(fd);
  
    int f=open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644);

    len=tee(STDIN_FILENO,fd[1],INT_MAX,SPLICE_F_MOVE);
    
    while (len > 0) {
        slen = splice(fd[0], NULL, f, NULL, len, SPLICE_F_MOVE);
        len -= slen;
        if(slen==0)
            break;
    }   

    len_out = tee(STDIN_FILENO,fd[1],INT_MAX,SPLICE_F_MOVE);    

    while (len_out > 0) {
        slen_out = splice(fd[0], NULL, STDOUT_FILENO, NULL, len_out, SPLICE_F_MOVE);
            len_out -= slen_out;
            if(slen_out==0)
                break;
    }

    close(fd[1]);
    close(fd[0]);
    close(f);  
    
    return 0;
}

当我 运行 我的程序带有管道 ex: cat test.txt| ./a.out result.txt test.txt 中的内容进入 result.txt

但使用另一种方法,例如:./a.out result.txt <test.txt 什么都没发生。难道不应该表现得一样吗?

另外,当我拼接到STDOUT_FILENO时,它从不在标准输出上打印,我不明白为什么。

感谢您的帮助

两种方法不等价:

  • cat in.txt | 实际上会创建一个 pipe 来满足您的程序
  • < in.txt 只会 open 给定的文件并将其提供给 fd 0

在第二种情况下,tee returns -1perror 抱怨参数无效。

您可以使用 fstat 检查 fd 0 的性质并检查 st_mode 值:

    struct stat statbuf;
    fstat(STDIN_FILENO, &statbuf);
    
    if (statbuf.st_mode & S_IFREG) 
        printf("regular file");
    
    if (statbuf.st_mode & S_IFIFO) 
        printf("pipe");