k3b4b
k3b4b

Reputation: 31

Sharing memory between three processes with semaphores

Process 1 forks processes 2 and 3, each process writes a character equal to their number to the shared memory. The last process should read the memory

Output should looks like "read: 123", but i get "read: 1"(only the last process number)

I have no idea how to use shared memory with multiple process, any help?

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <zconf.h>
#include <sys/sem.h>
#include <wait.h>

int main(){
    int pid1, pid2, pid3, semid, shmid, n=3;
    semid = semget(1, 1, 0);
    shmid = shmget(2,1024,0666|IPC_CREAT);
    char *number = (char *) shmat(shmid, (void *) 0, 0);
    pid1=getpid();
    pid2=fork();
    pid3=fork();

    if(pid3==0) {
        printf("Process 3 is writing...\n");
        gets(number);
    }
    else if(pid2==0){
        wait(NULL);
        printf("Process 2 is writing...\n");
        gets(number);
    }
    else{
        wait(NULL);
        printf("Process 1 is writing...\n");
        gets(number);
        printf("read: %s\n", number);
    }

}

I just want to get some advice about multiple process memory writing.

Upvotes: 0

Views: 1230

Answers (1)

pifor
pifor

Reputation: 7892

Here is a fixed answer with a modified and simplified program and explanations.

When creating a child process most of the environment used by the parent process is inherited: shared memory segments are automatically inherited - you don't need to run any shmat, shmget or shmctl routines.

To read and write into a shared memory segment, the child process needs the know the corresponing address: it already has it because in your code it's the number variable.

I have simplified your example in my code:

  • only 2 processes: parent and child
  • no usage of gets in the processes: process just write a letter in shared memory: parent writes 'P' and child writes 'C'; after child exit, parent reads again shared memory to check that the value is what child has written
  • I have added a lot of printf to display who is the current process (parent or child) and what is the process doing
  • like in your code there is no synchronization between parent and child to read and write shared memory: this is just a simplified example (but in a real program there should be some synchronization with semaphores or mutexes).

Code:

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

int main(){
    pid_t pid;
    int shmid;
    char *addr;

    shmid = shmget(2,1024,0666|IPC_CREAT);
    addr = (char *) shmat(shmid, (void *) 0, 0);
    printf("In parent => addr: %p \n", (void *)addr);
    printf("In parent  =>  writing *addr ... \n");
    *addr = 'P';
    printf("In parent  =>  ... writing *addr: done \n");
    printf("In parent  => reading *addr = %c \n", *addr);

    pid = fork();
    if(pid == 0) 
    {
        printf("In child  => PID: %d PPID: %d\n", getpid(), getppid());
        printf("In child  => addr: %p \n", (void *)addr);
        printf("In child  => reading *addr = %c \n", *addr);
        printf("In child  => writing *addr ... \n");
        *addr = 'C';
        printf("In child  => ... writing *addr: done \n");
        printf("In child  => reading *addr = %c \n", *addr);
        printf("In child  => exiting \n");
        exit(EXIT_SUCCESS);
    }
    else if(pid > 0) 
    {
        printf("In parent => PID: %d\n", getpid());
        printf("In parent => waiting for child process to finish ...\n");
        wait(NULL);
        printf("In parent => child process finished.\n");
        printf("In parent  => reading *addr = %c \n", *addr);
    }
    else {
        printf("In parent => unable to create child process.\n");
    }

   printf("In parent => exiting.\n"); 
  return EXIT_SUCCESS;
}

Example of output:

In parent => addr: 0x7fcef5100000 
In parent  =>  writing *addr ... 
In parent  =>  ... writing *addr: done 
In parent  => reading *addr = P 
In parent => PID: 22027
In parent => waiting for child process to finish ...
In child  => PID: 22028 PPID: 22027
In child  => addr: 0x7fcef5100000 
In child  => reading *addr = P 
In child  => writing *addr ... 
In child  => ... writing *addr: done 
In child  => reading *addr = C 
In child  => exiting 
In parent => child process finished.
In parent  => reading *addr = C 
In parent => exiting.

Upvotes: 2

Related Questions