Kyle Bridenstine
Kyle Bridenstine

Reputation: 6393

execv on a child process is keeping its parents process id in the new program instead of zero

Program Description:

I am working on a program to help teach me about processes in C and Linux. The program uses fork to create a child process and then the parent and the child both print out a message a certain amount of times saying Parent Process, Child Process accordingly. To keep things from being scrambled the parent waits for the child process to print all it's messages. To make things even more interesting the child process uses execv to call another program that prints it's messages.

From what I've read on execv a new process is not started; the new process image overlays the original process image. So when the child process starts the new program the process id inside that new program should be the same as the childs process id which is zero.

Problem:

When I print out the child's process id before calling execv it is zero (as expected) but as soon as I get into the new program I print out the process id and it is the parents process id (but it should be the childs id).

Could anyone please explain why the new program does not have zero as the process id?

Arguments:

Initial Program:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int arg, char *argv[]) {

if(arg < 6) {
    printf("\n\t(Task4.c) Please provide the right arguments\n\n");
    exit(EXIT_FAILURE);
}

char *argv2[3];

argv2[0] = argv[1];
argv2[1] = argv[3];
argv2[2] = argv[5];

int Nc = atoi(argv[1]);
int Np = atoi(argv[2]);
int Tc = atoi(argv[3]);
int Tp = atoi(argv[4]);
int n, exit_code;

pid_t pid;
char *message;

printf("\n\n(Task4.c)\tfork program starting\n");

pid = fork();

//Let child go first before the parent
if(pid != 0) {
    int stat_val;
    pid_t child_pid;

    child_pid = wait(&stat_val);

    printf("\n(Task4.c)\tChild has finished: PID = %d\n", child_pid);
    if(WIFEXITED(stat_val))
        printf("(Task4.c)\tChild exited with code %d\n\n", WEXITSTATUS(stat_val));
    else
        printf("(Task4.c)\tChld terminated abnormally\n");
}

//Set up the values for the parent and child
switch(pid)
{
    case -1:
        perror("(Task4.c)\tfork failed");
        exit(1);
    case 0:
        /* a child execute different program */
        printf("\n(Task4.c)\tpid=%d\n\n", pid);
        if (execv ("child", argv2) <0)
        {
            printf ("(Task4.c)\texecl ERROR");
            exit (EXIT_FAILURE);
        }
        break;
    default:
        message = "This is the parent";
        n = Np;
        exit_code = 0;
        break;
}

//Print the message for the process using their values
for(; n > 0; n--) {
    printf("(Task4.c)\tpid=%d  ", pid);
    puts(message);
    switch(pid)
    {
        case 0:
            sleep(Tc);
            break;
        default:
            sleep(Tp);
            break;
    }
}

printf("\n\n");

exit(exit_code);
}

New Program Being Called By Child Process:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int arg2, char *argv2[]) {

if(arg2 < 3) {
    printf("\n\t(child.c) Please provide the right arguments\n\n");
    exit(EXIT_FAILURE);
}

int Nc2 = atoi(argv2[0]);
int Tc2 = atoi(argv2[1]);

int Np2 = 5;
int Tp2 = 1;
int n2, exit_code2;

//Here I was expected to get 0 as the pid...
pid_t pid2 = getpid();
char *message2;

printf("(child.c)\tchild program starting\n\n");
printf("(child.c)\tpid=%d  \n\n", pid2);

switch(pid2)
{
    case -1:
        perror("(child.c) fork failed");
        exit(1);
    case 0:
        message2 = argv2[2];
        n2 = Nc2;
        exit_code2 = 37;
        break;
    default:
        message2 = "(child.c)\tThis is the parent";
        n2 = Np2;
        exit_code2 = 0;
        break;
}

for(; n2 > 0; n2--) {
    printf("(child.c)\tpid=%d  ", pid2);
    puts(message2);
    switch(pid2)
    {
        case 0:
            sleep(Tc2);
            break;
        default:
            sleep(Tp2);
            break;
    }
}

exit(37);
}

Example Output:

enter image description here

Upvotes: 0

Views: 1833

Answers (1)

lnvd
lnvd

Reputation: 137

I think you are confusing the meaning of the return value of fork(). It actually never returns the pid of the running process, but either the pid of the freshly spawned child (from the parent's perspective) or 0, which is not a valid pid but an indicator to identify the child. That return value is just a way to distinguish the two execution threads and for the parent to keep track which children have been spawned.

Upvotes: 3

Related Questions