今天学到了一个新系统调用:sendfile,它专门用来在两个文件描述符之间传输数据.
#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
在引入 sendfile
系统调用之前,要传输文件内容(拷贝文件或通过网络传输文件)往往需要经过下面几个步骤:
- 调用
read
系统调用读取文件内容,这会产生一次上下文切换 - 将内核中的数据拷贝到用户空间
- 调用
wirte
函数调用写入数据,这又会产生一次上下文切换
如此算来,至少要经过两次上下文切换和一次数据拷贝的动作,甚至在文件内容巨大的时候这个流程可能需要流转多次。
考虑到拷贝文件这个动作实在太过常见,因此系统引入了 sendtofile
系统调用,这样只需要一个系统调用就行了,在传输巨大文件时能够极大地节省CPU时间。
另外,通过strace跟踪系统调用,居然发现 cp
和 dd
命令还是用的read和write的方式来进行文件之间的数据传输的。
date >d.tmp
strace cp d.tmp d1.tmp 2>&1
echo '------------------------------------'
strace dd if=d.tmp of=d.tmp bs=512 2>&1