您的位置:首页 > 大数据 > 人工智能

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

2016-07-12 13:59 393 查看
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()调用从来不会返回。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: