【发布时间】: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 准备帖子。