Home > Blockchain >  shm_open shared memory across programs
shm_open shared memory across programs

Time:09-27

I am building 3 multithreaded programs with pthread that need access to the same shared memory.

I have one program called parent that will create the shared memory and the other two, the children. I have been able to get the parent working with two threads, one that has a cond_wait and the other broadcasts. Then I went on to try and get it working with one of the children. I copied the code for the cond_wait thread to the child and tried to run it, but have had no luck.

This is because the child is not able to use the shared memory, I'm pretty certain it is because of how I create the shared object in the parent in the child but I have been stuck for a couple of hours and am not sure what to try now.

The parent uses this code to make the shared memory

bool create_shared_object( shared_memory_t* shm) {
    const char* share_name = shared_memory_name;
    shm_unlink(share_name);
    shm->name = share_name;

    shm->fd = shm_open(shm->name, O_CREAT | O_EXCL  | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);    

    if(shm->fd == -1){
        fprintf(stderr, "shm_open(%s): %s (%d)\n", shm->name, strerror(errno), errno);

        return false;
    }

    if (ftruncate(shm->fd , MEMORY_SIZE)){
        fprintf(stderr, "ftruncate(%s): %s (%d)\n", shm->name, strerror(errno), errno);

        return false;
    }

    shm = mmap(NULL, MEMORY_SIZE,
        PROT_WRITE | PROT_READ, MAP_SHARED, shm->fd, 0);
    if (shm == MAP_FAILED){
        fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, (size_t)MEMORY_SIZE, strerror(errno), errno);

        return false;     
    }   
    return true;
}

And this is what the child is using to open the object

bool create_shared_object( shared_memory_t* shm) {
    const char* share_name = shared_memory_name;

    shm->name = share_name;

    shm->fd = shm_open(shm->name, O_RDWR, 0);
    if(shm->fd == -1){
        fprintf(stderr, "shm_open(%s): %s (%d)\n", shm->name, strerror(errno), errno);

        return false;
    }
    

    shm = mmap(NULL, MEMORY_SIZE,
        PROT_WRITE | PROT_READ, MAP_SHARED, shm->fd, 0);
    if (shm == MAP_FAILED){
        fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, (size_t)MEMORY_SIZE, strerror(errno), errno);

        return false;
    }

    return true;
}

For reference I define shm like this in each file shared_memory_t shm; And this is the structure of shared_memory_t

typedef struct shm{
    const char* name;

    int fd;

    shared_parking_t data;
}shared_memory_t;

The result of ls -l /dev/shm shows the corresponding memory file:

 -rwxr-xr-x 1 cab403 cab403 584 Sep 26 23:27 PARKING

If anyone can lend a hand I would be quite grateful

edit* I am not sure if this is important but I am using Linux

edit 2 I am checking if the child can use the shared memory by printing in a loop the value in the memory the parent changes. In this test the child only has open_shared_object and the printing for loop

edit 3 I have updated my code based on input from answers

CodePudding user response:

You should add some debug prints in the error branches to know which system call fails. For example:

#include <errno.h>

shm->fd = shm_open(shm->name, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
if(shm->fd == -1){
    fprintf(stderr, "shm_open(%s): %s (%d)\n", shm->name, strerror(errno), errno);
    return false;
}

if (ftruncate(shm->fd , MEMORY_SIZE)){
    fprintf(stderr, "ftruncate(%s): %s (%d)\n", shm->name, strerror(errno), errno);
    return false;
}

shm = mmap(NULL, MEMORY_SIZE,
    PROT_WRITE | PROT_READ, MAP_SHARED, shm->fd, 0);
if (shm == MAP_FAILED) {
    fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, (size_t)MEMORY_SIZE, strerror(errno), errno);
    return false;
}

return true;
}

Do the same in the child...

Moreover, the code is incoherent as you pass shm of type shared_memory_t and you overwrite it with the mapped region?!? It should be:

[...]
shm->data = mmap(NULL, MEMORY_SIZE,
        PROT_WRITE | PROT_READ, MAP_SHARED, shm->fd, 0);
if (shm->data == MAP_FAILED){
        fprintf(stderr, "mmap(%s, %zu): %s (%d)\n", shm->name, (size_t)MEMORY_SIZE, strerror(errno), errno);

        return false;
    }
[...]

CodePudding user response:

First, why do you use O_CREAT flag on child? It should open an existing area, not create a new one.

Secondly, have you made sure that your shared regions have same name and the name starts with / and there is no name collisions?

Third, I don't think child should feed in the mode parameter as they are not creating the area.

Also, you could have O_EXCL flag in the parent just to make sure that you have created a new area and not just opened an old one.

  • Related