一个线程写入文件(甚至删除它),另一个线程同时调用该文件的 sendfile() 以获取重叠位置。
这里的预期行为是什么?
另外,如果我的理解是正确的,sendfile 调用只会向套接字添加一条记录(文件描述、位置、长度)并返回给调用者。 (还没有复制到套接字的缓冲区吗?),因此即使 sendfile() 在修改文件之前返回,操作系统也依赖于文件存在,直到文件完全发送。
那么在文件发送之前进行任何修改的结果是什么?
最佳答案
预期的行为是结果是不可预测的。 sendfile()
不是原子的,它实际上相当于编写自己的循环,从文件描述符调用 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摘录自一篇文章,解释了这些细节。
关于c - 如果在 sendfile() 正在进行时写入/更改文件,预期的行为是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48016137/