1

I'm writing a program that uses the cpu power to process some information. The program depends on the CPU cores. If there are 2 cores, the program will fork() twice to create 2 instances of the work and return the results.

#define CORES 4

void worker(int id)
{    
    // blablabla work here
    printf("worker %d\n",id);
    printf("[%d] I'm child of %d\n",getpid(),getppid());    
}

int main (int argc, const char * argv[])
{
    int pid;

    for (int i=0; i<CORES; i++)
    {
        pid = fork();
        if (pid == 0) // if child
        {
            worker(i);
            exit(0);
        }
        else if (pid>0)
        {
            printf("[%d] Big father here!\n",getpid());
        }
        else
        {
            printf("--- Fork problem ---");
        }
    }

    return 0;

}

My questions:

  1. What can I do so the program only terminates when ALL the child processes are done processing the required information? (i think they're becoming orphans)
  2. How to count the time it took since the first process started working until the last process terminates
Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
andrepcg
  • 1,301
  • 7
  • 26
  • 45

3 Answers3

6

Use wait() to wait for children to terminate:

int status;
pid_t pid;

while ((pid = wait(&status)) != -1) {
    // pid just terminated
}

// all children terminated

See man 2 wait.

For measuring the time, see gettimeofday():

struct timeval tv = {0};

gettimeofday(&tv, NULL);

struct timeval:

struct timeval {
    time_t      tv_sec;     /* seconds */
    suseconds_t tv_usec;    /* microseconds */
};
Arnaud Le Blanc
  • 98,321
  • 23
  • 206
  • 194
3

To wait for the child processes to be finished, you use any of the wait family of system calls. If you use wait4, the kernel will give you information about how much CPU and wall-clock time each process consumed. However, you may find that calling gettimeofday at the beginning and the end of the run is easier.

zwol
  • 135,547
  • 38
  • 252
  • 361
0

One way to do what you want: Write a SIGCHLD handler that increments a counter. (Declare the counter volatile or mischief may ensue.) Then sigsuspend() repeatedly waiting on SIGCHLD. When the counter matches CORES, terminate.

To time this, call time() just before spawning the worker threads and then just before termination; difftime(3) will give you the time difference in seconds as a double.

ESR
  • 574
  • 1
  • 5
  • 10
  • 1
    Why on earth would you muck around with signals when a simple `wait[pid]` loop will do the job? – zwol Sep 19 '11 at 17:45
  • Zack, mainly because my C reflexes were formed back when wait(2) behavior was a lot murkier and more platform-dependent. Looking at a modern wait(2) manual page I agree that a wait loop would make sense, _if_ all that complexity is implemented correctly and to standard. – ESR Sep 24 '11 at 07:19
  • Don't forget to also declare the *type* of the counter as `sigatomic_t` :) – user4815162342 Apr 21 '13 at 20:22
  • @ESR, that won't actually work right. The `SIGCHLD` signal may not happen a number of times equal to the number of children that die. I ran in that problem myself as I have heavily been running daemons for the past two years. It does not happen often, but when it does you go out of sync. Also what does the parent do while waiting? Call sleep()? Unless the parent does part of the calculation, but it will be slowed down by the interruptions... – Alexis Wilke Dec 13 '16 at 22:29