系统调用wait()

5.2系统调用wait()

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

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

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

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

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

[cpp]  view plain  copy
  1. prompt> ./p2  
  2.   
  3. hello world(pid:29266)  
  4.   
  5. hello, I am child(pid:29267)  
  6.   
  7. hello, I am parentof 29267 (wc:29267) (pid:29266)  
  8.   
  9. prompt>  
根据这些代码,我们现在可以知道,子进程永远在父进程前面执行输出操作。为什么我们会知道咧?首先,可能子进程先执行了所以在父进程之前打印。然而,也可能碰巧父进程先运行,那么他会立即出发wait()函数从而让子进程开始执行直至子进程结束退出,然后才会返回到父进程中继续执行。

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


5.3系统调用exec()函数族

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

[cpp]  view plain  copy
  1. #include<stdio.h>  
  2.   
  3. #include<stdlib.h>  
  4.   
  5. #include <unistd.h>  
  6.   
  7. #include <string.h>  
  8.   
  9. #include <sys/wait.h>  
  10.   
  11.    
  12.   
  13.  int main(int argc, char *argv[])  
  14.   
  15.  {  
  16.   
  17.  printf("hello world (pid:%d)\n",(int) getpid());  
  18.   
  19.  int rc = fork();  
  20.   
  21.  if (rc < 0) { // fork failed; exit  
  22.   
  23.  fprintf(stderr, "fork failed\n");  
  24.   
  25.  exit(1);  
  26.   
  27.  } else if (rc == 0) { // child (new process)  
  28.   
  29.  printf("hello, I am child(pid:%d)\n", (int) getpid());  
  30.   
  31.  char *myargs[3];  
  32.   
  33.  myargs[0] = strdup("wc"); //program: "wc" (word count)  
  34.   
  35.  myargs[1] = strdup("p3.c"); //argument: file to count  
  36.   
  37.  myargs[2] = NULL; // marks end of array  
  38.   
  39.  execvp(myargs[0], myargs); // runs word count  
  40.   
  41.  printf("this shouldn’t print out");  
  42.   
  43.  } else { // parent goes down this path (main)  
  44.   
  45.  int wc = wait(NULL);  
  46.   
  47.  printf("hello, I am parent of %d (wc:%d)(pid:%d)\n",  
  48.   
  49.  rc, wc, (int) getpid());  
  50.   
  51.  }  
  52.   
  53.  return 0;  
  54.   
  55. }  


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

[cpp]  view plain  copy
  1. prompt> ./p3  
  2.   
  3. hello world(pid:29383)  
  4.   
  5. hello, I am child(pid:29384)  
  6.   
  7. 29 107 1030 p3.c  
  8.   
  9. hello, I am parentof 29384 (wc:29384) (pid:29383)  
  10.   
  11. prompt>  


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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值