Operating Systems: Three Easy Pieces(操作系统:三个简单方面)5进程API/5.2&&5.3wait()和exec()

5.2系统调用wait()

迄今为止,我们还没做多少工作,只是创建了一个子进程打印了点信息就退出了。事实说明,有时候让父进程去等待子进程结束是十分有用的。这项工作就是由wait()函数完成的(或者由waitpid()函数完成)详见figure5.2。

在程序p2.c中,父进程通过调用wait()函数来延迟自身的执行直至子进程执行完成。当子进程完成,wait()函数就返回到父进程中。

在上面的程序中加入wait()函数使得程序的输出变得确定。你知道为什么咩?小小滴思考一下~

(进入wait过程等待您的思考……考虑完毕,进程结束)

现在你应该已经想了一会了,这里给大家展示一下程序输出:

prompt> ./p2

hello world(pid:29266)

hello, I am child(pid:29267)

hello, I am parentof 29267 (wc:29267) (pid:29266)

prompt>
根据这些代码,我们现在可以知道,子进程永远在父进程前面执行输出操作。为什么我们会知道咧?首先,可能子进程先执行了所以在父进程之前打印。然而,也可能碰巧父进程先运行,那么他会立即出发wait()函数从而让子进程开始执行直至子进程结束退出,然后才会返回到父进程中继续执行。

因此,即使是父进程先执行,它也会礼貌的等待子进程结束后,wait()函数返回后再打印自己的输出信息。


5.3系统调用exec()函数族

最后一个重要的进程创建的API是exec()。在你想要运行一个程序而非调用程序时,这个系统调用非常适用。比如,在程序p2.c中调用fork()函数只是对你在程序运行时拷贝一个与父进程一样的进程有用。然而,我们更多的是想要运行一个不同的程序,exec()函数就是帮我们完成这项工作的。

#include<stdio.h>

#include<stdlib.h>

#include <unistd.h>

#include <string.h>

#include <sys/wait.h>

 

 int main(int argc, char *argv[])

 {

 printf("hello world (pid:%d)\n",(int) getpid());

 int rc = fork();

 if (rc < 0) { // fork failed; exit

 fprintf(stderr, "fork failed\n");

 exit(1);

 } else if (rc == 0) { // child (new process)

 printf("hello, I am child(pid:%d)\n", (int) getpid());

 char *myargs[3];

 myargs[0] = strdup("wc"); //program: "wc" (word count)

 myargs[1] = strdup("p3.c"); //argument: file to count

 myargs[2] = NULL; // marks end of array

 execvp(myargs[0], myargs); // runs word count

 printf("this shouldn’t print out");

 } else { // parent goes down this path (main)

 int wc = wait(NULL);

 printf("hello, I am parent of %d (wc:%d)(pid:%d)\n",

 rc, wc, (int) getpid());

 }

 return 0;

}


Figure 5.3: 调用 fork(), wait(), 和 exec()函数 (p3.c)
在例子5.3中,子进程调用了execvp()来运行进程统计对象wc。实际p3.c源文件运行wc来统计告知我们文件有多少行,多少单词和字节。

prompt> ./p3

hello world(pid:29383)

hello, I am child(pid:29384)

29 107 1030 p3.c

hello, I am parentof 29384 (wc:29384) (pid:29383)

prompt>


这里的fork()函数很奇怪,同样exec()函数也不正常。它做的事情是:在给了执行对象(wc)和参数(p3.c)的情况下,载入可执行程序中的代码并用来覆盖当前的代码段,内存空间的堆栈以及其他部分都重新初始化。然后操作系统开始执行这个程序,并按照argv那样传递进程的参数。因此,它并没有创建一个新的进程,实际上,他只是将当前运行的进程(p3)转换到另一个不同的运行中的进程(wc).当子进程的exec()函数执行完成后,整个程序看起来好像p3从没运行过。一个成功的exec()调用从来不会返回。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值