输出结果为:

我们可以看到,之前在第二点中没有出现的ps Done是打印出来了,但是顺序却有点不对,这是因为,父进程先于子程序执行,所以先输出了Parent, ps Done,那有没有办法让它在子进程输出完之后再输出,当然有,就是用wait和waitpid函数。注意,一般情况下,父进程与子进程的生命周期是没有关系的,即便父进程退出了,子进程仍然可以正常运行。
2、等待一个进程
wait函数和waitpid函数的原型为:
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *stat_loc); pid_t waitpid(pid_t pid, int *stat_loc, int options);
wait用于在父进程中调用,让父进程暂停执行等待子进程的结束,返回子进程的PID,如果stat_loc不是空指针,状态信息将被写入stat_loc指向的位置。
waitpid等待进程id为pid的子进程的结束(pid为-1,将返回任一子进程的信息),stat_loc参数的作用与wait函数相同,options用于改变waitpid的行为,其中有一个很重要的选项WNOHANG,它的作用是防止waippid调用者的执行挂起。如果子进程没有结束或意外终止,它返回0,否则返回子进程的pid。
改变后的程序保存为源文件new_ps_fork2.c,代码如下:
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
pid_t pid = fork();
int stat = 0;
switch(pid)
{
case -1:
perror("fork failed");
exit(1);
break;
case 0:
//这是在子进程中,调用execlp切换为ps进程
printf("n");
execlp("ps", "ps", "au", 0);
break;
default:
//这是在父进程中,等待子进程结束并输出相关提示信息
pid = wait(&stat);
printf("Child has finished: PID = %dn", pid);
//检查子进程的退出状态
if(WIFEXITED(stat))
printf("Child exited with code %dn", WEXITSTATUS(stat));
else
printf("Child terminated abnormallyn");
printf("Parent, ps Donen");
break;
}
exit(0);
}
输出为:

可以看到这次的输出终于正常了,Parent的输出也在子进程的输出之后。
总结——三种启动新进程方法的比较
首先是最简单的system函数,它需要启动新的shell并在新的shell是执行子进程,所以对环境的依赖较大,而且效率也不高。同时system函数要等待子进程的返回才能执行下面的语句。
exec系统函数是用新的进程来替换原先的进程,效率较高,但是它不会返回到原先的进程,也就是说在exec函数后面的所以代码都不会被执行,除非exec调用失败。然而exec启动的新进程继承了原进程的许多特性,在原进程中已打开的文件描述符在新进程中仍将保持打开,但需要注意,任何在原进程中已打开的目录流都将在新进程中被关闭。










