gpt4 book ai didi

c - mmap 总线错误写入超过 2Gb 的 MAP_SHARED 文件

转载 作者:太空狗 更新时间:2023-10-29 12:16:33 26 4
gpt4 key购买 nike

我正在尝试使用 MAP_SHARED 创建一个内存映射文件。当文件大小达到 2gb 时,我遇到了问题。下面粘贴的代码是我正在使用的(作为测试)。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>

#define MY_FILE "/dev/shm/mmap_test"
#define BLOCK_SIZE (1024*1024)
#define NUM_FILES 1

void mk_file(int f_num)
{
uint64_t len = 0;
int fd, j, k;
char tmp_file[1024], *x, *rr_addr;

// Open file in /dev/shm
sprintf(tmp_file, "%s%d", MY_FILE, f_num);
fd = open(tmp_file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);

if (fd == -1)
{
perror("file open");
exit(-1);
}

// 16Gb file
len = 16UL * 1024 * 1024 * 1024;
printf("len: %ld Gb\n", len/(1024*1024*1024));

printf("Mapping %ld blocks\n", len/BLOCK_SIZE);

for (j = 0; j < len/BLOCK_SIZE; j++) {
// Increase the file size
ftruncate(fd, ((j + 1) * BLOCK_SIZE));

// Just mmap memory... don't have file backing
//rr_addr = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_NORESERVE, -1, 0);

// MMAP a region to the file at a given offset
rr_addr = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_NORESERVE, fd, (j * BLOCK_SIZE));

if (rr_addr == MAP_FAILED) {
perror("mmap error");
printf("INDEX: %d\n", j);
exit(-1);
}

// Write to every byte of allocated memory
x = (char *) rr_addr;

for (k = 0; k < BLOCK_SIZE; k++)
{
*x = '1';
x++;
}
}

return;
}

int main(int argc, char **argv)
{
uint64_t i;

for (i = 0; i < NUM_FILES; i++)
mk_file(i);

return 0;
}

在上面的代码中,当文件中的偏移量达到 2gb 时出现总线错误。这些是我尝试过的事情:

  1. 如果我将 NUM_FILES 更改为 16 并将 len 更改为 1GB,我没有任何问题。
  2. 如果我删除写入内存的 for 循环(仅 mmap),程序不会崩溃(即使 len 远大于 2gb)b/c linux 内核实际上不会将页面映射到文件,直到您读取/写入 mmap 区域。
  3. 如果我将 mmap 调用从 MAP_SHARED 更改为 MAP_ANON(取消第一个 mmap 调用的注释并注释掉第二个)并且没有链接到文件,则没有问题(即使写入成功)。
  4. /dev/shm (30gb) 上有足够的空间,我这里只使用了 16gb。
  5. 我不必写入每个分配的字节。我只需要写入最后一个 mmap 区域(将内部 for 循环移到外面),如果偏移量 + BLOCK_SIZE >= 2gb,那么我会收到总线错误。
  6. 我已经在 Ubuntu 13.10 和 CentOS 6.4 上试过了,两者都有同样的问题。

我想知道这是否是 linux 内核中的问题?有没有人尝试使用大于 2gb 的 MAP_SHARED 映射单个文件并成功使用(读/写)它?

最佳答案

我认为问题在于 j 是一个 int。当 j 达到较大的值时,(j + 1) * BLOCK_SIZE 会溢出并且您的 ftruncate 调用不会执行您想要的操作。检查 ftruncate 的返回值应该可以确认这一点。

mmap man page特别调用 SIGBUS 表示尝试的访问不受文件支持。

关于c - mmap 总线错误写入超过 2Gb 的 MAP_SHARED 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22794432/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com