1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstring>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
static void sig_usr(int);
static volatile sig_atomic_t *sharedArray;
static int segmentId;
int number_of_children = 10;
bool check_children_finished(){
for (int i=1; i<number_of_children; i++)
if (sharedArray[i*2] == -1)
return false;
return true;
}
void sig_usr (int signo)
{
/*
// This is signals handler (when a signal fires this is what runs)
// we expect SIGUSR1 from the child process
if(signo == SIGUSR1)
cout << "(parent: " << (int)getpid() << ") --- caught SIGUSR1" << endl;
if (signo == SIGUSR2){
cout << "(parent: " << (int)getpid() << ") --- caught SIGUSR2" << endl;
}else
perror("unexpected signal fired");
// return;
*/
}
int main()
{
// size of the shared memory array
int arrSize = 100;
const int shareSize = sizeof(sig_atomic_t) * (arrSize);
/* Allocate shared memory segment */
segmentId = shmget(IPC_PRIVATE, shareSize, S_IRUSR | S_IWUSR);
sharedArray = (sig_atomic_t *) shmat(segmentId, NULL, 0);
// feel shared memory with -1
for (int i=0; i<arrSize; i++)
sharedArray[i] = -1;
// binding SIGUSR1 & SIGUSR2 to sig_usr method
// we need to override SIGUSR2 because of group signaling
signal(SIGUSR1, sig_usr);
// signal(SIGUSR2,sig_usr);
fprintf(stderr, "\n (parnet) myPid=%d ; segId=%d\n",(int)getpid(), segmentId);
sharedArray[0] = 123;
int kids = 0; // this is the number of child processes
// we send to the child (as shell parameters) the parent pid, shared segment address , and index to the shared memory(this is where he will write his pid and in index+1 the heuristic value)
char* kidsParams[5];
// takes care of param[0]=command to run
string exec_line = "./child";
kidsParams[0] = new char[exec_line.size()+1];
memcpy(kidsParams[0], exec_line.c_str(), exec_line.size());
// takes care of param[1]=parent pid
kidsParams[1] = new char[100]; // = malloc(100*sizeof(char));
sprintf( kidsParams[1],"%d",(int)getpid());
// takes care of param[2]=shared mem segment address
kidsParams[2] = new char[100];
sprintf( kidsParams[2],"%d",segmentId);
// takes care of param[3]=the child private index in shared mem
kidsParams[3] = new char[100];
kidsParams[4] = NULL; // needed as end of array
int index = 0;
for(; kids<number_of_children; kids++) {
sprintf( kidsParams[3],"%d",index);
index+=2;
pid_t childpid = fork();
if(childpid==0){
execv(kidsParams[0],kidsParams);
}
}
cout << "(parent) --- just finished creating " << number_of_children << " kids" << endl;
cout << "(parent) entering to while {...} pause" << endl;
for (int i=0; i<number_of_children; i++)
cout << "[" << i << "] = " << sharedArray[i];
cout << endl;
// going to sleep --- here I want while loop with conditioning that all children finished
while ( ! check_children_finished() ) {
cout << "(parent) now will signal the group" << endl;
// killpg sends signal to the group (all the children). note that the group has the same pid as the father
killpg(getpid(),SIGUSR2);
cout << "(parent) just finished signaling the group" << endl;
pause();
for (int i=0; i<number_of_children; i++)
cout << "[" << i << "] = " << sharedArray[i];
cout << endl;
}
cout << "(parent) exited the while{...} paused" << endl;
// removes shared memory
// shmdt (sharedArray);
// shmctl (segmentId, IPC_RMID, NULL);
// note that all children must also shmctl (...IPC_RMID...);
}
|