【问题标题】:Bus error attempting to access memory mapped circle buffer试图访问内存映射圆缓冲区的总线错误
【发布时间】:2020-07-09 23:51:25
【问题描述】:

我正在使用 C 中的圆形缓冲区创建的队列,方法是将文件一个接一个地映射到同一底层缓冲区的两半。如果我尝试在创建缓冲区后立即访问它(在将文件映射到顶部之前和之后),则会引发总线错误。

我在 x86 机器上编程,所以(如果我理解正确的话),发生这种情况的唯一原因是内存位置在物理上不可访问。如果是这种情况,为什么mmap 会返回物理上不可用的地址?

我创建新代码的代码如下所示。

struct queue create_queue() {
    size_t pagesize = getpagesize();
    size_t sz = ((BUFFSIZE*sizeof(char *))/pagesize)*(pagesize+1); //align to page
    int fd = fileno(tmpfile());
    
    void *buffer = mmap(NULL, 2*sz, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 
    mmap(buffer, sz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED, fd, 0); 
    mmap(buffer+sz, sz, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED, fd, 0); 
        
    struct queue new_queue;
    
    new_queue.buffer = (char **)buffer;
    new_queue.front = 0;
    new_queue.back = 0;
    sem_init(&(new_queue.sem), 0, 0); 
    
    return new_queue;
}

【问题讨论】:

  • sizeof(char *)你确定吗?
  • 需要查看mmap的返回值。你不能只是假设调用成功。如果其中任何一个失败,请致电 perror 以获取更详细的错误描述,然后从那里开始。
  • 您的代码中没有任何内容可以实际访问buffer。那么总线错误到底发生在哪里呢?是不是这里没有显示的代码?你有回溯吗?你能告诉我minimal verifiable example吗?对于 MVE,如果您说不需要它们来重现问题,请删除另外两个 mmap 调用。
  • 我觉得你需要发一个minimal reproducible example
  • 如果您从一开始就提供一个最小的可验证示例,这将节省大量时间。它甚至可以帮助您在构建该示例的过程中自己发现问题。删除所有代码,只有一个main 以固定大小调用mmap,然后访问它。所以本质上是两行代码。看看这是否会重现问题。标准调试步骤,即使没有为 SO 准备帖子。

标签: c queue mmap fault


【解决方案1】:

问题是:

size_t sz = ((BUFFSIZE*sizeof(char *))/pagesize)*(pagesize+1); //align to page

确实将sz 设置为页面大小的倍数,但设置为页面大小加一的倍数。另一种方法是:

size_t sz = ((BUFFSIZE*sizeof(char *)+pagesize-1)/pagesize)*pagesize; //align to page

【讨论】:

    猜你喜欢
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    • 1970-01-01
    • 2022-07-15
    • 1970-01-01
    • 2014-12-28
    相关资源
    最近更新 更多