1

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.

KaP
  • 387
  • 1
  • 2
  • 12
  • Possible duplicate of [Waiting for all child processes before parent resumes](http://stackoverflow.com/questions/1510922/waiting-for-all-child-processes-before-parent-resumes-execution-unix?rq=1) – moffeltje Jun 04 '15 at 11:45
  • 1
    Actually it's not. I've read that topic. Author wants "the parent process to resume execution (the point after this while loop ) only **after all children have terminated**." I wan't to hold all my children till all of them are in the same moment in the code. – KaP Jun 04 '15 at 11:50
  • Ah my bad. I didn't flag it ;) – moffeltje Jun 04 '15 at 11:53

5 Answers5

2

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;
}
Gil Hamilton
  • 11,973
  • 28
  • 51
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:

  1. Personally I like Beej Guides, which are awsome, clear, concise and FREE! http://beej.us/guide/bgipc/
  2. There is also Advanced Linux Programming by CodeSourcery LLC. http://www.advancedlinuxprogramming.com/
  3. And of course, once you have some notions of the basics, you can look up more specifically http://stackoverflow.com, i.e. right here :-)
0

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.

cruxion effux
  • 1,054
  • 3
  • 14
  • 27
  • A semaphore is used to control/grant access to a restricted resource. It is not meant to be used for that use case. – Ely Jun 04 '15 at 12:22
  • Why ? I think we can use semaphore as a general synchronization construct and have used in various programs. Semaphore is a structure with a variable and a queue and nowhere it is said to be used just for restring access to a resource. – cruxion effux Jun 04 '15 at 12:26
  • That is correct. You can use it at your heart's content. Still my feeling is that it turns out to be a "hack" when you try to implement it with a semaphore. I just think there might be a more elegant solution. I thought of Countdown Latch for example. You might be right though... maybe in C there are not too many alternatives. – Ely Jun 04 '15 at 12:33
0

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.

PLG
  • 448
  • 5
  • 21
  • I used OpenMPI for some other projects. In this one MPI-like solutions are useless. Thanks for answer anyway. – KaP Jun 04 '15 at 12:44
0

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.

KaP
  • 387
  • 1
  • 2
  • 12