Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

francis21

macrumors member
Original poster
May 2, 2011
82
2
Mississauga, ON, Canada
Hey people! I just have a question about running child processes in parallel in C using fork().

So what I did was to establish several child processes via the fork() function available using a for-loop. Then, I did my calculations on each child process. An example format would be:

Code:
pid_t process_IDs[num_of_cores];

for (int i = 0; i < num_of_cores; i++) {
    process_IDs[i] = fork();

    if (process_IDs[i] == 0) {
        // Do calculations here in the child.
        ...
    } else if (process_IDs[i] < 0) {
        fprintf(stderr, "fork() error: no child can be created.\n");
        exit(EXIT_FAILURE);
    }
}

Given that, my problem is this: I want to stop further calculations if one of the child processes, after the wait() function is called by the parent, returns an exit status of 0. So I would like to kill everything, using the kill() function.

Note that I kept the process IDs in an array so that I can just keep track of each child process IDs.

So what would be the best way to approach that problem? Thanks!
 

chown33

Moderator
Staff member
Aug 9, 2009
10,751
8,424
A sea of green
I don't see a problem. Use kill(), looping over the pids in the array. Is there some reason that won't work? Are you expecting something else to work better?

If you're going to fork(), and there's no other communication with the child, then kill() is the way to go. By communication I mean waiting on a semaphore, shared memory, pipes, etc. Obviously, signals sent by kill can be treated as communication.

What are the requirements a solution must meet? Does each worker require its own address space? Must it only use Standard C calls? Standard Posix functionality?

Personally, I think fork() is an overly heavyweight approach. You'd be better off using threads (man pthread), assuming the workers can share an address space. Or on a recent OS version, use GCD (Grand Central Dispatch) and it will automatically scale for number of cores.
 

francis21

macrumors member
Original poster
May 2, 2011
82
2
Mississauga, ON, Canada
I don't see a problem. Use kill(), looping over the pids in the array. Is there some reason that won't work? Are you expecting something else to work better?

If you're going to fork(), and there's no other communication with the child, then kill() is the way to go. By communication I mean waiting on a semaphore, shared memory, pipes, etc. Obviously, signals sent by kill can be treated as communication.

What are the requirements a solution must meet? Does each worker require its own address space? Must it only use Standard C calls? Standard Posix functionality?

Personally, I think fork() is an overly heavyweight approach. You'd be better off using threads (man pthread), assuming the workers can share an address space. Or on a recent OS version, use GCD (Grand Central Dispatch) and it will automatically scale for number of cores.

Since this is an assignment, I cannot use other methods learned outside of class, though I'm willing to explore them in the near future.

But if I loop through each and every process IDs in the array I created, would it complain if I try to kill() an earlier process? What I mean is, let say I have the process IDs 1000, 1001, 1002, 1003. And let say that the wait() function returns 1002 and meets the requirement that the exit status of this child process is 0, then if I went through the list of process IDs I created earlier, would the kill() function will experience an error if I kill the process IDs 1000, 1001? Shouldn't I just kill the ones just right after 1002?
 

chown33

Moderator
Staff member
Aug 9, 2009
10,751
8,424
A sea of green
Step 1: Read The Fine Man Page for kill().
This should always be Step 1.

Step 2: So what if kill() returns an ESRCH error?
What does this mean? Simple: no such process. It's terminated by itself for some reason. What reason? I don't know, you didn't tell us what it's doing. If you've designed the child processes to terminate when work is finished, and they have to return that work somewhere, it might be a good idea to do something with the delivered work product. Or ignore it, depending on what your program is designed to do. There's no single right answer. It depends entirely on how you've designed and written the program(s).

Always remember that there's no way to predict the order of process termination. You have little or no absolute control over process scheduling, even if you use nice(). Just because a process is nice'd doesn't mean it won't run. And if it runs, it's entirely possible it will finish its work before some other process doing the same work at a different nice level.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.