Skip to content
Advertisement

Working with semaphores and shared memory under Linux

I need to write a program that is creating a N amount of sub processes and every single one of them adds one to a shared memory variable. My idea is to use semaphores and shared memory, but the processes are not waiting for each other and the shared memory variable is also not working as I want it.

mydefs.h

#ifndef __MYDEFS__H__
#define __MYDEFS__H__
// Includes
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <memory.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/shm.h>
#endif // __MYDEFS__H__

main.c

#include "mydefs.h"
#define PROC_COUNT 3
#define INITAL_MARKER_VALUE 0
#define PID_LEN 32

char mypid[PID_LEN];

int main()
{
    int i, shm_id;
    sem_t mutex;
    if(sem_init(&mutex,1,1) < 0)
    {
        perror("semaphore initilization");
        exit(0);
    }
    shm_id = shmget(IPC_PRIVATE, 4*sizeof(int), IPC_CREAT | 0666);
    if (shm_id < 0) {
         printf("shmget errorn");
    }
    int *shmpointer = shmat(shm_id,0,0);
    memset(mypid, 0, sizeof(mypid));
    sprintf(mypid, "%06d", getpid());

    for(i = 0; i < PROC_COUNT; i++)
    {
        if (fork() == 0)
        {
            while(sem_wait(&mutex)!=0);
            execl("slaveproc", "slaveproc", mypid, (char *)0);
            shmpointer += 1;
            sem_post(&mutex);
            perror("n Can't exec slave program. Cause ");
            exit(1);
        }
    }
    sleep(1);
    printf("%dn", *shmpointer);
    return 0;
}

slaveproc.c

#include "mydefs.h"

int marker; // Marker value

int main(int argc, char *argv[])
{
    master_pid = atoi(argv[1]);
    printf("n --------------------------------------");
    printf("n I'm the slave proc!");
    printf("n My pid: %d", getpid());
    printf("n My master's pid: %d", master_pid);
    printf("n --------------------------------------");
    for(;;) pause();
        return 0;
}

Advertisement

Answer

The problem (or at least “a problem”) is that mutex is not in shared memory: it’s allocated on the stack. When you fork(), the new process will have a completely separate copy from the old process, so calling sem_wait(&mutex) on one process will not affect the other process’s mutex at all.

You should put mutex in the shared memory:

int main()
{
    int i, shm_id;
    shm_id = shmget(IPC_PRIVATE, sizeof(sem_t) + 4*sizeof(int), IPC_CREAT | 0666);
    if (shm_id < 0) {
         printf("shmget errorn");
    }
    int *shmpointer = shmat(shm_id,0,0);
    sem_t *mutex = shmpointer;
    shmpointer = (void*)shmpointer + sizeof(sem_t);
    if(sem_init(mutex,1,1) < 0)
    {
        perror("semaphore initilization");
        exit(0);
    }        
    memset(mypid, 0, sizeof(mypid));
    sprintf(mypid, "%06d", getpid());

    for(i = 0; i < PROC_COUNT; i++)
    {
        if (fork() == 0)
        {
            while(sem_wait(mutex)!=0);
            execl("slaveproc", "slaveproc", mypid, (char *)0);
            shmpointer += 1;
            sem_post(mutex);
            perror("n Can't exec slave program. Cause ");
            exit(1);
        }
    }
    sleep(1);
    printf("%dn", *shmpointer);
    return 0;
}

You’re also never writing to the memory in shmpointer (perhaps you meant (*shmpointer) += 1?), but I’ll let you figure that out on your own.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement