1

I allocated a shared memory segment of the size of an integer.

The expected outcome on stdout should be:

P: 1
C: 2

But instead it is:

C: 1
P: 2

Why is the child process not being blocked until parent is done and has unlocked the shared memory segment?

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <unistd.h>
#include <semaphore.h>

#define SHMSEGSIZE sizeof(int)

int main(void){

   pid_t pid;
   int shmID;
   int *shared_mem;

   /* initializing shared memory */
   shmID  = shmget(IPC_PRIVATE, SHMSEGSIZE, IPC_CREAT | 0644);
   shared_mem  = (int *)shmat(shmID, 0, 0);
   *shared_mem = 0;

   /* initializing semaphore */
   sem_t sem;
   int pshared = 1; // !=0 for processes, =0 for threads
   int value = 1; // number of processes at a time
   sem_init(&sem, pshared, value); // initialize the semaphore

   pid = fork();

   if(pid>(pid_t)0){ // parent
       sem_wait(&sem);
       sleep(6);
       *shared_mem += 1;
       printf("P: %d\n", *shared_mem);
       sem_post(&sem);
       exit(EXIT_SUCCESS);
   } // parent

   if(pid==(pid_t)0){ // child
       sleep(3);
       sem_wait(&sem);
       *shared_mem += 1;
       sem_post(&sem);
       printf("C: %d\n", *shared_mem);
       exit(EXIT_SUCCESS);
   } // child

   /* fork() failed */
   printf("Failed to fork().");
   exit(EXIT_FAILURE);
}

Compiled with:

gcc -o executable sem.c -pthread
jkbx
  • 414
  • 1
  • 6
  • 21

2 Answers2

2

The sem_t itself must be in shared memory if it is to be "pshared".

struct my_shared_mem {
  sem_t sem;
  int   value;
};

... later ...

 struct my_shared_mem *shared;

 shmID  = shmget(IPC_PRIVATE, sizeof(*shared), ...);
 shared = shmat(shmID, ...);
 shared->value = 0;
 sem_init(&shared->sem, 1, 1);
 ...
pilcrow
  • 56,591
  • 13
  • 94
  • 135
  • Can you please be more specific? How do I get it into shared memory? Mapping it somehow or really saving it in there with *shared_mem=sem ? – jkbx Apr 29 '15 at 17:12
  • @JohannesKlaus The argument to `sem_init` must point to shared memory. I've updated the answer. (Note you couldn't just copy the sem on to shared memory, as operations on a copy are [undefined](http://pubs.opengroup.org/onlinepubs/7908799/xsh/sem_init.html).) – pilcrow Apr 29 '15 at 17:18
  • 1
    Instead of using a stack allocated `sem_t` use a pointer which points somewhere into your shared memory block. – doron Apr 29 '15 at 17:25
  • @doron Does it matter where it points to? Or do I have to make my shared memory segment bigger (it's size of int now) and save one 'slot' for the pointer to point to? – jkbx Apr 29 '15 at 17:44
  • The actual semaphore must reside in shared memory which means you will need some sort of pointer to it, just like memory on the heap. The example above is a perfect what to do what you want. The alternative is to use a names semaphore. – doron Apr 30 '15 at 10:13
1

Whenever you fork, the child process inherits a copy of the parent process's address space. Thus the variable sem will be copied to the child's address space. Any changes made in the parent will not be reflected in the child. (sem_wait basically decrements the value of the semaphore)

One way as mentioned previously is to put the semaphore in the shared memory segment.
The other method is to create a system-wide semaphore using the semget call (refer to man semget). The interface here is a bit more complex than pthread library one. You will have to use semctl to set the value (using union semun) and perform semaphore operations using semop (using struct sembuf). This semaphore is an IPC which has a key (passed in the semget call). You can see the system-wide semaphores using ipcs -s

arch3r
  • 56
  • 9
  • Is the semget attempt a named or an unnamed semaphore? – jkbx Apr 29 '15 at 17:59
  • @JohannesKlaus You don't use a name to identify it, but you use a key. Technically, according to the definition given [here](http://stackoverflow.com/questions/13145885/name-and-unnamed-semaphore/13148258#13148258) it is a named semaphore. Sorry for the edits. I am new to the formatting :/ – arch3r Apr 29 '15 at 18:17