首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C,sendfile()和send()有什么区别?

C,sendfile()和send()有什么区别?
EN

Stack Overflow用户
提问于 2012-11-04 10:59:47
回答 3查看 23.3K关注 0票数 19

sendfile()在内核空间内的两个文件描述符之间复制数据。我在某处看到,如果你在linux中用C语言编写web服务器,你应该使用send()和recv()而不是write()和read()。那么send()是否也使用内核空间呢?

无论我使用什么发送- sendfile()或send() -在客户端,我将使用recv(),对吗?

另一方面,man page说:“send()和write(2)之间唯一的区别就是标志的存在。有了零个标志参数,send()就等同于write(2)。”

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 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/recvwrite/read都没有区别。

sendfile系统调用是一种优化。如果你有一个套接字sockfd和一个常规的文件filefd,并且你想把一些文件数据复制到套接字中(例如,如果你是一个提供文件的web服务器),那么你可以这样写:

代码语言:javascript
复制
// 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系统调用使我们可以跳过所有复制,并让内核直接读取文件数据,并一举将其发送到套接字:

代码语言:javascript
复制
sendfile(sockfd, filefd, NULL, BUFSIZE);
票数 38
EN

Stack Overflow用户

发布于 2012-11-04 11:07:11

正如您所指出的,唯一的区别是旗帜。send/recv用于联网,而read/write是任何文件描述符的通用I/O函数。只有当你想使用一个标志时,send才对write有用,因为所有的标志都是与网络相关的,在非网络的文件描述符上调用send是没有意义的(我也不确定它是否有效)。

此外,您还应注意:

in_fd参数必须对应于支持mmap(2)-like操作的文件(即它不能是套接字)。

这意味着你不能从套接字复制(你可以复制到套接字,在2.6.33之前你必须复制到套接字)。

票数 3
EN

Stack Overflow用户

发布于 2012-11-04 11:11:38

sendspecified 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。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13215656

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档