文件系统技术内幕:大数据时代海量数据存储之道
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.8.2 零拷贝的系统API

Linux通过sendfile()函数来使用零拷贝,sendfile()函数的语法格式如下:

在sendfile()函数中,int out_fd参数是输入数据的文件描述符,可以与前面的文件对应;int in_fd参数是输出数据的文件描述符,可以与前面的套接字对应。实际上,在目前的Linux中,输出数据的位置可以是网络,也可以是文件。

off_t*offset和size_t count两个参数分别是偏移和大小,这两个参数的组合用来确定从源文件的哪个位置读取多少数据。

虽然sendfile()函数可以直接在内核中实现文件内容的读取和数据的发送(写入),但是我们无法对数据进行修改。这样就限制了零拷贝技术的使用,毕竟很多场景是需要对原始文件做一些处理的。

Linux为了解决该问题实现了另一个API,也就是mmap()函数。通过mmap()函数可以将一个文件中一定区域的数据直接映射到进程的虚拟地址空间,并返回内存空间的地址,mmap()函数的语法格式如下:

在mmap()函数中,addr参数是期望返回的地址,其值可以为NULL,此时系统会自动分配地址;fd参数是对应的文件的文件描述符;offset参数是对应的数据在文件的位置;length参数是映射的长度;另外,还有两个确定附加特性的参数,prot和flags。

构建映射后,文件内容与用户态内存之间的关系如图2-22所示。这样我们就可以通过访问这个内存来访问文件数据,也就是当修改该内存的内容时,也就对文件的内容进行了修改。通过使用这种方式也就不需要使用write()函数和read()函数,避免内存拷贝和上下文切换的消耗。

图2-22 文件内容与用户态内存之间的关系