【问题标题】:Writing data bigger than page size into shared memory将大于页面大小的数据写入共享内存
【发布时间】:2015-04-08 07:39:36
【问题描述】:

我的处理器的页面大小为 4096。我需要将数据写入共享内存,该数据的大小为 7168 (7 KB)。 我使用了 ftruncate 并分配了 8192 (2*page_size) 以便有足够的内存。

shmem_fd = shm_open( TRIAL_SHMEM_FILE, O_RDWR, S_IRUSR | S_IWUSR);
if( shmem_fd == -1 ) 
{
    printf("Create_shmem, open failed:%s",strerror( errno));PASLOG  return false;
}
if( ftruncate( shmem_fd, 8192) == -1 )
{
    printf("Create_shmem, ftruncate failed:%s",strerror( errno));PASLOG return false;
}

我正在编写如下结构。 [767*10]bytes 小于 [2*page_size]。但是下面的代码会导致分段错误。 如果我尝试写 [1-page_size] 内的 [767*5],则不会发生崩溃。我无法知道坠机的真正原因。有其他方法可以继续吗?

// data to be written into shared memory
list_data item[10]; // struct size is 767 bytes
for (uiCounter=DEFAULT_VALUE_ZERO; uiCounter < 10; ++uiCounter)
{
    memset(&item[uiCounter], 0, sizeof(list_data));
}           

list_data* list_shmem;
list_shmem = (list_data *) mmap(NULL, sizeof(list_data) * 10, PROT_READ | PROT_WRITE, MAP_SHARED, shmem_fd, 0 );

if(list_shmem == MAP_FAILED)
{
    printf("mmap failsed: %s", strerror(errno));
    return false;
}

// write to shared mem
for (uiCounter = DEFAULT_VALUE_ZERO; uiCounter < 10; ++uiCounter)
{
    memcpy ( list_shmem, &item[uiCounter], sizeof(person) );
    ++list_shmem;
}

munmap(list_shmem, sizeof(list_data) * 10);

【问题讨论】:

  • 你能一步步调试程序,找到导致段错误的确切行吗?
  • seffault 发生在 memcpy ( list_shmem, &item[uiCounter], sizeof(list_data) );当计数器为 6 时总是行

标签: c++ shared-memory mmap


【解决方案1】:

您的代码有几个问题:

  1. 您将错误的地址传递给munmap in:

    list_data* list_shmem;
    list_shmem = (list_data *) mmap(...);
    
    for (uiCounter = DEFAULT_VALUE_ZERO; uiCounter < 10; ++uiCounter)
    {
        memcpy ( list_shmem, &item[uiCounter], sizeof(person) );
        ++list_shmem; // <---- invalidates list_shmem original value
    }
    
    munmap(list_shmem, sizeof(list_data) * 10);
    
  2. 你在memcpy中指定了错误的尺寸:

    memcpy ( list_shmem, &item[uiCounter], sizeof(person) );
    

    解决方法是:

    memcpy ( list_shmem, &item[uiCounter], sizeof(item[uiCounter]) );
    

解决这两个问题的方法之一是使用标准算法 std::copy 而不是手动编码循环:

    std::copy(item + DEFAULT_VALUE_ZERO, item + 10, list_shmem);

奖励积分:

list_data item[10]; // struct size is 767 bytes
for (uiCounter=DEFAULT_VALUE_ZERO; uiCounter < 10; ++uiCounter)
{
    memset(&item[uiCounter], 0, sizeof(list_data));
}  

等同于:

list_data item[10] = {}; 

【讨论】:

  • @BЈовић 因为你更改了list_shmem,然后将其传递给munmap
  • 我明白你对 memcpy 的看法,这个错误是由于我放在这里的示例代码造成的。但是 munmap 有什么问题
  • @BlueBottle 注意++list_shmem; // &lt;---- invalidates list_shmem original value 行。但是你从来没有注意到它,因为你没有检查munmap的返回值。
  • 谢谢,我会检查的。我现在需要知道为什么我不能一次写入超过 4096 个字节。
  • 我现在需要知道为什么我不能一次写入超过 4096 个字节 - 你应该可以。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 2013-03-04
  • 1970-01-01
  • 2014-01-19
  • 2022-12-05
相关资源
最近更新 更多