【发布时间】:2016-07-01 16:18:44
【问题描述】:
我正在使用sendfile() 在 Linux 6.4 下复制大文件来测试性能。
我的代码遵循以下逻辑,使用gcc编译
read_fd = open (argv[1], O_RDONLY);
fstat(read_fd, &stat_buf);
write_fd = open (argv[2], O_WRONLY | O_CREAT, stat_buf.st_mode);
left_to_write = stat_buf.st_size;
while (left_to_write > 0) {
written=sendfile (write_fd, read_fd, &offset, stat_buf.st_size);
if (written == -1)
return -1;
else {
left_to_write -= written;
bytes_done=stat_buf.st_size-left_to_write;
printf("%ld bytes written, %ld bytes left to write\n", written, left_to_write);
}
}
close(read_fd);
close(write_fd); /* this takes minutes */
sendfile() 调用非常快;我可以看到它大约每 5 秒写入 2GB 的块。
当while 循环结束时,它会在close(output) 停留几分钟,然后才能成功完成。
为什么close(output) 需要这么长时间才能运行?它是在刷新缓冲区吗?我怎样才能让它更快?
【问题讨论】:
-
只是一点点数学运算:“它大约每 5 秒写入 2GB 的块。”表示 400MB/秒。你用什么媒介?这对于 HDD 来说太快了,而对于消费级 SSD 来说仍然相当先进。文件有多大?提供更多信息,即minimal reproducible example。见How to Ask。
-
您的
open电话没有多大意义;他们应该是input = open(…);和output = …something that opens a stream socket…吗?此外,sendfile()的参数与 BSD 上的参数不同——这是因为您的代码是伪代码还是因为 BSD 和 Linux 存在分歧? (BSD 接口:int sendfile(int fd, int s, off_t offset, off_t *len, struct sf_hdtr *hdtr, int flags);— 我特别注意到输入文件描述符(fd)在 BSD 中位于输出流套接字(s)之前。) -
回答我自己:Linux 的
sendfile()与 BSD (Mac OS X) 版本完全不同。 Linux 使用不同的标头(<sys/sendfile.h>而不是 Mac OS X 上的<sys/uio.h>),声明为ssize_t sendfile(int out_fd, int in_fd, off_t * offset, size_t count);。因此,除非您希望将代码移植到其他系统,否则我之前的评论并不重要——如果您是,请小心! -
更复杂的问题是,FreeBSD
sendfile()与 Mac OS Xsendfile()不同。好好玩! (这是一个让读者找出与 Mac OS X 定义匹配的 BSD 变体(如果有的话)的练习。主要是,这是一个“程序员当心”通知——sendfile()因系统而异。) -
@JonathanLeffler:可能是因为
sendfile不是任何标准的一部分 :-)
标签: c linux file linux-kernel