我正在尝试在Linux 2.6.32下测试sendfile()
系统调用,以便在两个常规文件之间对数据进行零复制。
据我了解,它应该工作:从2.6.22开始,sendfile()
已经使用splice()
实现,输入文件和输出文件都可以是常规文件或套接字。
以下是sendfile_test.c
的内容:
#include <sys/sendfile.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char **argv) {
int result;
int in_file;
int out_file;
in_file = open(argv[1], O_RDONLY);
out_file = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
result = sendfile(out_file, in_file, NULL, 1);
if (result == -1)
perror("sendfile");
close(in_file);
close(out_file);
return 0;
}
当我运行以下命令时:
$ gcc sendfile_test.c
$ ./a.out infile outfile
输出
sendfile: Invalid argument
运行时
$ strace ./a.out infile outfile
输出包含
open("infile", O_RDONLY) = 3
open("outfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
sendfile(4, 3, NULL, 1) = -1 EINVAL (Invalid argument)
我做错了什么?
答案 0 :(得分:6)
您忘了检查argc
是否等于3
,即您是按名称argv[2]
打开输出文件,但只给您的程序一个参数(并且您没有检查对于open(2)
之后的错误。)
您可以使用strace(1)
找出哪个系统调用失败。
对我来说这看起来像旧内核。相同的源(模数错误检查)在2.6.33.4 #3 SMP
下正常工作。另外,你只复制一个字节的任何特殊原因?
#include <sys/sendfile.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main( int argc, char *argv[] )
{
int in_file, out_file;
if ( argc != 3 )
{
fprintf( stderr, "usage: %s <in-file> <out-file>\n", argv[0] );
exit( 1 );
}
if (( in_file = open( argv[1], O_RDONLY )) == -1 ) err( 1, "open" );
if (( out_file = open( argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644 )) == -1 )
err( 1, "open(2)" );
if ( sendfile( out_file, in_file, NULL, 4096 ) == -1 ) err( 1, "sendfile" );
exit( 0 );
}
跟踪:
nickf@slack:~/csource/linux/splice$ cc -Wall -pedantic -ggdb -g3 -o sf sndf.c
nickf@slack:~/csource/linux/splice$ strace ./sf Makefile mm
...
open("Makefile", O_RDONLY) = 3
open("mm", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
sendfile(4, 3, NULL, 4096) = 239
exit_group(0) = ?
nickf@slack:~/csource/linux/splice$ diff Makefile mm
nickf@slack:~/csource/linux/splice$