目录
1.exec函数族
【案例 1.1】
2.进程退出
3.wait函数
【案例3. 1】
【案例 3.2】
4.waitpid函数
【案例 4.1】
【案例 4.2】
1.exec函数族
- fork:子进程复制父进程的堆栈段和数据段,子进程一旦开始运行,它继承了父进程的一切数据,但实际上数据却已经分开,相互之间不再影响
- exec:一个进程调用exec类函数,它本身就"死亡"了,系统把代码段替换成新的程序代码,废弃原有数据段和堆栈段,并为新程序分配新数据段与堆栈段
exec函数族中包含6个函数,分别为:
#includeint 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[]);
【案例 1.1】
#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());
//execl("/bin/ls","-a","-l","test_exec.c",NULL); //①
//execlp("ls","-a","-l","test_exec.c",NULL); //②
char *arg[]={"-a","-l","test_exec.c", NULL}; //③
execvp("ls", arg);
perror("error execn");
printf("child process:pid=%dn", getpid());
} //of if
return 0;
} //of main
结果:
2.进程退出
#include
void exit(int status);
- 参数说明:
(1)status:表示进程的退出状态,0表示正常退出,非0表示异常退出,一般用-1或1表示;
(2)为了可读性,标准C定义了两个宏:EXIT_SUCCESS和EXIT_FAILURE
Linux系统中有一个与exit()函数非常相似的函数:_exit()
#includevoid _exit(int status);
- 区别:
1)_exit:系统会无条件停止操作,终止进程并清除进程所用内存空间及进程在内核中的各种数据结构;
2)exit:对_exit进行了包装,在调用_exit()之前先检查文件的打开情况,将缓冲区中的内容写回文件。相对来说exit比_exit更为安全
3.wait函数
【案例3. 1】
若子进程p1是其父进程p的先决进程,基于wait函数使得进程同步。
#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()); }else{//parent tempW = wait(NULL); printf("Catched a child process, pid = %d, ppid = %dn", tempW, getppid()); }//of if printf("......finish......"); return 0; }//of main
结果:
【案例 3.2】
使用wait同步进程,并使用宏获取子进程的返回值。
#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); 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
结果:
4.waitpid函数
【案例 4.1】
父进程等待进程组中指定子进程,该进程不退出,则父进程一直阻塞。
#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
结果:
【案例 4.2】
基于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", w); }else{ printf("waitpid errorn"); }//of if }//of if return 0; }//of main
结果:



