共享内存包含指针

shared memory contain pointer

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

假设我们有右边的情况 baseaddr 是来自 mmap() 的 return 值 想要在 *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

这个描述我实在是看不懂offset的意思,我该修改什么 获得正确 "hello world" 的来源 ?!

编辑:

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

优秀的网页可以参考。

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

这样你就可以创建指针 p 并将其值(相对或绝对,无关紧要)存储在共享内存中。

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

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

因此您需要扩展您创建的共享内存以存储包含字符串 "hello world"p。换句话说,您应该从 p.

的共享内存中获取适当的空闲地址,而不是 new()malloc()