如果在sendfile()正在进行时写入/更改文件,则预期的行为是什么

时间:2017-12-29 00:47:53

标签: c linux sockets

一个线程写入一个文件(甚至删除它),另一个线程同时为该文件调用sendfile()以获得重叠位置。

这里的预期行为是什么?

另外,如果我的理解是正确的,sendfile调用只会向socket添加一条记录(文件描述,位置,长度)并返回给调用者。 (还没有复制到socket的缓冲区吗?),所以即使sendfile()在修改文件之前返回,OS依赖文件存在直到文件完全发送。

那么在发送文件之前修改的结果是什么?

1 个答案:

答案 0 :(得分:3)

预期的行为是结果不可预测。 sendfile()不是原子的,它实际上等同于编写自己的循环,从文件描述符调用read()并在套接字描述符上调用write()。如果某个其他进程在此过程中写入文件,您将获得旧内容和新内容的混合。可以把它想象成一个方便的功能,虽然它也应该显着提高效率,因为它不需要多个系统调用,并且可以直接在文件缓冲区和套接字缓冲区之间复制,而不是在应用程序之间来回复制缓冲区。因此,漏洞窗口应该小于read/write循环,但它仍然存在。

要避免此问题,您应该在执行写入的进程和调用sendfile()的进程之间使用文件锁定。所以序列应该是:

lock the file
call sendfile()
unlock the file

并且写作过程应该:

lock the file
write to the file
unlock the file

编辑:

实际上,它看起来并不简单,因为sendfile()将套接字缓冲区链接到文件缓冲区缓存,而不是将其复制到内核中。由于sendfile()没有等待发送数据,因此在文件返回后修改文件仍然会影响发送的内容。您需要检查应用层确认是否已收到所有数据。有关解释这些详细信息的文章摘录,请参阅Minimizing copies when writing large data to a socket