barfatchen
barfatchen

Reputation: 1698

shared memory contain pointer

http://man7.org/training/download/posix_shm_slides.pdf page 22-30 describe :

Suppose we have situation at right baseaddr is return value from mmap() Want to store pointer to target in *p

Wrong way *p = target

Correct method (relative offset) : *p = target - baseaddr ;

To dereference pointer : target = baseaddr + *p ;

According to this , I have the following source implement :

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)  ;
}

and 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) ;
}

compiled on g++ 4.8.2 :

g++ --std=c++11 shmem1.cpp -lrt -o shmem1.exe
g++ --std=c++11 shmem2.cpp -lrt -o shmem2.exe

run shmem1.exe 2 times look fine to me , then shmem2.exe segment fault :

(2)(2)(4)
Segmentation fault

I really don't get offset meaning in this description , What should I modify the source to get the correct "hello world" ?!

Edit :

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

excellent webpage to refer to .

Upvotes: 1

Views: 298

Answers (1)

Rohan
Rohan

Reputation: 53316

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

With this you are creating pointer p and storing its value (relative or absolute, does not matter) in shared memory.

But when you read it from another process, the address of p may not be valid in that process, as its from another process. So its like accessing unallocated memory address. And this would cause segfault.

One thing that is not clear in the document you referred is that, the address that you want to store in shared memory should also reside in same shared memory. You cannot store address (again absolute or relative) in shared memory and access it from another process safely.

So you need to extend the shared memory you created to store p containing string "hello world". In another word, instead new() or malloc() you should get appropriate free address from shared memory for p.

Upvotes: 4

Related Questions