Thread: Help with fork()

  1. #1
    Registered User
    Join Date
    Nov 2010
    Posts
    20

    Help with fork()

    Ok, so I know the basics of fork, however I am confused about a couple things. Basically, I will spare the details of my program, but I need to write code that will receive a number on execution and spawn that many processes to carry out my code. I don't need help with the algorithm that splits my code up, I just don't understand how to spawn all the processes to be carried out at the same time.

    For example, if I constructed a for loop that would "fork" x times, where x is the specified number of processes, for all intents and purposes wouldn't this be the same as just using 1 process, since the next fork would not begin until the first fork finished?

    The idea here is to carry out multiple processes simultaneously for quicker computation. Thanks for reading.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    wouldn't this be the same as just using 1 process, since the next fork would not begin until the first fork finished?
    No. Forking runs the child processes concurrently with the parent, in a non-blocking fashion. You can fork numerous children and once that loop is done, the parent process will continue running. Your code should look roughly like this:
    Code:
    for (i = 0; i < x; i++) {
        pid = fork();
        switch (pid) {
            case -1:
                // error
                break;
            case 0:
                // act childish
                break;
            default:
                // record child's pid if needed for checking signals later
                break;
        }
    }
    Do pay attention to things like inherited file handles, etc. There seems to be a decent little explanation here, if you want some more info: Mr. Peabody Explains fork().

  3. #3
    Registered User
    Join Date
    Nov 2010
    Posts
    20
    Quote Originally Posted by anduril462 View Post
    No. Forking runs the child processes concurrently with the parent, in a non-blocking fashion. You can fork numerous children and once that loop is done, the parent process will continue running. Your code should look roughly like this:
    Code:
    for (i = 0; i < x; i++) {
        pid = fork();
        switch (pid) {
            case -1:
                // error
                break;
            case 0:
                // act childish
                break;
            default:
                // record child's pid if needed for checking signals later
                break;
        }
    }
    Do pay attention to things like inherited file handles, etc. There seems to be a decent little explanation here, if you want some more info: Mr. Peabody Explains fork().
    Just to be clear, this coding would allow for up to X processes to be spawned all at the same time and they would all carry out their processes concurrently, correct? Also, thanks for the link, it was helpful for my conceptual understanding.

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> this coding would allow for up to X processes
    If both the parent and child continue to run the for-loop, you'll end up with more than 'x' offspring.

    gg

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Yes. There is a caveat though, the child processes will need to exit from the case statement, otherwise it will fall into the loop it inherited from it's parents and fork it's own children, etc (leading to grandchildren, etc). This could eat up resources very quickly.

    Try the following code as proof. I compiled it with gcc as "gcc -Wall fork.c -o foobar". Then, I ran it as "./foobar 3", and for extra proof, in a second terminal window I ran "ps -ef | grep foobar" while foobar was still running.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <errno.h>
    
    int main(int argc, char *argv[])
    {
        int     i,
                x = 0,
                pid,
                nap_time;
    
        if (argc != 2) {
            printf("Missing command line option\n");
            return 1;
        }
    
        x = atoi(argv[1]);
        if (x == 0) {
            printf("Need a numeric command line option\n");
            return 1;
        }
    
        for (i = 0; i < x; i++) {
            pid = fork();
            switch (pid) {
                case -1:
                    // error
                    fprintf(stderr, "fork failed: %s\n", strerror(errno));
                    break;
    
                case 0:
                    // act childish
                    srand(getpid());
                    nap_time = rand() % 5 + 2;
                    printf("Child %i going to sleep for %d seconds\n", i, nap_time);
                    sleep(nap_time);
                    printf("Child %i waking up\n", i);
                    return 0;  // If you just did break, you would get 1 + 2 + ... + x child processes
    
                default:
                    // record child's pid if needed for checking signals later
                    break;
            }
        }
    
        sleep(10);
    
        return 0;
    }
    $ ps -ef | grep foobar
    anduril462 5860 5539 0 16:05 pts/2 00:00:00 ./foobar 3
    anduril462 5861 5860 0 16:05 pts/2 00:00:00 ./foobar 3
    anduril462 5862 5860 0 16:05 pts/2 00:00:00 ./foobar 3
    anduril462 5863 5860 0 16:05 pts/2 00:00:00 ./foobar 3
    anduril462 5865 5813 0 16:05 pts/1 00:00:00 grep foobar

  6. #6
    Registered User
    Join Date
    Nov 2010
    Posts
    20
    Quote Originally Posted by anduril462 View Post
    Yes. There is a caveat though, the child processes will need to exit from the case statement, otherwise it will fall into the loop it inherited from it's parents and fork it's own children, etc (leading to grandchildren, etc). This could eat up resources very quickly.

    Try the following code as proof. I compiled it with gcc as "gcc -Wall fork.c -o foobar". Then, I ran it as "./foobar 3", and for extra proof, in a second terminal window I ran "ps -ef | grep foobar" while foobar was still running.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <errno.h>
    
    int main(int argc, char *argv[])
    {
        int     i,
                x = 0,
                pid,
                nap_time;
    
        if (argc != 2) {
            printf("Missing command line option\n");
            return 1;
        }
    
        x = atoi(argv[1]);
        if (x == 0) {
            printf("Need a numeric command line option\n");
            return 1;
        }
    
        for (i = 0; i < x; i++) {
            pid = fork();
            switch (pid) {
                case -1:
                    // error
                    fprintf(stderr, "fork failed: %s\n", strerror(errno));
                    break;
    
                case 0:
                    // act childish
                    srand(getpid());
                    nap_time = rand() % 5 + 2;
                    printf("Child %i going to sleep for %d seconds\n", i, nap_time);
                    sleep(nap_time);
                    printf("Child %i waking up\n", i);
                    return 0;  // If you just did break, you would get 1 + 2 + ... + x child processes
    
                default:
                    // record child's pid if needed for checking signals later
                    break;
            }
        }
    
        sleep(10);
    
        return 0;
    }
    $ ps -ef | grep foobar
    anduril462 5860 5539 0 16:05 pts/2 00:00:00 ./foobar 3
    anduril462 5861 5860 0 16:05 pts/2 00:00:00 ./foobar 3
    anduril462 5862 5860 0 16:05 pts/2 00:00:00 ./foobar 3
    anduril462 5863 5860 0 16:05 pts/2 00:00:00 ./foobar 3
    anduril462 5865 5813 0 16:05 pts/1 00:00:00 grep foobar
    Thanks for the coding, I think I'm beginning to understand it better. I just still don't see how this spawns all the processes simultaneously.

    Additionally, I would like to know if something is possible. Is it possible to have a 2d array declared before the child processes are spawned, but then as each child process carries its' tasks out, pipe certain numbers back into the original 2d array?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fork problem
    By lordofdarkness in forum C Programming
    Replies: 1
    Last Post: 02-14-2010, 08:16 PM
  2. Fork(), pause(), and storing PID's in a linked list
    By vital101 in forum C Programming
    Replies: 10
    Last Post: 09-28-2007, 02:16 AM
  3. Fork - unpredictable?
    By fredkwok in forum Linux Programming
    Replies: 4
    Last Post: 03-26-2006, 02:49 PM
  4. fork(), exit() - few questions!
    By s3t3c in forum C Programming
    Replies: 10
    Last Post: 11-30-2004, 06:58 AM
  5. Daemon programming: allocated memory vs. fork()
    By twisgabak in forum Linux Programming
    Replies: 2
    Last Post: 09-25-2003, 02:53 PM