我正在编写一个程序,其中多个线程可能同时从文件中读取。没有线程写入该文件,但它们可能各自将其内容复制到单独的内存段。
为了实现这一点,我需要使用一个 API,为我想要读取的文件提供一个文件描述符。我正在用 C 读取文件的块read功能。手册页说:“成功时,返回读取的字节数(零表示文件结尾),并且文件位置将按此数字前进。”不过,我找不到任何关于文件位置的前进是否是线程安全的明确信息。
假设我有线程 T1 和线程 T2 一次读取文件的 1 个字节。如果read()
是线程安全的,我期望以下内容:
T1: read() => file position == 1
T2: read() => file position == 1
T1: read() => file position == 2
T2: read() => file position == 2
...
但我担心如果是not线程安全,那么可能会发生以下情况:
T1: read() => file position == 1
T2: read() => file position == 2
T1: read() => file position == 3
T2: read() => file position == 4
...
如果有帮助,每个线程将使用相同的文件描述符。换句话说,它是使用以下命令打开文件的 APIopen()
。然后,正在读取文件的线程根据客户端请求获取该文件描述符。如果每个线程都存储自己的有关文件位置的信息,那么应该没问题。我只是找不到任何有关文件位置和位置的信息read()
弄清楚它是什么。
read
它本身是线程安全的,但这并不一定意味着您想要用它做的事情是线程安全的。根据 POSIX (2.9.7 线程与常规文件操作的交互):
当以下所有函数在常规文件或符号链接上操作时,在 POSIX.1-2008 中指定的效果中,彼此之间应是原子的:
...
(read
在下面的列表中。)
除此之外,这意味着读取数据和前进当前文件位置相对于彼此而言是原子的,并且读取的每个字节将被读取一次。然而,还有其他一些考虑因素可能会让事情变得复杂,特别是:
-
短读:read(fd, buf, n)
不需要阅读n
字节。它可以读取 1 到 1 之间的任何位置n
字节,当您再次调用它来读取其余部分时,第二次读取相对于第一次读取不再是原子的。
-
其他文件类型:POSIX仅保证原子性read
适用于常规文件以及其他一些类型。 Linux 等特定系统probably有更强的保证,但我会保持谨慎。
最好使用pread
函数(您可以在其中指定要读取的文件偏移量without必须寻找该位置,并且结果文件位置保持不变)或对文件访问执行锁定以避免此类问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)