AzuelleDawn88
AzuelleDawn88

Reputation: 9

Using Fork() and Exec() for Child Processes in Ubuntu

I am new to C++ and Linux and I am confused on how to correctly pass an integer parameter using execlp() to a child class. I tried following the parameter requirements for this system call, however, the argument is not passing the correct value when I am executing the program. The char conversions is what is making me confused.

In the programs below, the parent accepts gender name pairs from the terminal. Next, it uses the fork() and exec() system calls where it passes the child number, gender, and name to the child program. The child program will output the statement. The output for the child numbers is off (should be: 1,2,3,4,...ect.). However, the output value is blank. Is it because of how I am initializing the argument in the execlp() system call?

Below is my code for the parent program - parent.cc:

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

int main (int argc, char* argv[])
{
    int i, num = 0;
    /* Holds the value of the number of pairs */
    int pairs = (argc - 1) / 2;
    pid_t pid;
    
    cout << "I have " << pairs << " children." << endl;
    
    /* Perform all child process depending on the number of name-gender pairs*/
    for (i = 1; i <= argc-1; i+=2)
    {
        pid = fork();
        /* Child process */
        if (pid == 0)
        { 
            char n[] = {char(num++)};
            execlp("./c",n,argv[i],argv[i+1], NULL);
        }
        /* Parent will wait until all child processes finish */
        wait(NULL);
    }
    cout << "All child process terminated. Parent exits." << endl;
    
    /* Exits program */
    return 0;
}

Here is my child program- child.cc

#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

using namespace std;

int main(int argc, char* argv[])
{
    /* When child process starts, it will print out this statement */
    cout << "Child # " << argv[0] << ": I am a " << argv[1] << ", and my name is " << argv[2] << endl;  
    exit(0);
}

Here is my output in the terminal:

g++ -o parent.cc
g++ -o c child.cc
./p boy Mark girl Emily boy Daniel girl Hailey
I have 4 children.
Child # : I am a boy, and my name is Mark
Child # : I am a girl, and my name is Emily
Child # : I am a boy, and my name is Daniel
Child # : I am a girl, and my Hailey
All child process terminated. Parent exits.

Upvotes: 0

Views: 1297

Answers (1)

that other guy
that other guy

Reputation: 123410

There's two and a half issues:

  • You are not correctly converting an integer to a string, so the value is wrong
  • You are incrementing the number in the child process, so the next child process won't see the update
  • argv[0] is conventionally the program name, and failing to follow this convention means that e.g. ./c 1 boy Mark will not work in a shell, and that the child process can't easily be substituted for something written in a different language.

Here's the updated parent process:

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

int main (int argc, char* argv[])
{
    int i, num = 0;
    /* Holds the value of the number of pairs */
    int pairs = (argc - 1) / 2;
    pid_t pid;
    
    cout << "I have " << pairs << " children." << endl;
    
    /* Perform all child process depending on the number of name-gender pairs*/
    for (i = 1; i <= argc-1; i+=2)
    {
        pid = fork();
        /* Child process */
        if (pid == 0)
        { 
            string str = to_string(num);
            execlp("./c",
               "./c",       // Conventionally the first argument is the program name
               str.c_str(), // Pass in the correctly formatted number
               argv[i],argv[i+1], NULL);
        }
        // Increment in the parent process so that the change is not lost
        num++;
        /* Parent will wait until all child processes finish */
        wait(NULL);
    }
    cout << "All child process terminated. Parent exits." << endl;
    
    /* Exits program */
    return 0;
}

Accordingly, the child should access argv[1], 2, and 3, and not 0, 1 and 2.

Upvotes: 1

Related Questions