tags:

views:

454

answers:

5

I have found examples of how to fork multiple children by having something like this:

if ( fork() = 0 ) {
    //In child
} else {
    if ( fork() = 0 ) {
       //in second child

But if I don't know how many children I am going to need, how might I do this?

For instance, if I have a linked list of commands, and I want to fork and exec for each of them... So I guess I need to know which child it is as well...

+1  A: 

But the number of routines would have to be fixed, even if the execution over those branches is unbounded. So what about a while loop with some sort of switch statement logic to each routine?

uosɐſ
Don't quite follow, maybe if you post a little code ...
Kyle Brandt
I posted an answer (comes with for loop instead of while) containing skeleton code
DVK
The other posts have good examples. But when I say "switch", I'm referring to what appear to be multiple options of execution. A simple loop as they show could run one coded routine many times (forked) but you seem to want multiple routines (a first and a second and so on). The switch (but not necessarily the keyword) piece is for some decision criteria of which routine to run (first or second or so on). You don't know how MANY you'll want to run, but the /options/ of the routines couldn't be infinite, right?
uosɐſ
Jason, thats right, it won't always be the same routine... that is where I am tripped up I think ..
Kyle Brandt
Kyle, well what are you doing to determine which routine of the set of all available routines should be chosen?
uosɐſ
And, not that it matters much, but do want one long chain of decendants or basically one parent with a lot of children?
uosɐſ
+1  A: 

How about

for (i=0; i< 1000; i++) {
    pid = fork();
    if (pid) {
        // Error handling for pid==-1 
        break;
    }
    // Some logic dependent on value of 'i'
}
DVK
So i will be different for each child?
Kyle Brandt
Correct - the first child will be forked when i==0, second will be forked with i==1, etc... so if your commands are in an array of "char*" you can simply exec commands as "command_array[i]"
DVK
+1  A: 
for(i = 0; i < num_children_to_spawn(); ++i) {
    pid_t pid = fork();
    if (pid == -1) {
        exit(-1); /* error */
    } else if (pid == 0) {
        /* child */
        do_child_things();
        break;
    } else {
        /* parent */
    }
}

Note that I didn't use a switch() because it would make it more cumbersome to break out of the loop.

John Ledbetter
`break`? don't you generally want to `exit()` at the end of the child code block?
mobrule
+1  A: 
pid_t children_pids[MAX_CHILDREN];
int last_child_index = 0;
for (int i=0; i < num_wanted_children; i++) {
  pid_t pid = fork();
  if (pid == 0)
    // in child
  else
    children_pids[last_child_index++] = pid;
}
orip
+5  A: 

Taking you at your word that you need to do this for a linked list:

linked_list_of_commands_t *node = root;
while (node != NULL) {
   int pid = fork();
   if (pid == -1) {
       break; // handle error
   } else if (pid == 0) {
       // child
       execv(node->command, node->argv);
       exit(1); // execv should not return, but just in case the execv call fails
   } else {
       node = node->next;
   }
}

This will launch a separate process for every item in the list.

mobrule
This is a good answer. It might be worth it to note that on POSIX systems errno is set after one of the the exec* functions fail.
BobbyShaftoe
@BobbyShaftoe: yes, you could report the error - but the mere fact that an exec-family function returns means it failed.
Jonathan Leffler