问题描述
sendfile()在内核空间内的两个文件描述之间复制数据.在我看到的某个地方,如果您在Linux中编写了Web服务器,则应使用send()和recv(),而不是使用write()和read().那么send()也使用内核空间吗?
我用来发送的任何用于发送的 - sendfile()或发送() - 在客户端,我将使用recv()对吗?
在另一面, Man Page 说:" send()和写入(2) )是标志的存在.在零标志参数的情况下,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,并且要将某些文件数据复制到套接字(例如,如果您是网络服务器服务文件),则可以这样写:
// 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 call)中.
.sendfile系统调用使我们可以跳过所有复制,并让内核直接读取文件数据并在一个Fell Swoop中发送到插座上:
sendfile(sockfd, filefd, NULL, BUFSIZE);
其他推荐答案
正如您指出的,唯一的区别是标志.发送/RECV用于网络,而读/写是任何文件描述符的通用I/O函数.发送仅是有用的VS写入时,当您要使用标志时,由于标志都是与网络相关的,因此在非网络文件描述符上呼叫发送是没有意义的(我也确定它是否有效).<<<<<<<
您也应该注意:
in_fd参数必须对应于支持的文件 mmap(2)类似于操作(即,它不能是插座).
这意味着您不能从插座复制(您可以复制到插座,并且在2.6.33之前,您必须复制到套接字).
其他推荐答案
send是 A>,说:
send()函数等于用空指针 dest_len参数,如果不使用标志,则写().
sendfile是Linux特异性的.它告诉内核从文件到插座进行零拷贝I/O. (请注意,仅当源fd是文件而目标是套接字;对于通用Linux特异性零副本I/O时,请阅读有关splice().)
.请注意,很少需要使用Linux特异性零拷贝I/O.标准和便携式read+write(或send)带有小的用户空间缓冲区(8K-16K)的循环通常会将该缓冲区保存在L1 CACHE中,从而使其等同于系统RAM的"零拷贝"观点.
因此,除非您的分析显示您的特定应用程序有所不同,请坚持标准接口.只是mho.