使用splice syscall时没有输出

使用splice syscall时没有输出,c,linux,system-calls,C,Linux,System Calls,我有以下代码: 定义GNU源 #包括 #包括 #包括 #包括 #包括 #包括 #包括 int main(int argc,字符**argv){ 如果(argc1){ 如果((fl=fcntl(1,F_GETFL))=-1)错误(1,“fcntl(1,GETFL)”); if(atoi(av[1])fl |=O|u追加; else fl&=~O_APPEND; 如果(fcntl(1,F_SETFL,fl))错误(1,“fcntl(1,SETFL,%x)”,fl); } 而((z=拼接(0,0,1,

我有以下代码:

定义GNU源
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,字符**argv){
如果(argc<2){
fputs(“错误:您必须提供一个\n文件名”,stderr);
返回1;
}
文件*handle=fopen(argv[1],“r”);
如果(!句柄){
perror(“打开文件时出错:”);
转到错误;
}
int handle_fd=fileno(句柄);
int filedes[2];
if(管道(filedes)){
perror(“创建管道时出错:”);
转到错误;
}
而(1){
ssize_t rc=拼接(handle_fd,NULL,filedes[1],NULL,BUFSIZ,0);
如果(rc==-1){
//发生错误
perror(“复制数据时出错:”);
转到错误;
}else if(rc==0){
打破
}
拼接(filedes[0],NULL,STDOUT_FILENO,NULL,BUFSIZ,0);
}
返回0;
错误:
如果(fclose(句柄)){
perror(“关闭文件时出错:”);
}
返回1;
}
当我运行它时,我没有得到任何输出。perror的电话也没有被触发,我也不明白为什么它不起作用


当我在GDB中运行程序时,它可以工作,但是当从shell运行时,它不会显示任何内容

您应该检查
STDOUT\u FILENO
是否未在追加模式下打开,或者第二个
拼接(2)
将失败,如its中所述:

EINVAL
目标文件以附加模式打开

是的,即使是tty,也会发生这种情况,
O\u APPEND
标志不应该有任何区别,这看起来非常像一个bug。或者至少是一个麻烦,特别是因为在插座或管道上设置
O_APPEND
标志时,
splice
并不关心

试着以同样的方式运行你的程序

./your_program file >/dev/tty
#包括
并将其添加到
main()
函数的开头:

if(isatty(1))fcntl(1,F_SETFL,fcntl(1,F_GETFL)和~O_APPEND);

请注意,
O\u APPEND
标志可能会在您的终端上意外打开:要检查它是否打开,请查看
/proc//fdinfo/

一个奇怪的例子是;-)


测试用例,
scat.c

/*
*通过拼接(2)将输入复制到输出的简单程序
*如果给定“1”参数,它将在标准输出上打开O_APPEND标志
*如果给定“0”参数,它将关闭该参数
*否则它将保持原样
*/
#定义_GNU_源1
#包括
#包括
#包括
#包括
内部主(内部ac,字符**av){
国际货币基金组织;
如果(ac>1){
如果((fl=fcntl(1,F_GETFL))=-1)错误(1,“fcntl(1,GETFL)”);
if(atoi(av[1])fl |=O|u追加;
else fl&=~O_APPEND;
如果(fcntl(1,F_SETFL,fl))错误(1,“fcntl(1,SETFL,%x)”,fl);
}
而((z=拼接(0,0,1,0,65536,0)))
如果(z<0)错误(1,“拼接”);
}
使用管道或插座作为输出时OK:

$ echo yup | ./scat 1 | cat
yup
$ nc -l -p 9999 &
[4] 23952
$ echo yup | ./scat 1 | nc -q0 localhost 9999
yup
[4]-  Done                    nc -l -p 9999

我只是浏览了一下您的代码,但是如果您试图打印的数据不包含换行符,您需要使用fflush stdout才能显示文本
fflush(stdout)
。您忘记检查第二个拼接的状态。关于:
FILE*handle=fopen(argv[1],“r”);如果(!handle){perror(“打开文件时出错”);转到错误;
错误:如果(fclose(handle)){
由于无法打开文件,尝试关闭它将导致崩溃。即,发布代码的逻辑流不正确。需要做的事情之一是调用
关闭(filedes[0])
关闭(filedes[1]);
但是发布的代码在第二次调用:
splice()
时无法执行这些操作,发布的代码无法检查返回值。
$ strace -e trace=fcntl make
fcntl(1, F_GETFL) = 0x48002 (flags O_RDWR|O_LARGEFILE|O_NOATIME)
fcntl(1, F_SETFL, O_RDWR|O_APPEND|O_LARGEFILE|O_NOATIME) = 0
...
$ cc -Wall scat.c -o scat

$ echo yup | ./scat
yup
$ echo yup | ./scat 1
scat: splice: Invalid argument
$ echo yup | ./scat
scat: splice: Invalid argument
$ echo yup | ./scat 0
yup
$ echo yup | ./scat
yup
$ echo yup | ./scat 1 | cat
yup
$ nc -l -p 9999 &
[4] 23952
$ echo yup | ./scat 1 | nc -q0 localhost 9999
yup
[4]-  Done                    nc -l -p 9999