1.exec函数族和fork函数的区别
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 #include2 #include 3 #include 4 int main() 5 { pid_t tempPid; 6 tempPid=fork(); 7 if(tempPid == -1){ 8 perror("fork error"); 9 exit(1); 10 }else if(tempPid>0) { 11 printf("parent process :pid=%dn",getpid()); 12 } else { 13 printf("child process : pid=%dn"getpid()); 14 char *arg[]={"-a","-l","demo1.c",NULL}; 15 execvp("ls",arg); 16 perror("error execn"); 17 printf("child process:pid=%dn",getpid()); 18 }//of it 19 return 0; 20 }//of main
运行:
2.wait函数
#include
pid_t wait(int *status);
案例2 若进程p1是其父进程p的先决进程,基于wait函数使得进程同步
#include#include #include #include int main(){ pid_t pid,w; pid = fork(); if(pid == -1){ perror("fork error"); exit(1); } else if( pid == 0){ sleep(3); printf("Child proccess: pid =%dn",getpid()); exit(5); } else if( pid > 0){ int status; w = wait(&status); if(WIFEXITED(status)){ printf("Child process pid = %d exit normally.n",w); printf("Return Code:%dn",WEXITSTATUS(status)); } else{ printf("Child process pid = %d exit abnormally.n",w); } } return 0; }
waitpid函数:
#include
pid_t waitpid(pid_t pid int *status int options);
案例3代码
#include#include #include #include int main(){ pid_t pid,p,w; pid = fork();//创建第一个子进程 if(pid == -1){//第一个子进程创建后父子进程的执行内容 perror("fork error"); exit(1); } else if(pid == 0){//子进程沉睡 sleep(5); printf("First child process: pid =%dn",getpid()); } else if(pid > 0){//父进程继续创建进程 int i; p = pid; for(i = 0; i<3 ; i++){//由父进程创建3个子进程 if( (pid=fork()) == 0){ break; } } if( pid == -1){//出错 perror("fork error"); exit(2); } else if(pid == 0){//子进程 printf("Child process: pid =%dn",getpid()); exit(0); } else if(pid > 0){//父进程 w =waitpid(p,NULL,0);//等待第一个子程序执行 if(w == p){ printf("Catch a child Process : pid = %dn",w); } else{ printf("waitpid errorn"); } } } return 0; }
特殊进程的危害
僵尸进程不能再次被运行,而且会占用一定的内存空间,并占据进程编号(id),当僵尸进程较多时,将会消耗系统内存,新进程可能因内存不足或无法获取pid而无法创建。
父进程通过 wait() 和 waitpid() 函数可以有效防止僵尸进程的产生,对于已存在的僵尸进程,则可通过杀死其父进程的方法解决。
当僵尸进程的父进程被终止后,僵尸进程将作为孤儿进程被 init 进程接收,init 进程会不断调用wait() 函数获取子进程状态,对已处于僵尸态的进程进行处理。
孤儿进程永远不会成为僵尸进程。



