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

标签 c linux sockets

一个线程写入文件(甚至删除它),另一个线程同时调用该文件的 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/

相关文章:

linux - 瓶颈问题的 epoll 架构问题

c - 数据类型 - socklen_t、sa_family_t

c - 处理 GetDIBits() 返回的像素缓冲区的正确方法是什么?

linux - Crontab 权限被拒绝

java - 在 Linux 上执行 grep 命令并捕获结果

python - 如何选择我在 Linux 上运行的 python 版本?

python - SYN 数据包没有得到回复(Python)原始套接字

c - 为什么 char *s = "string"在不是 const 时不显示错误或警告

c - 单行 fprintf 命令是线程安全的吗?

c - 指向结构 C 指针的指针