1.exec函数族和fork函数的区别
fork: 子进程复制父进程的堆栈段和数据段,子进程一旦开始运行,它继承了父进程的一切数据,但实际上数据却已经分开,相互之间不再影响
exec:一个进程调用exec类函数,它本身就"死亡"了,系统把代码段替换成新的程序代码,废弃原有数据段和堆栈段,并为新程序分配新数据段与堆栈段
exec 函数族中包含6个函数,分别为:
#Include <unistd.h>
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[]);
————————————————
案例1代码:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
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=%d\n",getpid());
12 } else {
13 printf("child process : pid=%d\n"getpid());
14 char *arg[]={"-a","-l","demo1.c",NULL};
15 execvp("ls",arg);
16 perror("error exec\n");
17 printf("child process:pid=%d\n",getpid());
18 }//of it
19 return 0;
20 }//of main
运行:
2.wait函数
#include<sys/wait.h>
pid_t wait(int *status);
案例2 若进程p1是其父进程p的先决进程,基于wait函数使得进程同步
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
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 =%d\n",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:%d\n",WEXITSTATUS(status));
}
else{
printf("Child process pid = %d exit abnormally.\n",w);
}
}
return 0;
}
waitpid函数:
#include<sys/wait.h>
pid_t waitpid(pid_t pid int *status int options);
案例3代码
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
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 =%d\n",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 =%d\n",getpid());
exit(0);
}
else if(pid > 0){//父进程
w =waitpid(p,NULL,0);//等待第一个子程序执行
if(w == p){
printf("Catch a child Process : pid = %d\n",w);
}
else{
printf("waitpid error\n");
}
}
}
return 0;
}
特殊进程的危害
僵尸进程不能再次被运行,而且会占用一定的内存空间,并占据进程编号(id),当僵尸进程较多时,将会消耗系统内存,新进程可能因内存不足或无法获取pid而无法创建。
父进程通过 wait() 和 waitpid() 函数可以有效防止僵尸进程的产生,对于已存在的僵尸进程,则可通过杀死其父进程的方法解决。
当僵尸进程的父进程被终止后,僵尸进程将作为孤儿进程被 init 进程接收,init 进程会不断调用wait() 函数获取子进程状态,对已处于僵尸态的进程进行处理。
孤儿进程永远不会成为僵尸进程。