exec函数族包括以下六个函数:
int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *path, const char *arg, ..., char * const envp[]); int execv(const char *path, char * const argv[]); int execvp(const char *file, char * const argv[]); int execve(const char *path, char * const argv[], char * const envp[]);
示例:创建一个子进程,父进程打印自己的pid,子进程通过exec获取系统命令文件执行ls命令
#include#include #include int main(){ pid_t tempPid; tempPid=fork(); if(tempPid == -1){ perror("fork error"); exit(1); } else if(tempPid > 0) { printf("parent process:pid=%dn", getpid()); } else { printf("child process:pid=%dn", getpid()); char *arg[]={"-a","-l","main.c", NULL}; execvp("ls", arg); perror("error execn"); printf("child process:pid=%dn", getpid()); } //of if return 0; } //of main
运行结果
另外,使用exec函数族调用时不会产生返回值,因此会出现调用失败的情况,比如下面这种:
进程退出比较简单,调用exit()实现,且调用exit()较为安全。
进程同步wait()函数会阻塞进程
调用成功会返回子进程的pid,失败返回-1
示例:
#include#include #include #include int main(){ pid_t tempPid, tempW; tempPid = fork(); if(tempPid == -1){ perror("fork error"); exit(1); }else if(tempPid == 0){//child sleep(3); printf("Child process: pid = %d, ppid = %dn", getpid(), getppid());//子进程的pid和ppid信息 }else{//parent tempW = wait(NULL); printf("my child pid = %d",tempPid); //验证当前父进程的子进程的pid printf("Catched a child process: pid = %dn", tempW);//验证捕获到的子进程的pid }//of if printf("------finish------n"); return 0; }//of main
子进程沉睡三秒后输出了pid和ppid信息,在父进程中调用wait()来捕获僵尸态的子进程信息,因此结果中父进程捕获到的僵尸进程是自己的子进程,即回收子进程。
wait函数的参数不为空,可以获取子进程的退出状态,退出状态存放在参数status的低八位中。
int WIFEXITED(int status) 判断子进程是否正常退出,若是,返回非0值,否则返回0
int WEXITSTATUS(int status)和WIFEXITED配合使用,WIFEXITED返回非0值,则使用该宏提取子进程的返回值。
示例:
#include#include #include #include int main(){ int tempStatus; pid_t tempPid, tempW; tempPid = fork(); if(tempPid == -1){ perror("fork error"); exit(1); } else if(tempPid == 0){//子 sleep(3); printf("Child process: pid=%dn",getpid()); exit(5); //子进程退出状态码 } else{//父 tempW = wait(&tempStatus); //保存子进程pid,退出状态存入参数 if(WIFEXITED(tempStatus)){ //正常退出 printf("Child process pid=%d exit normally.n", tempW ); printf("Return Code:%dn",WEXITSTATUS(tempStatus)); } else { printf("Child process pid=%d exit abnormally.n", tempW); }//of if }//of if return 0; }//of main
结果:子进程正常退出且成功返回状态码。
waitpid()弥补wait()的缺点,可以等待指定的子进程,也可以在父进程不阻塞的情况下获取子进程的状态。
pid_t waitpid(pid_t pid, int *status, int options)
示例:
#include#include #include #include int main(){ pid_t tempPid, tempP, tempW; tempPid= fork(); //创建第一个子进程 if (tempPid == -1){ perror("fork1 error"); exit(1); } else if (tempPid == 0){ //子进程沉睡 sleep(5); printf("First child process:pid=%dn", getpid()); } else { //父进程继续创建进程 int i; tempP = tempPid; for (i = 0; i < 3; i++){ //由父进程创建3个子进程 if ((tempPid = fork()) == 0){ break; }//of if }//of for i if (tempPid == -1){ //出错 perror("fork error"); exit(2); } else if (tempPid == 0){ //子进程 printf("Child process:pid=%dn", getpid()); exit(0); } else { //父进程 tempW = waitpid(tempP, NULL, 0); //等待第一个子进程执行 if (tempW == tempP){ printf("Catch a child Process: pid=%dn", tempW); }else{ printf("waitpid errorn"); }//of if }//of if }//of if return 0; }//of main
结果:第一个子程序先沉睡,因此先输出三个子程序的pid,后输出第一个子进程的pid,使用waitpid()指定等待第一个子进程退出。
示例:
获取状态
#include#include #include #include int main() { pid_t tempPid, tempW; tempPid = fork(); if (tempPid == -1){ perror("fork error"); exit(1); } else if (tempPid == 0){ sleep(3); printf("Child process:pid=%dn", getpid()); exit(0); } else { do{ tempW = waitpid(tempPid, NULL, WNOHANG); if (tempW == 0){ printf("No child exitedn"); sleep(1); }//of if } while (tempW == 0); if (tempW == tempPid){ printf("Catch a Child process:pid=%dn", tempW); }else{ printf("waitpid errorn"); }//of if }//of if return 0; }//of main
结果:因为使用sleep()沉睡,所以父进程一开始无法捕获到子进程输出没有子进程,三秒后子进程终止,父进程捕获到子进程退出信息。



