Lexx
Lexx

Reputation: 725

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 error\n");
    }
    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("%d\n", *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;
}

Upvotes: 0

Views: 3864

Answers (1)

Brian Malehorn
Brian Malehorn

Reputation: 2685

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 error\n");
    }
    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("%d\n", *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.

Upvotes: 2

Related Questions