exec函数族
使进程执行某一程序。成功无返回值,失败返回-1.
int execlp(const char* file, const char* arg, …); 借助PATH环境变量寻找执行程序
参1:程序名
参2:argv0
参3:argv1
… : argvN
哨兵: NULL
int execl(const char* path, const char* arg, …); 自己指定执行程序路径。
孤儿进程
父进程先于子进程终止,子进程成为孤儿进程,被init进程领养。
僵尸进程
子进程终止,父进程尚未对子进程进行回收,在此期间,子进程为僵尸进程,kill 对其无效。
wait函数
父进程调用wait函数可以回收子进程终止信息,该函数具有三个功能:
1、阻塞等待子进程退出;
2、回收子进程残留资源;
3、获取子进程结束状态(退出原因)。
pid_t wait(int* status);
参数:(传出)回收进程状态
返回值:成功:回收进程的pid,失败:-1.
调用成功返回子进程ID,失败返回-1。
WIFEXITED(status) 返回真,说明子进程正常终止,调用:
WEXITSTATUS(status) 可获取退出状态;
WIFSIGNALED(status) 返回真,说明子进程被信号终止,调用:
WTERMSIG(status) 可获取终止信号。
pid_t waitpid(pid_t pid, int* status, int options);
参数:
pid: 指定回收某一指定子进程,pid>0时,待回收子进程pid;pid=-1时,表示回收任意子进程;pid=0时,同组子进程。
status: (传出)回收进程的状态;
options:WNOHANG 指定回收方式,非阻塞。
返回值:
大于0,表成功回收子进程pid;
等于0,函数调用时,参3指定了 WNHANG ,并且没有子进程结束。
-1,回收失败。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
#include<pthread.h>
int main(int argc, char* argv[])
{
int i;
pid_t pid, wpid;
for(i=0; i<5; i++){
pid=fork();
if(pid==0){
break;
}
}
if(i==5){
while((wpid=waitpid(-1,NULL,WNOHANG)) != -1){
// 循环回收子进程,非阻塞形式
if(wpid>0){
printf("wait child %d \n",wpid);
}else if(wpid==0){
sleep(1);
continue;
}
}
}
else{
sleep(i);
printf("I'm %dth child, pid=%d\n",i+1, getpid());
}
return 0;
}
编程练习
创建两个子进程,分别调用"ls"命令和自定义程序命令,最后使用父进程进行子进程回收:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main(int argc, char* argv[])
{
int i;
pid_t pid, wpid;
for(i=0; i<2; i++){
pid=fork();
if(pid==0){
break;
}
}
if(i==0){
printf("I'm %dth child,pid=%d \n",i+1,getpid());
execlp("ls","ls","-l",NULL);
perror("exec error");
}else if(i==1){
printf("I'm %dth child,pid=%d \n",i+1,getpid());
execl("./t","./t",NULL);
perror("exec error");
exit(1);
}
if(i==2){
sleep(3);
while((wpid=waitpid(-1,NULL,WNOHANG))!=-1){
if(wpid>0){
printf("wait child %d\n",wpid);
}else if(wpid==0){
sleep(1);
continue;
}
}
}
return 0;
}