【问题标题】:Thread Safety of Reading a File读取文件的线程安全
【发布时间】:2020-03-03 09:38:55
【问题描述】:

所以我的最终目标是允许多个线程从头到尾读取同一个文件。例如,如果文件是 200 字节:

Thread A  0-> 200 bytes
Thread B  0-> 200 bytes
Thread C  0-> 200 bytes

等等

基本上让每个线程读取整个文件。该软件只读取该文件,不写入。

所以我打开文件:

fd = open(filename, O_RDWR|O_SYNC, 0);

然后在每个线程中简单地循环文件。因为我只创建一个文件描述符,所以也在每个线程中使用 dup 创建一个文件描述符的克隆

这是一个线程函数的最小示例:

void ThreadFunction(){
 int file_desc= dup(fd);
 uint32_t nReadBuffer[1000];
 int numBytes = -1;
 while (numBytes != 0) {
  numBytes = read(file_desc, &nReadBuffer, sizeof(nReadBuffer));
  //processing on the bytes goes here
 }
}

但是,我不确定这是否正确循环整个文件,并且每个线程都以某种方式以菊花链方式连接文件。

这种方法正确吗?我为我正在处理的项目继承了这个软件,文件描述符在 mmap 调用中使用,所以我不完全确定 O_RDWR 或 O_SYNC 问题

【问题讨论】:

  • 重复的文件描述符共享相同的文件位置。
  • 每个线程需要单独打开文件,不能使用dup()
  • 根据文件的大小和线程数,将文件映射到内存可能是有意义的。
  • 基本上让每个线程读取整个文件。该软件只读取该文件,不写入。 只读取一次文件并将该缓冲区传递给每个线程比拥有每个线程更有效很多将相同的数据读入不同的缓冲区。
  • @AndrewHenle,如果文件很小,则使用普通的read(...) 系统调用将整个文件读入缓冲区很好,但如果文件很大,分配该缓冲区可能会出现问题。这就是内存映射的用武之地。如果你将一个数 GB 的文件映射到进程地址空间,你的堆分配器不需要知道它。

标签: c linux multithreading memory io


【解决方案1】:

正如其他人所提到的,这里不可能使用重复的文件描述符。但是,有一个线程安全的替代方案,即使用preadpread 读取一个偏移量的文件,不会改变文件描述中的隐含偏移量。

这确实意味着您必须手动管理每个线程中的偏移量,但这对您提议的函数来说应该不是太大问题。

【讨论】:

    猜你喜欢
    • 2019-04-13
    • 2023-04-05
    • 1970-01-01
    • 2013-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多