tags:

views:

124

answers:

2
+2  Q: 

Mmap and structure

I'm working some code including communication between processes, using semaphores. I made structure like this:

typedef struct container {
    sem_t resource, mutex;
    int counter;
} container;

and use in that way (in main app and the same in subordinate processes)

container *memory;

shm_unlink("MYSHM"); //just in case
fd = shm_open("MYSHM", O_RDWR|O_CREAT|O_EXCL, 0);

if(fd == -1) {
    printf("Error");
    exit(EXIT_FAILURE);
}
memory = mmap(NULL, sizeof(container), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
ftruncate(fd, sizeof(container));

Everything is fine when I use one of the sem_ functions, but when I try to do something like

memory->counter = 5;

It doesn't work. Probably I got something wrong with pointers, but I tried almost everything and nothing seems to work. Maybe there's a better way to share variables, structures etc between processes ? Unfortunately I'm not allowed to use boost or something similiar, the code is for educational purposes and I'm intentend to keep as simple as it's possible.

+2  A: 

Because you're using shm_unlink() immediately before shm_open(), your two processes never open the same shared memory object - each one is creating a new, distinct object (even though they have the same name).


It's not clear what you mean by "doesn't work". The following minimal example, based on your code, works fine for me. What does it do for you?

#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>

typedef struct container {
    sem_t resource, mutex;
    int counter;
} container;

int main()
{
    container *memory;
    int fd = shm_open("MYSHM", O_RDWR|O_CREAT|O_EXCL, 0);

    if(fd == -1) {
        perror("shm_open");
        return 1;
    }

    ftruncate(fd, sizeof(container));
    memory = mmap(NULL, sizeof(container), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

    memory->counter = 5;
    printf("%d\n", memory->counter);

    return 0;
}

On reviewing your code, it's failing because you are trying to access the file descriptor in a child process after exec(), and shm_open sets the FD_CLOEXEC flag by default so the file descriptor is no longer open in the child. So you just need to unset that flag in the main process (eg. right after checking for the error after shm_open):

fdflags = fcntl(fd, F_GETFD);
fdflags &= ~FD_CLOEXEC;
fcntl(fd, F_SETFD, fdflags);
caf
that's not it; memory->counter = 5; does not work even if use it only in main app.
@blid..pl: The `ftruncate()` call should also be before the `mmap()` call.
caf
@caf: ftruncate() has apparently nothing to do with my problem.
@bild..pl: You'll need to explain what exactly you mean by "does not work" then. I've updated my answer with a minimal example that works fine here.
caf
It works fine now, but only for main program. It turned out that I've included too many unnecessary libraries which casued seg fault. But my problem still stands, I can't read what's I put into shared memory in main app in other processes. There's too much code to paste it here, so here are the links:Main app (pass fd by argument to the process):http://pastebin.com/DifMKJC7Reader (try to read what's been in main app):http://pastebin.com/vbtkdhM2Writer containts just main().
@blid..pl: Your problem is that `shm_open` sets `FD_CLOEXEC` on the file descriptor that it opens. See my latest update.
caf
Thanks a lot for your time, that finally helped (at least for now).
A: 

Why are you calling shm_open at all? A pretty good way to do this is to just call 'open' on some pathname and use that.

bmargulies