C语言中系统函数的工作原理

3

我已经阅读过,系统函数内部使用execl、fork和wait函数。因此,我试图模拟不使用system函数的工作方式。但是我无法实现相同的工作。

当我们使用system函数调用程序时,在system()函数调用之后,下面的代码也会执行。因此,为了模拟system函数,我编写了以下代码:

int main()
{
    printf("In controller Start: %d\n\n",getpid());
    system("./prog1");
    printf("Forking New Process %d\n\n",fork());
    printf("Process Id: %d\n\n",getpid());
    execl("./infinite",0);
    printf("In controller End\n\n");
    return 0;
}

在上面的代码中,运行“infinite”程序后,最后一行不会被打印出来。
printf("In controller End\n\n"); 为了打印出最后一行并执行“无限”程序,而又不使用system函数,应该怎么做?
如果有人能够逐步解释系统函数的工作原理,例如哪个函数首先被系统调用等,则会非常好。
为什么执行不会继续到最后一行,就像我们进行简单的函数调用(除execl之外)那样。
注:infinite是使用C代码创建的二进制文件。

我之前是多么愚蠢啊。 - mSatyam
6个回答

5
最后一行没有被打印出来,因为它从未被执行。如果一切顺利,execl函数不会返回,而是用调用中的程序替换您的程序。
我强烈建议您阅读forkexecl的手册页面。
简而言之,fork将当前进程分成两个部分,并根据它返回到父进程还是子进程而返回不同的结果。在子进程中,您可以进行exec调用,而父进程则继续执行其想要的操作。但是,父进程必须wait等待子进程完成,否则子进程将成为所谓的“僵尸”进程
在您的代码中,父进程和子进程都调用了exec

2

这是fork的基础知识。

/*previous code*/
if((cpid=fork())<0){
    printf("\n\tFORK ERROR");
    exit(1);
}

if(cpid==0){        /*SON*/
    /*CODE FOR SON-your `execl("./infinite",0);` goes here*/

}else{              /*FATHER*/

    /*CODE FOR FATHER-your `printf("In controller End\n\n");` */

}

不要忘记,制作分支时内存和变量会复制到子进程的PID。


@msatyam,你能帮我点个赞吗?因为我的提问权限被撤销了,我需要它们回来,谢谢。 - mf_

2
当您调用fork()时,父进程和子进程都从该点继续执行相同的代码,但对于每个进程,fork()的返回值是不同的。通常您会根据返回值进行一些条件逻辑。
我想system()大致是这样实现的:
int childpid = fork();
if (childpid) {
  /* This is the parent */
  wait( childpid );
} else {
  /* This is the child */
  execl( program_name );
}

由于execl()替换了当前可执行文件为新的可执行文件,子进程将会运行该可执行文件并结束。父进程将等待子进程完成后继续执行。


2

在你的示例中,父进程和子进程都执行了相同的操作。你需要检查fork的返回值以确定你处于父进程还是子进程,并在子进程中使用exec,同时在主进程中等待。


1
他使用fork,只是在两个结果进程中执行相同的操作。 - Will
啊,没错。它藏得很好 :) - jbr

1
你没有根据fork的返回值执行任何条件语句。如果你不确定一个进程执行exec,而另一个进程执行其他操作,那么两个进程都会执行相同的操作。
通常你需要检查0,然后执行想要运行的程序。 0表示一切正常,你在子进程中。

0
int main()
{
    int pid;

    printf("In controller Start: %d\n\n",getpid());

    system("./prog1");

    pid = fork();

    printf("Forking New Process %d\n\n",pid);
    printf("Process Id: %d\n\n",getpid());

    if (pid == 0) {  /* Son process : execute the command */
        execl("./infinite",0);
    } else {  /* Original process : keep working */
        printf("In controller End\n\n");
        return 0;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接