I have an application which creates many processes via fork(). At some point I want to pause them all and wait until all of them finish earlier tasks. Then start them all at once.
for (int i = 0; i < N; i++)
{
if(fork() == 0)
{
//some operations here
<----- wait here for all N forked processes
//some operations I want all processes start at similiar time
I don't want any of children to quit.
This seems tailor-made for a semaphore. Specifically, this is easy to implement with "System V semaphores". See semget(2) and semop(2).
The idea is that you obtain a semaphore in the parent, initialize its value to N, then have each child as it's "ready" decrement the value by 1. All children wait for the result to become 0. Voila.
Here's a sample program
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define N 5
int main(int ac, char **av)
{
int i, n, sem_id;
sem_id = semget(IPC_PRIVATE, 1, 0777);
struct sembuf buf;
buf.sem_num = 0;
buf.sem_flg = 0;
// Initialize semaphore value to N
buf.sem_op = N;
n = semop(sem_id, &buf, 1);
// All children will do the same thing:
// decrement semaphore value by 1
// wait for semaphore value == 0
for (i = 0; i < N; ++i) {
if (fork() == 0) {
printf("Child %d (%d) started\n", i, getpid());
sleep(i + 1); // Sleep awhile.
buf.sem_op = -1;
n = semop(sem_id, &buf, 1);
buf.sem_op = 0;
n = semop(sem_id, &buf, 1);
printf("Child %d (%d) done\n", i, getpid());
return 0;
}
}
return 0;
}
There are many ways to communicate with processes, it is called IPC (Inter Process Communication). It depends on what kind of information you need to send, how large etc. Process signals is also a way to control processes.
Here are a few resources to get you started:
Personally I like Beej Guides, which are awsome, clear, concise and FREE!
http://beej.us/guide/bgipc/
There is also Advanced Linux Programming by CodeSourcery LLC.
http://www.advancedlinuxprogramming.com/
And of course, once you have some notions of the basics, you can look up more specifically http://stackoverflow.com, i.e. right here :-)
What you can use is a synchronization construct like semaphore.
At the point of code where you want to stop all childrens make them wait in queue (call wait on a semaphore with 0 as initial value )of semaphore and thus they all will block.
In parent then you can signal semaphore and thus start them all.
I would highly recommend Message Passing Interface (MPI) for this, since it has MPI_Barrier that you can used to achieve exactly what you want with almost no logic you have to code yourself. There are alternatives such as OpenMP as well.
I've managed to resolve this via group signals:
for (int i = 0; i < N; i++)
{
if(fork() == 0)
{
/* save first process pid in shared memory */
if(localID == 0)
*sh_temp = getpid();
/* wait in all processes for shared memory with group id to be set */
while(*sh_temp == 0)
usleep(10000);
/* set group id to first process PID */
setpgid(getpid(), *sh_temp);
//some operations here
fprintf(stderr, "Process %d paused... W8ing for signal to resume\n", getpid());
raise(SIGSTOP);
//some operations I want all processes start at similiar time
}
}
if(parentPID == getpid())
{
fprintf(stderr, "Wake-up signal sent to group %ld.\n", *sh_temp);
killpg(*sh_temp, SIGCONT);
}
But - if anyone has better solution please post it.
Related
I have a multiprocess and I want to block other processes with Semaphores to stop the acces for the function in the middle of the pseudo code.
while(true){
fork()
reset buf
getting input
while(getting input){
if(true) {give only acces to this process for the next function}
function()
if(true){stop acces to only that one process for the function}
reset buf
getting input
}
}
So I want to activate and close the Semaphores with the statements, to give the acces only to that one process which activate the statement, other processes has to wait.
How to implement this in C?
I hope my probleme is clear enough to understand
EDIT 1:
right now I try to use sysV
unsigned short marker2[2];
struct sembuf sem_down;
sem_down.sem_num = 0;
sem_down.sem_op = -1;
sem_down.sem_flg = 0;
struct sembuf sem_up;
sem_up.sem_num = 0;
sem_up.sem_op = +1;
sem_up.sem_flg = 0;
sem_id = semget (IPC_PRIVATE, 1, IPC_CREAT | IPC_EXCL | 0600);
marker2[0] = 1;
semctl(sem_id, 1, SETALL, marker2);
while(true) {
fork();
while(input){
if (strncmp("BEG", inputBuffer[0], 3) == 0) {
semop (sem_id, &sem_down, 1);
printf("blocked from %d\n", getpid());
}
conditions(inputBuffer[0],
inputBuffer[1],
inputBuffer[2],
cfd, semID1, shmID);
if (strncmp("END", inputBuffer[0], 3) == 0) {
semop (sem_id, &sem_up, 1);
printf("open by %d\n", getpid());
}
}
}
right now, other processes doesn't get blocked
Edit 2:
sem_t semvar;
sem_init(&semvar, 0,1);
while(true) {
fork();
while(input){
if (strncmp("BEG", inputBuffer[0], 3) == 0) {
sem_wait(&semvar);
printf("blocked from %d\n", getpid());
}
conditions(inputBuffer[0],
inputBuffer[1],
inputBuffer[2],
cfd, semID1, shmID);
if (strncmp("END", inputBuffer[0], 3) == 0) {
sem_post(&semvar);
printf("open by %d\n", getpid());
}
}
still doesn't work
The basic operations on a semaphore are "acquire" -- waiting until the value is non-zero and atomically decrement it, and "release" -- increment the value (thus allowing someone waiting for am "acrquire" to proceed.)
So to allow only one process to access a critical section like you describe with a semaphore, you would initialize the semaphore value to 1, acquire the semaphore before the critical section, and release it afterwards. So your first "if(true)" should be "acquire" and the second should be "release"
So how do you actually do this in C? Well, C does not have any native semaphore types or operations. There are a number of different libraries that provide them -- the SysV semctl/semop calls, POSIX sem_open, WIN32 semaphores, and probably others. C11 does have native mutex types, but they are only process local (so can only be used for multithreading in a single process)
While I was playing with C, and trying to learn more about processes, forks and wait, I've reached a problem where I'm not able to wait for a sibling process to finish until I can continue.
So, here's the problem:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
int processoDisplayLyric;
int processoDisplayGraph;
int processoTimer;
int main(){
int numeroMusicaAtual = 0;
int continueWorking = 0;
int fathersPID = getpid();
while(continueWorking == 0) {
//Create graph process
processoDisplayGraph = fork();
if(processoDisplayGraph == 0){
int work = 0;
while(work == 0){
pause();
}
}
if(processoDisplayGraph != 0){
//Create lyric process.
processoDisplayLyric = fork();
if(processoDisplayLyric == 0){
int work = 0;
while(work == 0){
pause();
}
}
}
if(processoDisplayLyric != 0 && processoDisplayGraph != 0){
//Create timer process.
processoTimer = fork();
if(processoTimer == 0){
printf("I was created and i just want to wait for my brothers.\n");
}
}
if(getpid() != fathersPID){
wait(processoDisplayLyric);
wait(processoDisplayGraph);
}else{
//It's the father.
int child_status;
for (int i = 0; i < 2; i++) {
pid_t wpid = waitpid(processoDisplayLyric, &child_status, 0);
if (WIFEXITED(child_status))
printf("Saw %d done with %d\n", wpid, WEXITSTATUS(child_status));
else
printf("Child %d terminated abnormally\n", wpid);
}
}
numeroMusicaAtual++;
}
}
The thing is: processDisplayLyric, processDisplayGraph and processTimer are created, BUT, the Timer DOESN'T wait for the other two to finish (something that should never happen!!!).
Under standard POSIX, only a parent process can wait for its (immediate) children to die.
Sibling processes cannot wait for other sibling processes to die.
Child processes cannot wait for parent processes to die.
A grandparent process cannot wait for grandchildren to die.
There are ways to detect whether a parent process is dead (the result of getppid() is 1, or if you recorded the original PPID, then signalling it fails). You can find out if you could signal a known PID — and if it doesn't exist, you can't. There may be some alternatives on some platforms using other APIs. But there's no general analogy to wait() for siblings or parents (or any other related process) — only children can be waited for.
Note that recent versions of Linux (since kernel 3.4) have the prctl() system call. The PR_SET_CHILD_SUBREAPER option allows a process other than the system process (PID 1 usually) to collect the status information of dead children in its process hierarchy. That's still not collecting sibling processes; it is only able to collect children, grandchildren, great-grandchildren, and so on.
I am trying to develop a simple railroad simulation following the answer to the question Make children process wait until receiving parent's signal.
My task: I have exactly 5 process representing trains. I need to create these 5 process (T1, T2, T3, T4, and T5) via fork(), and pause each one until all of them are created. After that the parent process will send a signal to the children, and each child will use an execl (i.e. execl(execl_path_name, CHILDETCONE, i, NULL);). After signaling, the parent waits for all the children to complete their tasks.
I quite understand the handler function, but I am not clear on these points:
Do I need to insert my execl inside the handler function?
I don't understand the significance of this last loop from the answer to the previous question:
for (int i = 0; i < NUMBER_TRAINS; i++)
{
wait(NULL);
}
This is my code:
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include "accessory.h"
#define NUMBER_TRACKS 16
#define NUMBER_STATIONS 8
#define NUMBER_TRAINS 5
#define TRACKS_INITIALS "MA"
#define STATION_INITIALS "S"
#define SIZE 256
#define CHILDETCONE "childETCone"
void handler(int sig);
int main(int argc , char *argv[]) {
pid_t pid;
pid_t pid_array[NUMBER_TRAINS];
char track_name[2];
char track_number[2];
int execl_return;
char str[2];
char * execl_path_name;
memset(pid_array, 0, sizeof(pid_array));
/* create the MAx file initialized to zero */
for (int i = 1; i < (NUMBER_TRACKS + 1); i++) {
memset(track_name, '\0', sizeof(track_name));
memset(track_number, '\0', sizeof(track_number));
strcpy(track_name, TRACKS_INITIALS);
sprintf(track_number, "%d", i);
strcat(track_name, track_number);
create_track_file(track_name, "", SIZE);
}
execl_path_name = get_file_name(CHILDETCONE, "", SIZE);
printf("path %p\n", execl_path_name);
for(int i = 0; i < NUMBER_TRAINS; i++) {
pid = fork();
if (pid < 0) {
perror("fork");
exit(1);
}
if (pid == 0) { //child
//sprintf(str, "%d", i+1);
//execl_return = execl(execl_path_name, CHILDETCONE, i, NULL);
signal(SIGUSR1, handler);
pause();
exit(0);
}
//parent
pid_array[i] = pid;
}
for (int j = 0; j < NUMBER_TRAINS; j++) {
kill(pid_array[j], SIGUSR1);
sleep(1);
}
for (int i = 0; i < NUMBER_TRAINS; i++) {
wait(NULL);
}
return 0;
}
void handler(int sig) {
printf("printed from child [%d]\n", getpid());
printf("signal [%d]\n", sig);
}
Do I need to insert my execl inside the handler function?
No. pause() will return only after the process in which it is called catches a signal that causes a signal-handling function to run. The execl call can therefore go just after the pause call. I think that would be clearer in your case.
Note, too, that POSIX standardizes a list of "async-signal-safe" functions that are safe for a signal handler to call, and that it is unsafe for a handler to call others. execl is on the list, but printf and other stream I/O functions are not. Signal handlers should not call printf. Your particular signal handler does not need to do anything at all.
Additionally, consider using sigsuspend() in place of pause(), as the former will give you more control over which signals cause your trains to start.
I don't understand the significance of this last loop from the answer
to the previous question:
for (int i = 0; i < NUMBER_TRAINS; i++)
{
wait(NULL);
}
The wait() function instructs the calling process to block until one of its children terminates. The loop makes as many wait() calls as there are children, so that, in the absence of errors, the main program does not proceed until all its children have terminated.
It looks like you may have tried to achieve something similar by calling sleep() in the loop with the kill call, but that strategy is plain wrong. In the first place,
waiting after each kill means that the children's execl calls will be spaced out by at least the sleep time, which is not what I understood you to want. In the second place, you cannot know in advance how long it will take the children to finish, so the one second you allow may not be enough under some circumstances. In the third place, since you seem to expect that the children will run very quickly, one second is probably much more than you need most of the time.
I'm using pipe() to split up a file by index, send that index to child processes, have the child process calculate the sum of the numbers in its designated block of the file, and return its sum to the parent.
My children seem to execute in order, where I would like them to execute at the same time to make this process more efficient.
Here's the code I'm working with:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/select.h>
#include <time.h>
int main(int argc, char *argv[])
{
int numchild;
struct timeval stop, start;
int i, j, len, ret, fpos=0, val, count=0, total=0, alltotal=0;
pid_t pid;
int nums = 1000;
FILE * file;
printf("How many children to use: ");
scanf("%d", &numchild);
printf("\nWill use %d child process(es).\n", numchild);
gettimeofday(&start, NULL);
int fd[numchild][2]; //parent to child. one for each
int results[2]; //all children to parent
pipe(results);
fd_set result_fd;
FD_ZERO(&result_fd);
FD_SET(results[0], &result_fd);
struct timeval tm = {.tv_sec=0, .tv_usec=1};
// create all pipes
for (i=0; i<numchild; i++)
{
pipe(fd[i]);
}
for (i=0; i<numchild; i++)
{
if((pid = fork()) == 0) // child process
{
pid = getpid();
// read from parent
len = read(fd[i][0], &fpos, sizeof(fpos));
if (len > 0)
{
file = fopen("file1.dat", "r");
fseek (file, fpos, SEEK_SET);
count = 0;
total = 0;
printf("Child(%d): Recieved position: %d\n", pid, fpos);
// read from file starting at fpos
// add values read to a total value
while (count < (nums/numchild))
{
fscanf(file, "%i", &val);
total += val;
count++;
}
//write to parent
write(results[1], &total, sizeof(total));
printf("Child(%d): Sent %d to parent.\n", pid, total);
}
else
{
printf("Child(%d): Error with len\n", pid);
}
_exit(0);
}
// parent process
pid = getpid();
fpos = ((i*nums*5)/numchild); // 5 is the offset of the file values
// write to child process
printf("Parent(%d): Sending file position to child\n", pid);
write(fd[i][1], &fpos, sizeof(fpos));
// wait for child responce
ret = select(FD_SETSIZE+1, &result_fd, NULL, NULL, NULL); //&tm
if (FD_ISSET(results[0], &result_fd))
{
ret = read(results[0], &total, sizeof(total));
// output total
printf("Parent(%d): Recieved %d from child.\n", pid, total);
alltotal += total;
//printf("\tParent(%d): Total: %d\n", pid, alltotal);
}
}
wait(0);
gettimeofday(&stop, NULL);
printf("\tTime elapsed: %lu microseconds\n", stop.tv_usec - start.tv_usec);
printf("\tParent(%d): Total: %d\n", pid, alltotal);
}
Please let me know what I need to change to have the child processes run simultaneously (not wait to run at the exact same time, but run as soon as the parent gives them their index, instead of waiting for the previous child to complete).
From the comments above, I conclude that:
1. this is an assignment of some type
2. it requires using fork and pipe
If I were doing something like this for real (and it's not clear that it would be worth doing), I would probably be using threads queues and semaphores.
Given the constraints, I'll try to answer your question.
The problem is that you are have the parent code inside the for loop. So what is happening is that each time through the loop, the parent is spawning a child, then sending the offset information, then waiting for the result. So that forces the child to complete before the parent goes through the next iteration of the loop.
The answer is to have more than one loop. In the first loop, spawn all of the children. In the second loop, send the children their offsets. In the third loop, collect the results. In the fourth loop wait for the children to terminate. It would probably be faster if you sent the children their offsets in the first loop.
Another way to do this is to set the offset in a variable prior to doing each fork. That would obviate the need to use pipes for the input. I believe that you could also have each child just exit with the sum. Then the return exit status of the child could be the sum. The parent could just total the sums and you avoid using a return pipe. That would be a better way to do this -- though it wouldn't follow your apparent rules.
I'm writing a multi-threading application(school project, modified river crossing problem).
I'm using POSIX semaphores, shared memory and fork function. Main process creates 2 processes. Each of them then creates N processes. Each process represent a single person. I'd like to know what is the professional technique/the best approach for parent to wait for all of his children till they finish and then obtain their exit code. I don't/can't use constructions like:
while (wait(NULL) > 0)
;
// parent code
Neither constructions using shared variable like
while (1)
if (num_of_processes == num_of_finished_processes)
break;
// parent_code
NOTE: num_of_processes is argument passed to program
Can I somehow use semaphore to tell parent: "now wake up and execute your code".
In one sentence. I don't want to use active/cyclic waiting.
Thank you for any suggestion. I'm just beginner in this field.
The definition of "professional" can be elastic.
There are basically two reasons to reap your children: avoid zombies taking up room in the process table and to interrogate the children return codes and (presumably) base some action on them. Both of these may point to, all things being equal, reaping them as quickly as possible.
So your options are:
have the parent block waiting for them with wait or waitpid.
periodically poll for them with waitpid and the WNOHANG option
have the SIGCHLD signal delivered and handle them as they arise
have the SIGCHLD signal delivered and use signalfd (on linux) but this still requires polling or the use of select/poll/epoll
Since you have rejected 1 & 2 (and implicitly 4) that leaves dealing with the signal and using a handler. For mental health reasons, if not necessarily professionalism, most people avoid signals as much as they can and don't go looking for ways to deal with them if they don't have to do so because:
signal handlers come with their own constraints, primarily that you want to be in and out of them as quickly as possible and there are limited number async-safe functions you should employ within them. So that usually means recording whatever you can inside the handler and dealing with the information when you can in the main program or a thread dedicated to it.
Since you have specifically invited a signal (SIGCHLD) into your life by choosing to handle it, you have bear the consequences of you system calls being interrupted. Since you are using POSIX semaphores then sem_wait would be of particular concern. You can get around most of this by just turning on the SA_RESTART flag via your sigaction call when establishing your handler but even with the flag there are a number of calls which are not automatically restarted.
Multi-threading and signals come with their own set of headaches.
Below is a crude but illustrative example of some of the above issues:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
typedef struct childInfo
{
pid_t childPid;
int childstatus;
} childInfo;
static volatile sig_atomic_t numberOfChildren = 0;
static volatile sig_atomic_t childrenReaped = 0;
childInfo *childrenTable;
void saveStatus(pid_t pid, int status)
{
for (int i = 0; i < numberOfChildren; ++i)
{
if (pid == childrenTable[i].childPid)
childrenTable[i].childstatus = status;
}
}
void printChildrenStatus()
{
for (int i = 0; i < numberOfChildren; ++i)
{
if (childrenTable[i].childPid != 0)
{
if (WIFEXITED(childrenTable[i].childstatus))
printf("PID %d exited normally. "
"Exit status: %d\n",
childrenTable[i].childPid, WEXITSTATUS(childrenTable[i].childstatus));
else
if (WIFSTOPPED(childrenTable[i].childstatus))
printf("PID %d was stopped by %d\n",
childrenTable[i].childPid,
WSTOPSIG(childrenTable[i].childstatus));
else
if (WIFSIGNALED(childrenTable[i].childstatus))
printf("PID %d exited due to signal %d\n.",
childrenTable[i].childPid,
WTERMSIG(childrenTable[i].childstatus));
childrenTable[i].childPid = 0;
childrenReaped++;
}
}
}
void childHandler(int signum)
{
int childstatus;
pid_t childpid;
while ((childpid = waitpid( -1, &childstatus, WNOHANG)) > 0)
saveStatus(childpid, childstatus);
}
int main(int argc, char *argv[])
{
if (argc > 1)
numberOfChildren = atoi(argv[1]);
else
{
printf("must enter num of children to create...");
exit(1);
}
childrenTable = calloc(numberOfChildren, sizeof(childInfo));
struct sigaction sa;
sa.sa_handler = childHandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART; // Restart functions, particularly your parent's
// sem_wait if interrupted by the handler
if (sigaction(SIGINT, &sa, NULL) == -1)
{
perror("sigaction");
exit(1);
}
for (int i = 0; i < numberOfChildren; ++i)
{
pid_t pid = fork();
if (pid)
childrenTable[i].childPid = pid;
else
{
sleep(i);
exit(0);
}
}
while(numberOfChildren - childrenReaped)
{
pause();
printChildrenStatus();
}
return(0);
}
while ( wait(NULL) > 0 )
is an infine loop, because the return value of wait(2) is the pid of the terminated - child process, which is != 0, and won't change.
If you want the parent - process to wait for N processes to exit you can simply use a loop like this:
for (i = 0; i < N; ++i)
wait(NULL);