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

问题描述 投票:1回答:1

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

这里的预期行为是什么?

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

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

c linux sockets
1个回答
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

© www.soinside.com 2019 - 2024. All rights reserved.