sendfile()在内核空间内的两个文件描述符之间复制数据。我在某处看到,如果你在linux中用C语言编写web服务器,你应该使用send()和recv()而不是write()和read()。那么send()是否也使用内核空间呢?
无论我使用什么发送- sendfile()或send() -在客户端,我将使用recv(),对吗?
另一方面,man page说:“send()和write(2)之间唯一的区别就是标志的存在。有了零个标志参数,send()就等同于write(2)。”
发布于 2012-11-04 11:09:05
如果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);发布于 2012-11-04 11:07:11
正如您所指出的,唯一的区别是旗帜。send/recv用于联网,而read/write是任何文件描述符的通用I/O函数。只有当你想使用一个标志时,send才对write有用,因为所有的标志都是与网络相关的,在非网络的文件描述符上调用send是没有意义的(我也不确定它是否有效)。
此外,您还应注意:
in_fd参数必须对应于支持mmap(2)-like操作的文件(即它不能是套接字)。
这意味着你不能从套接字复制(你可以复制到套接字,在2.6.33之前你必须复制到套接字)。
发布于 2012-11-04 11:11:38
send是specified by the POSIX standard,它说:
()函数等同于带有空指针dest_len参数的sendto(),如果没有使用标志,则相当于write()。
sendfile是特定于Linux的。它告诉内核执行从文件到套接字的零拷贝I/O。(请注意,只有当源fd是文件而目标是套接字时,它才有效;对于通用的特定于Linux的零拷贝I/O,请阅读splice()。)
注意,很少需要使用特定于Linux的零拷贝I/O。具有小用户空间缓冲区(8K-16K)的标准和可移植的read+write (或send)循环通常会将该缓冲区保存在L1缓存中,从系统内存的角度来看,它等同于“零拷贝”。
因此,除非您的概要分析显示您的特定应用程序有所不同,否则请坚持使用标准接口。就是MHO。
https://stackoverflow.com/questions/13215656
复制相似问题