共享内存包含指针

时间:2015-09-25 08:16:43

标签: c++ c pointers shared-memory

http://man7.org/training/download/posix_shm_slides.pdf 第22-30页描述:

假设我们有正确的情况 baseaddr是来自mmap()的返回值 想要在* p

中存储指向目标的指针

错误的方式 * p =目标

正确方法(相对偏移): * p = target - baseaddr;

取消引用指针: target = baseaddr + * p;

据此,我有以下源工具:

shmem1.cpp:

struct datafeed
{
    int seqno ;
    int val1 ;
    char *ptr ;
    int val2 ;
} ;

static datafeed  *conf;
#define STATE_FILE "/datafeed.shared"

#define ARRAYSIZE 50

int main(int argc, char* argv[])
{
    int shm_fd;
    if((shm_fd = shm_open(STATE_FILE, (O_CREAT | O_EXCL | O_RDWR),
                       (S_IREAD | S_IWRITE))) > 0 ) {
        ; /* We are the first instance */
    }
    else if((shm_fd = shm_open(STATE_FILE, (O_CREAT | O_RDWR),
                    (S_IREAD | S_IWRITE))) < 0)
    {
        printf("Could not create shm object. %s\n", strerror(errno));
        exit( 0 ) ;
    }
    int iTotalByte = sizeof(datafeed)*ARRAYSIZE ;
    ftruncate(shm_fd, iTotalByte );
    conf =  (datafeed*) mmap(0, iTotalByte ,
            (PROT_READ | PROT_WRITE), MAP_SHARED, shm_fd, 0) ;
    if(conf  == MAP_FAILED)
    {
        printf(" mmap error ....\n")  ;
        exit( 0 ) ;
    }
    (conf+0)->seqno++ ;
    (conf+0)->val1++ ;
    (conf+0)->val2 = (conf+0)->val2 + 2  ;
    char *p = new char(128) ;
    strcpy(p,"hello world") ;
    (conf+0)->ptr = (char *)((char *)p - (char *)conf)  ;
}

和shmem2.cpp

int main(int argc, char* argv[])
{
    int shm_fd;
    if((shm_fd = shm_open(STATE_FILE, (O_RDWR),
                (S_IREAD | S_IWRITE))) < 0) {
        printf("Could not create shm object. %s\n", strerror(errno));
        return errno;
    }
    int iTotalByte = sizeof(datafeed)*ARRAYSIZE ;
    ftruncate(shm_fd, iTotalByte );
    conf =  (datafeed *)mmap(0, iTotalByte , 
            (PROT_READ | PROT_WRITE), MAP_SHARED, shm_fd, 0) ;
    if(conf  == MAP_FAILED)
    {
        printf("error in mmap \n") ;
        exit(0) ;
    }
    int seqno = (conf+0)->seqno ;
    int val1 = (conf+0)->val1 ;
    int val2 = (conf+0)->val2 ;
    printf("(%d)(%d)(%d)\n",seqno,val1,val2) ;
    //char *p = (char *) ( (char *)conf + (conf+0)->ptr ) ;
    char *p = (char *) ( (char *)conf + *((conf+0)->ptr) ) ;
    printf("(%s)\n",p) ;
}

在g ++ 4.8.2上编译:

g++ --std=c++11 shmem1.cpp -lrt -o shmem1.exe
g++ --std=c++11 shmem2.cpp -lrt -o shmem2.exe
运行shmem1.exe 2次看起来很好,然后shmem2.exe段错误:

(2)(2)(4)
Segmentation fault

我真的没有在本说明书中得到偏移,我应该修改什么 获得正确的“你好世界”的来源?!

编辑:

http://accu.org/index.php/journals/376

优秀的网页参考。

1 个答案:

答案 0 :(得分:4)

char *p = new char(128) ;
(conf+0)->ptr = (char *)((char *)p - (char *)conf)  ;

使用此方法,您将创建指针p并将其值(相对或绝对,无关紧要)存储在共享内存中。

但是当你从另一个进程读取它时,p的地址在该进程中可能无效,因为它来自另一个进程。所以它就像访问未分配的内存地址一样。这会导致段错误。

您提到的文档中不清楚的一点是,您要存储在共享内存中的地址也应该驻留在同一共享内存中。您不能在共享内存中存储地址(同样是绝对的或相对的),并安全地从另一个进程访问它。

因此,您需要扩展您创建的共享内存以存储包含字符串p的{​​{1}}。换句话说,而不是"hello world"new(),您应该从malloc()的共享内存中获取适当的免费地址。