【问题标题】:map shared memory size using mmap more than set size done by ftruncate使用 mmap 映射共享内存大小超过 ftruncate 完成的设置大小
【发布时间】:2019-03-01 09:51:13
【问题描述】:

我有几个问题基于以下来源:

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

int g;
int main(void) {
    int fd = shm_open("/myregion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
    ftruncate(fd, sizeof(int)); // set size by sizeof(int)
    int *p1 = mmap(NULL, 10*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd,0); //now map  10*sizeof(int).
    if (p1== MAP_FAILED) {
        printf("*****************error");
    }
    *p1 = mmap(NULL, 8*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd,0);
    if (p1== MAP_FAILED) {
        printf("*****************error");
    }

    *p1=89;

    return g;
}

问题 1: 为什么我在将 size 设置为 size_of(int) 然后映射 10*size_of(int) 时没有看到任何错误

问题 2: 这里创建了多少个共享内存?我的意思是只有一个共享内存创建或两个,因为我做了两次 mmap?

谢谢

【问题讨论】:

  • 你能确定第一个 mmap 返回一个有效的地址吗?
  • 我认为但可能我错了。
  • mmap 返回(void *)-1 失败。所以你的错误检查不能真正捕捉到失败。我想知道你运行代码时得到了什么。
  • 我已经更新了我的来源。我现在已经检查了两者的错误。
  • 您的第二次错误检查无效。

标签: c ubuntu posix shared-memory


【解决方案1】:

给定代码

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

int g;
int main(void) {
    int fd = shm_open("/myregion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
    ftruncate(fd, sizeof(int)); // set size by sizeof(int)
    int *p1 = mmap(NULL, 10*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd,0); //now map  10*sizeof(int).
    *p1 = mmap(NULL, 8*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd,0);
    if (!p1){
        printf("*****************error");
    }
    *p1 = g;
    *p1=89;

    return g;
}

问题 1:为什么我将 size 设置为 size_of(int) 然后映射 10*size_of(int) 时没有看到任何错误

因为你不检查来自mmap()的返回值,所以你不知道是否发生了错误。通过立即再次调用mmap()

*p1 = mmap(NULL, 8*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd,0);

您掩盖了第一次 mmap() 调用中的任何潜在错误,并且您还泄漏了任何已成功分配的内存。

问题2:这里创建了多少个共享mem实例?我的意思是只有一个共享内存创建或两个,因为我做了两次 mmap?

如果第一次调用成功,则映射了两个内存段。如果失败了,只有在第二个成功时才映射一个。

如果第一次调用成功了,你就泄露了内存。

请注意,如果您尝试在ftruncate() 设置的文件大小末尾之后写入mmap()'d 段,则不会导致文件增长。每the POSIX mmap() documentation:

请注意,超出对象末尾的引用不会扩展对象,因为大多数虚拟内存硬件无法精确确定新的结尾。相反,可以通过 ftruncate() 直接操作大小。

在 Linux 上,尝试访问超出映射文件末尾的 mmap()'d 数据可能会导致您的进程 receiving a SIGBUS signal。

【讨论】:

  • 实际上,如果我使用 if (p1== MAP_FAILED) { printf("*****************error"); } 在第一个 mmap 之后。
  • @EricIpsum 如果您更改代码以检测故障并且检查未检测到故障,则第一个 mmap() 工作。但正如最初发布的那样,您并不知道第一个 mmap() 调用是否有效,尽管很可能确实有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多