的sendfile()内核空间内的两个文件描述符的之间复制数据。 某处我看到,如果你在Linux下编写一个Web服务器用C,你应该使用send()和recv()而不是使用write()和read()。 那么,在send()使用的内核空间呢?
无论我用来发送 - 的sendfile()或发送() - 在客户端我会使用的recv()吗?
在另一面, 男子页说:“发送的唯一区别()和write(2)为标志的存在与零个flags参数,send()方法等同于写(2)。”
的sendfile()内核空间内的两个文件描述符的之间复制数据。 某处我看到,如果你在Linux下编写一个Web服务器用C,你应该使用send()和recv()而不是使用write()和read()。 那么,在send()使用的内核空间呢?
无论我用来发送 - 的sendfile()或发送() - 在客户端我会使用的recv()吗?
在另一面, 男子页说:“发送的唯一区别()和write(2)为标志的存在与零个flags参数,send()方法等同于写(2)。”
如果fd
是一个套接字文件描述符,那么这些系统调用是相同的:
send(fd, data, length, 0)
是相同的write(fd, data, length)
recv(fd, data, length, 0)
是相同的read(fd, data, length)
所以,除非你需要设置一个非零flags
参数,这都没有区别是否使用send/recv
或write/read
。
该sendfile
系统调用是一个优化。 如果你有一个插座sockfd
和普通文件filefd
并要一些文件数据复制到插座(例如,如果你服务了文件的Web服务器),那么你可能会写这样的:
// Error checking omitted for expository purposes
while(not done)
{
char buffer[BUFSIZE];
int n = read(filefd, buffer, BUFSIZE);
send(sockfd, buffer, n, 0);
}
然而,这是低效的:这涉及到内核中的文件数据复制到用户空间(在read
调用),然后同样的数据拷贝回内核空间(在send
呼叫)。
该sendfile
系统调用让我们跳过所有的复制和有内核直接读取文件数据,并一举将其发送插槽上:
sendfile(sockfd, filefd, NULL, BUFSIZE);
正如你所指出的那样,唯一的区别就是标志。 发送/ recv的是网络,而读/写的任何文件描述符的通用I / O功能。 发送才有用VS写,当你想使用一个标志,因为这些标志都与网络相关,它没有任何意义打电话发在非网络文件描述符(我也不是知道是否它甚至有效)。
还应注意:
所述in_fd参数必须对应于支持MMAP(2) - 样的操作(即,它不能是插座)的文件。
这意味着你不能从插座复制(可以复制到一个插座和之前2.6.33必须复制到一个插座)。
send
的POSIX标准规定 ,其中说:
发送()函数等同于SENDTO()与一个空指针dest_len参数,并写入()如果不使用标志。
sendfile
是Linux特有。 它告诉内核从文件到插座做零拷贝I / O。 (注意:当源fd是一个文件和目标是一个插座,它仅适用;对于通用的Linux特有的零拷贝I / O,了解splice()
请注意,很少需要使用Linux特有的零拷贝I / O。 标准和便携式read
+ write
(或send
一个小的用户空间缓冲区(8K-16K))循环一般会保持在L1高速缓存缓冲区,使之等同于从视系统RAM的点“零拷贝”。
所以,除非您的分析显示为具体应用的不同,坚持标准接口。 只是MHO。