您的位置:首页 > 运维架构 > Linux

Linux多任务: exec 和fork()的联用

2013-11-21 10:27 387 查看
  系统调用exec 和fork()联合起来为程序员提供了强有力的功能。我们可以先用fork()建立子进程,然后在子进程中使用exec,这样就实现了父进程运行一个与其不同的子进程,并且父进程不会被覆盖。
  下面我们给出一个exec 和fork()联用的例子,从中我们可以清楚的了解这两个系统调用联用的细节。其程序清单如下:

#include <stdio.h>
#include <unistd.h>
main()
{
int pid;
/* fork 子进程 */
pid=fork();
switch(pid) {
case -1:
perror("fork failed");
exit(1);
case 0:
execl("/bin/ls","ls","-l","--color",NULL);
perror("execl failed");
exit(1);
default:
wait(NULL);
printf("ls completed\n");
exit(0);
}
}


  在程序中,在调用fork()建立一个子进程之后,马上调用了wait(),使父进程在子进程结束之前,一直处于睡眠状态。所以,wait()向程序员提供了一种实现进程之间同步的简单方法,我们将在下面对它作出更详细的讨论。

  为了说明得更清楚一些,我们用图3-3 来解释程序的工作。图3-3 分为fork()调用前、fork()调用后和exec 调用后三个部分。



图1 exec()和fork()的联用

  在fork()调用前,只有一个进程A,PC 指向将要执行的下一个语句。fork()调用后,就有了进程A 和进程B。A 是父进程,它正在执行系统调用wait(),使进程A 睡眠,直至进程B 结束。同时,B 正在用exec 装入命令ls。exec 调用后,进程B 的程序被ls 的代码取代,这时执行ls 命令的代码。进程B 的PC 指向ls 的第一个语句。由于A 正在等待B 的结束,所以它的PC 所指位置未变。
  现在我们应该了解命令解释程序shell 的工作概况。当shell 从命令行接受到以正常方式(即前台运行)执行一个命令或程序的要求时,它就按上述方法调用fork()、exec 和ait(),以实现命令或程序的执行。当要求在后台执行一个命令或程序时,shell 就省略对wait 的调用,使得shell 和命令进程并发运行。

  为了帮助读者进一步熟悉和掌握fork()和exec 的使用,我们再来看一个名为docommand的程序,这个程序仿真Linux 库调用system() ,它可以在程序中执行一个shell 命令。docommand 的主题是对fork()和exec 的调用。程序清单如下:

int docommand(char* command)
{
int pid;
switch(pid=fork())
{
case -1:
return -1;
case 0:
execl("/bin/sh","sh","-c",command,NULL);
exit(127);
default:
wait(NULL);
}
return 0;
}


docommand 并没有通过exec 去直接执行指定的命令,而是通过exec 去执行shell(即/bin/sh),并由shell 再执行指定的命令。这是一种非常巧妙的方法,它使得docommand 能使用shell 提供的一系列特性(如文件名扩展等)。在引用shell 中使用的参数-c,表示从下一个参数中取得命令名,而不是从标准输入上取得。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: