2010-09-28 回答
父进程为什么要创建子进程呢?前面我们已经说过了linux是一个多用户操作系统,在同一时间会有许多的用户在争夺系统的资源.有时进程为了早一点完成任务就创建子进程来争夺资源. 一旦子进程被创建,父子进程一起从fork处继续执行,相互竞争系统的资源.有时候我们希望子进程继续执行,而父进程阻塞直到子进程完成任务.这个时候我们可以调用wait或者waitpid系统调用.
#i nclude
#i nclude
pid_t wait(int *stat_loc);
pid_t waitpid(pid_t pid,int *stat_loc,int options);
wait系统调用会使父进程阻塞直到一个子进程结束或者是父进程接受到了一个信号.如果没有父进程没有子进程或者他的子进程已经结束了wait回立即返回.成功时(因一个子进程结束)wait将返回子进程的id,否则返回-1,并设置全局变量errno.stat_loc是子进程的退出状态.子进程调用exit,_exit 或者是return来设置这个值. 为了得到这个值linux定义了几个宏来测试这个返回值.
wifexited:判断子进程退出值是非0
wexitstatus:判断子进程的退出值(当子进程退出时非0).
wifsignaled:子进程由于有没有获得的信号而退出.
wtermsig:子进程没有获得的信号号(在wifsignaled为真时才有意义).
waitpid等待指定的子进程直到子进程返回.如果pid为正值则等待指定的进程(pid).如果为0则等待任何一个组id和调用者的组id相同的进程.为-1时等同于wait调用.小于-1时等待任何一个组id等于pid绝对值的进程. stat_loc和wait的意义一样. options可以决定父进程的状态.可以取两个值 wnohang:父进程立即返回当没有子进程存在时. wuntached:当子进程结束时waitpid返回,但是子进程的退出状态不可得到.
父进程创建子进程后,子进程一般要执行不同的程序.为了调用系统程序,我们可以使用系统调用exec族调用.exec族调用有着5个函数.
#i nclude
int execl(const char *path,const char *arg,…);
int execlp(const char *file,const char *arg,…);
int execle(const char *path,const char *arg,…);
int execv(const char *path,char *const argv[]);
int execvp(const char *file,char *const argv[]):
exec族调用可以执行给定程序.关于exec族调用的详细解说可以参考系统手册(man execl). 下面我们来学习一个实例.注意编译的时候要加 -lm以便连接数学函数库.
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
#i nclude
void main(void)
{
pid_t child;
int status;
printf(”this will demostrate how to get child status\n”);
if((child=fork())==-1)
{
printf(”fork error :%s\n”,strerror(errno));
exit(1);
}
else if(child==0)
{
int i;
printf(”i am the child:%ld\n”,getpid());
for(i=0;i<1000000;i++) sin(i);
i=5;
printf(”i exit with %d\n”,i);
exit(i);
}
while(((child=wait(&status))==-1)&(errno==eintr));
if(child==-1)
printf(”wait error:%s\n”,strerror(errno));
else if(!status)
printf(”child %ld terminated normally return status is zero\n”,
child);
else if(wifexited(status))
printf(”child %ld terminated normally return status is %d\n”,
child,wexitstatus(status));
else if(wifsignaled(status))
printf(”child %ld terminated due to signal %d znot caught\n”,
child,wtermsig(status));
}
strerror函数会返回一个指定的错误号的错误信息的字符串.