阅读Linux 系统调用的手册页sendfile
,我想知道调用程序是否有可能知道何时in_fd
处于 EOF。据推测,这可以通过返回值 0 来表示,但这会导致返回值 0 的实际含义的问题。如果sendfile
是 like write
,则返回值 0 仅表示复制了 0 个字节。但是,如果sendfile
是 like read
,那么返回值 0 将意味着 EOF。必须事先知道要复制多少字节in_fd
才能out_fd
使用sendfile
?sendfile
返回0是什么意思?
4 回答
我认为没有任何直接的方法可以知道这一点,但这并不重要。通常,您会通过找到输入文件大小stat/fstat
并使用它来计算您的传输。插座端对您来说无关紧要。
这应该是有问题的唯一情况是如果您要传输正在增长或缩小的文件。鉴于输入文件必须是 mmap 的,并且在这些情况下使用 mmap 可能发生的坏事(没有一些聪明的代码)你可能不应该在这些情况下使用 sendfile。
您可以使用偏移参数进行读取计数。
根据手册页
如果 offset 不为 NULL,则它指向一个保存文件偏移量的变量,sendfile() 将从该文件偏移量开始从 in_fd 读取数据。当 sendfile() 返回时,此变量将设置为读取的最后一个字节之后的字节偏移量。如果offset不为NULL,则sendfile()不会修改in_fd的当前文件偏移量;否则调整当前文件偏移量以反映从 in_fd 读取的字节数。
count 是要在文件描述符之间复制的字节数。
返回值 如果传输成功,则返回写入 out_fd 的字节数。出错时,返回 -1,并适当设置 errno。
是的,这意味着返回值 0 表示没有数据复制到写入套接字。
当发送的字节数为 0 时,您可以假设已达到 EOF:
sent = sendfile(out_fd, in_fd, &offset, nbytes);
if (sent == 0) {
// EOF
...
}
这种假设也适用于非阻塞套接字的情况。
就我而言,遇到文件被rsync截断,应用程序同时使用sendfile传输文件。我发现应用程序在这种情况下吃 cpu 100%,我修复了我的代码参考下面的文章,问题消失了。 http://www.linuxjournal.com/article/6345
关键是使用 F_SETLEASE 为您的应用程序获取文件租约。