problem: implement IPC between 3 processes in a way that the first process create the shared memory and then sends a signal to the second and third processes so they can get attached to that shared memory, now make the second process write something to the shared memory and then make it send a signal to the third process so that the third process reads what the second process had written.
my code:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
static int pid0, pid1, pid2, shmid, status;
struct memory {
char msg[100];
};
struct memory* shmptr;
struct sigaction act0, act1, act2;
// Handler For P0
void handler0(int signum)
{
if (signum == SIGUSR1) {
printf("Allowing P1 And P2 To Get Attached\n\n");
kill(pid1, SIGUSR1); // Allow P1 To Get Attached
kill(pid2, SIGUSR1); // Allow P2 To Get Attached
}
if (signum == SIGUSR2) {
kill(pid1, SIGINT); // Kill P1
kill(pid2, SIGINT); // Kill P2
}
}
// Handler For P1
void handler1(int signum)
{
if (signum == SIGUSR1) {
// Attaching To The Shared Memory
shmptr = (struct memory*) shmat(shmid, 0, 0);
printf("P1 - Attached to: %d\n\n", shmid);
}
}
// Handler For P2
void handler2(int signum)
{
if (signum == SIGUSR1) {
// Attaching To The Shared Memory
shmptr = (struct memory*) shmat(shmid, 0, 0);
printf("P2 - Attached to: %d\n\n", shmid);
}
if (signum == SIGUSR2) {
printf("Message Read From Shared Memory Is: ");
puts(shmptr->msg);
status = 1;
// Detaching P2 From The Shared Memory
shmdt((void*)shmptr);
kill(pid0, SIGUSR2);
}
}
int main()
{
status = 0;
printf("P0\n\n");
pid0 = getpid();
// Key Of Shared Memory
key_t key = 123456;
// Shared Memory Creation
printf("Creating Shared Memory\n\n");
shmid = shmget(key, sizeof(struct memory), IPC_CREAT | 0666);
// Attaching P0 To The Shared Memory
shmptr = (struct memory*)shmat(shmid, 0, 0);
printf("P0 - Attached to: %d\n\n", shmid);
// Attaching Handler Function To Signal SIGUSR1 For Process 0
act0.sa_handler = handler0;
sigaction(SIGUSR1, &act0, NULL);
printf("Forking...\n\n");
pid1 = vfork();
if(pid1 == 0){ // Inside P1
printf("P1\n\n");
// Attaching Handler Function To Signal SIGUSR1 For Process 1
act1.sa_handler = handler1;
sigaction(SIGUSR1, &act1, NULL);
pid2 = vfork();
if(pid2 == 0){ // Inside P2
printf("P2\n\n");
// Attaching Handler Functions To Signals SIGUSR1 And SIGUSR2 For Process 2
act2.sa_handler = handler2;
sigaction(SIGUSR1, &act2, NULL);
sigaction(SIGUSR2, &act2, NULL);
kill(pid0, SIGUSR1); // Tell P0 That P1 And P2 Are Ready To Get Attached To The Shared Memory
} else { // Inside P1
printf("P1 Again\n\n");
// Writing A Message To The Shared Memory
printf("Enter A Message: \n");
fgets(shmptr->msg, 100, stdin);
// Sending The Message To Process 2
kill(pid2, SIGUSR2);
printf("Sent Message To P2\n\n"); // this gets printed and then a segmentation fault error occurs
}
} else { // Inside P0
printf("P0 - Waiting..\n\n");
while(1){
if(status == 1)
break;
}
// Detaching P0 From The Shared Memory
shmdt((void*)shmptr);
shmctl(shmid, IPC_RMID, (struct shmid_ds *) NULL);
}
}
after executing the printf("Sent Message To P2\n\n");
i get a segmentation fault error
please tell me why, i couldn't figure it out
thanks
You can't do this with vfork()
.
Read the man page, especially the part near the top where it says
the behavior is undefined if the process created by vfork() either modifies any data other than a variable of type pid_t used to store the return value from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully calling _exit(2) or one of the exec(3) family of functions.