How do I share a semaphore through shared memory between child processes?

376 views Asked by At

I'm trying to reproduce MapReduce with processes. I use shmget() to allocate shared memory in the parent process so each child should have access to it. The piece of memory is suppose to store a flag and a semaphore. The first child to finish sets waits on the semaphore (whose initial value is 1), sets the flag, and then runs the reduce method. Thus when the other child processes discover that the flag is set, they should each exit. I'm not getting the expected behavior and I'd appreciate it if someone could enlighten me on what is happening in my code provided below, and how it differs from what I'm trying to accomplish.

Checking errno after sem_init provides me with ENOSYS which according to the documentations is correct since I'm setting pshared to 1.

int map_reduce(int num_proc){
    int i, pid, id, sem_ret, sem_count;
    size_t index, size = 1 + sizeof(sem_t);
    key_t key = IPC_PRIVATE;
    id = shmget(key, size, IPC_CREAT | SHM_W | SHM_R);
    void *addr = shmat(id, NULL, 0);

    *((char *)addr) = 0;
    sem_t *sem = (sem_t *)((char *)addr + 1);
    sem_count = 1;
    sem_ret = sem_init(sem, 1, sem_count);
    printf("%d \n", errno == ENOSYS); // this is true

    for(i = 0; i < num_proc; i++){
        pid = fork();
        if(pid == 0){
            map();
            sem_ret = sem_wait(sem);
            if(*((char *)addr) == 0){
                *((char *)addr) = 1;
                reduce();
            }
            sem_ret = sem_post(sem);
            exit(0);
        }
    }

    while(wait(NULL) > 0);
    struct shmid_ds buf;
    key = shmctl(id, IPC_RMID, &buf);
    return 0;
}

This is the result i get from running an instance that just calls map_reduce(5). Also map and reduce simply prints out the pids.

pid: 19813 mapping
pid: 19814 mapping
pid: 19815 mapping
pid: 19816 mapping
pid: 19814 reducing
pid: 19812 reducing
pid: 19815 reducing
1

There are 1 answers

0
Remy Lebeau On

ENOSYS means

The function sem_init() is not supported by this implementation.

and

pshared is nonzero, but the system does not support process-shared semaphores.

In other words, your system does not support shared semaphores, so you cannot use a semaphore to accomplish what you are attempting across process boundaries.