共享内存包含指针

shared memory contain pointer

本文关键字:指针 包含 内存 共享      更新时间:2023-10-16

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

假设我们有正确的情况baseaddr是mmap((的返回值想要在*p 中存储指向目标的指针

走错了路*p=目标

正确的方法(相对偏移(:*p=目标-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. %sn", 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. %sn", 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两次对我来说很好,然后运行shmem2.exe段错误:

(2)(2)(4)
Segmentation fault

我真的不明白这个描述中的偏移含义,我应该修改什么获得正确的"你好世界"的来源?!

编辑:

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

优秀的网页参考。

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

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

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

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

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