-->

C,的sendfile()和send()的区别?(C, sendfile() and

2019-08-02 07:09发布

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

无论我用来发送 - 的sendfile()或发送() - 在客户端我会使用的recv()吗?

在另一面, 男子页说:“发送的唯一区别()和write(2)为标志的存在与零个flags参数,send()方法等同于写(2)。”

Answer 1:

如果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服务器),那么你可能会写这样的:

// 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);


Answer 2:

正如你所指出的那样,唯一的区别就是标志。 发送/ recv的是网络,而读/写的任何文件描述符的通用I / O功能。 发送才有用VS写,当你想使用一个标志,因为这些标志都与网络相关,它没有任何意义打电话发在非网络文件描述符(我也不是知道是否它甚至有效)。

还应注意:

所述in_fd参数必须对应于支持MMAP(2) - 样的操作(即,它不能是插座)的文件。

这意味着你不能从插座复制(可以复制到一个插座和之前2.6.33必须复制到一个插座)。



Answer 3:

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。



文章来源: C, sendfile() and send() difference?