对子进程的execv将其父进程id保留在新程序中而不是零

时间:2014-10-19 21:21:42

标签: c process exec pid

计划说明:

我正在开发一个程序来帮助我了解C和Linux中的进程。该程序使用fork创建子进程,然后父母和孩子都打印出一定数量的消息,相应地说Parent ProcessChild Process。为防止事情被扰乱,父母等待子进程打印所有消息。为了使事情变得更有趣,子进程使用execv来调用另一个打印它的消息的程序。

根据我在execv上所读到的,新流程尚未开始;新的过程映像覆盖原始过程映像。因此,当子进程启动新程序时,新程序中的进程id应该与子进程id为零相同。

问题:

当我在调用execv之前打印出孩子的进程ID时,它为零(正如预期的那样)但是当我进入新程序时,我打印出进程ID并且它是父进程进程ID(但它应该是childs id)。

有人可以解释为什么新程序没有零作为进程ID吗?

参数:

  • Argv[1] =邮件为子进程打印的次数
  • Argv[2] =邮件为父进程打印的次数
  • Argv[3] =子进程消息后等待的秒数
  • Argv[4] =父进程的消息后等待的秒数
  • Argv[5] =发送到子程序启动的新程序的消息(子处理要打印的消息)。

初始计划:

#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);
}

被子流程调用的新程序:

#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);
}

示例输出:

  • 参数为(5 3 1 1&#34; Hello From Child&#34;)

enter image description here

1 个答案:

答案 0 :(得分:3)

我认为你混淆了fork()的返回值的含义。它实际上永远不会返回正在运行的进程的pid,而是返回新生成的子进程的pid(从父进程的角度看)或0,这不是有效的pid,而是用于标识子进程的指示符。 该返回值只是区分两个执行线程和父级跟踪生成哪些子级的一种方式。