У меня есть один процесс, который создает 10 подпроцессов, и все они разделяют сегмент памяти.10 подпроцессов могут выполняться одновременно, но я хочу, чтобы отец спал в это время.Когда дети заканчивают, они идут спать.Когда все дети сделаны, отец делает некоторые вычисления и разбудит детей для следующего раунда (и он снова ложится спать, пока все дети не закончат свои вычисления).Я думал, что я могу сделать pause () внутри цикла while, что обусловлено check_children_finished ().Дети знают, что нужно подать сигнал родителю с помощью kill (), и у них есть свой pid (отправленный им в качестве аргумента), а на самом деле у отца также есть pid детей (сохраненный в общей памяти). Вот некоторый код -
Родительский код:
#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...);
}
Вот дочерний код:
(same includes...)
using namespace std;
// declare the function proptotype (needed in signal function)
static void sig_usr(int);
// handles the signal (what happens when the signal fires) --- here I want to solve the search problem
void sig_usr (int signo)
{
/*
if(signo == SIGUSR1){
cout << "(child: " << (int)getpid() << ") --- caught SIGUSR1" << endl;
}else if(signo == SIGUSR2){
cout << "(child: " << (int)getpid() << ") --- caught SIGUSR2" << endl;
}else
perror("eerrrr");
// return;
*/
}
int main(int argc, char** argv){
// binding the signal to the handler
signal(SIGUSR2,sig_usr);
int segmentId;
volatile sig_atomic_t *sharedArray ;
int myIndex;
int myData = 5;
int parentPid;
// read parameters
parentPid = atoi(argv[1]);
segmentId = atoi(argv[2]);
myIndex = atoi(argv[3]);
// declare a pointer to the shared memory
sharedArray = (sig_atomic_t *) shmat(segmentId, NULL, 0);
sharedArray[myIndex] =(int)getpid();
sharedArray[myIndex+1] = myData;
// fprintf(stderr, "My Group Pid(child): %d\n",(int)getpgrp());
cout << "(child: " << (int)getpid() << ") --- going to sleep" << endl;
pause();
cout << "(child: " << (int)getpid() << ") --- I woke up" << endl;
//calc data
//fprintf(stderr, "My Pid(child): %d\n",(int)getpid());
//fprintf(stderr, "I got %d (child)\n",sharedArray[0] );
// this signals the father
kill(parentPid,SIGUSR1);
cout << "fired SIGUSR1"<< endl;
}
Вот типичныйвывод:
(parnet) myPid=3104 ; segId=22872080
(parent) --- just finished creating 10 kids
(parent) entering to while {...} pause
[0] = 123[1] = -1[2] = -1[3] = -1[4] = -1[5] = -1[6] = -1[7] = -1[8] = -1[9] = -1
(parent) now will signal the group
User defined signal 2
Иногда я получаю что-то вроде:
(parnet) myPid=3126 ; segId=22937618
(child: 3129) --- going to sleep
(child: 3127) --- going to sleep
(parent) --- just finished creating 10 kids
(parent) entering to while {...} pause
[0] = 3127[1] = 5[2] = 3128[3] = 5[4] = 3129[5] = 5[6] = -1[7] = -1[8] = -1[9] = -1
(parent) now will signal the group
User defined signal 2
(child: 3127) --- I woke up
fired SIGUSR1
(child: 3128) --- going to sleep
(child: 3132) --- going to sleep
(child: 3129) --- I woke up
fired SIGUSR1
Может кто-нибудь предложить решение?Спасибо!- Лирон