Ad

Using Shared Memory In Posix Semaphore Wait And Signal In C

- 1 answer

Using this code below as an example. The code stops after printing waiting until stop the program manually, but doesn't signal the next function. I checked it multiple times (even removing the mutual exclusion) and discovered that being inside the for or while is what causes the problem.

According to other users, I must use shared memory to get this working, but I don't know how to use it or apply it to this specific code.

I've looked at many websites to better understand this situation such as https://www.geeksforgeeks.org/posix-shared-memory-api/

The most recommended I've seen is shmget() and mmap().

So the question, how can I get sem_wait() to work inside of any type of loop using Shared memory?

#include <stdio.h>
#include <semaphore.h> 
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <fcntl.h> 
#include <sys/shm.h> 
#include <sys/stat.h> 
sem_t *mutex; 
void wait_t(int a)
{
    for (int i = 0; i < 3; i++)
    {
        if (a < 0)
        {
            sem_wait(&mutex);
            printf("waiting\n"); //Stops here due lack of shared memory
        }
        a--;
    }
}

void signal_t(int a)
{
    for (int i = 0; i < 3; i++)
    {
        if (a <= 0)
        {
            printf("signal\n");
            sem_post(&mutex);
        }
        a++;
    }
}

int main()
{ 
    int shared_mem_id = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT);
    mutex = shmat(shared_mem_id, NULL, 0);
    sem_init(&mutex, 1, 1);
    int i = -2;
    if(fork() == 0){ // create 1st child process
        mutex = shmat(shared_mem_id, NULL, 0);
        wait_t(i);
        exit(0);
        shmdt(mutex);
    }

    wait(NULL);
    if(fork() == 0){ // create 2nd child process
        mutex = shmat(shared_mem_id, NULL, 0);
        signal_t(i);
        exit(0);
        shmdt(mutex);
    }

    wait(NULL);
    if(fork() == 0){ // create 3nd child process
        mutex = shmat(shared_mem_id, NULL, 0);
        signal_t(i);
        exit(0);
        shmdt(mutex);
    }
    wait(NULL);
    printf("%d\n", i);
    exit(0); 
}
Ad

Answer

So, the idea is that your parent process would need to create a new shared memory space:

shared_mem_id = shmemget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT);

Then all the processes needing access to the semaphore will need to do:

sem_t *mutex = shmat(shared_mem_id, NULL, 0);

(So you'll need to do this in each child process, after the fork)

And then the functions that use the semaphore will need to have access to the mutex pointer (remember to add a dereference to mutex).

Once they are done, each process using the mutex will need to do:

shmdt(mutex);

Of course, you can feel free to store more complex structures in the shared memory as long as you allocate enough space.

Ad
source: stackoverflow.com
Ad