exec中6个函数族分别为
#include
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[]);
可以将exec函数族分为execl和execv两类:
如果没有参数char * const envp[],则采用默认环境变量;如果有,则用传入的参数替换默认环境变量
#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=%d\n", getpid());
} else {
printf("child process:pid=%d\n", getpid());
//execl("/bin/ls","-a","-l","test_exec.c",NULL); //①
execlp("ls","-a","-l","exec_yj.c",NULL); //② 这里采用第二种方法
//char *arg[]={"-a","-l","test_exec.c", NULL}; //③
//execvp("ls", arg);
perror("error exec\n");
printf("child process:pid=%d\n", getpid());
} //of if
return 0;
} //of main
#include
void exit(int status);
参数说明:
#include
void _exit(int status);
对之前概念的补充和新概念的学习
#include
pid_t wait(int *status);
若子进程p1是其父进程p的先决进程,基于wait函数使得进程同步。
#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 = %d\n", getpid(), getppid());
}else{//parent
tempW = wait(NULL);
printf("Catched a child process, pid = %d, ppid = %d\n", tempW, getpid());
}//of if
printf("......finish......\n");
return 0;
}//of main
把wait函数注释掉,父进程先于子进程运行并终止。因为sleep函数导致子进程进入等待队列,所以终端竞争得到了运行权。
查看发现已经被init领养。
以上是wait函数参数为空的情况,下面进行记录子进程退出状态。
使用wait同步进程,并使用宏获取子进程的返回值。此处声明两个判断进程退出状态的宏函数:
#include
int WIFEXITED(int status);//判断子进程是否正常退出,若是,返回非0值,否则返回0
int WEXITSTATUS(int status);//和WIFEXITED配合使用,WIFEXITED返回非0值,则使用该宏提取子进程的返回值。
#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=%d\n",getpid());
exit(5);
} else{//父
tempW = wait(&tempStatus);
if(WIFEXITED(tempStatus)){
printf("Child process pid=%d exit normally.\n", tempW );
printf("Return Code:%d\n",WEXITSTATUS(tempStatus));
} else {
printf("Child process pid=%d exit abnormally.\n", tempW);
}//of if
}//of if
return 0;
}//of main
#include
pid_t waitpid(pid_t pid, int *status, int options);
1 WNOHANG:如果子进程没有终止,waitpid不会阻塞父进程,会立即返回;
2. WUNTRACED:如果子进程暂停执行,waitpid立即返回;
3. 0:不使用选项。
父进程等待进程组中指定子进程,该进程不退出,则父进程一直阻塞。
#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=%d\n", 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=%d\n", getpid());
exit(0);
} else { //父进程
tempW = waitpid(tempP, NULL, 0); //等待第一个子进程执行
if (tempW == tempP){
printf("Catch a child Process: pid=%d\n", tempW);
}else{
printf("waitpid error\n");
}//of if
}//of if
}//of if
return 0;
}//of main
基于waitpid函数不断获取子进程的状态。
#include
#include
#include
#include
int main(){
pid_t tempPid,tempP,tempW;
tempPid = fork();
if(tempPid == -1){
perror("fork error");
exit(1);
}else if(tempPid == 0){//child
sleep(5);
printf("First child process : pid = %d\n",getpid());
}else{
int i;
tempP=tempPid;
for(i=0; i < 3; i++){
if((tempPid=fork())==0){
break;
}//of if
}//of for
if(tempPid == -1){
perror("fork error");
exit(2);
}else if(tempPid == 0){
printf("Child process : pid = %d\n",getpid());
exit(0);
}else{
tempW = waitpid(tempP, NULL, 0);
if(tempW == tempP){
printf(" Catch a child Process: pid = %d\n",tempW);
}else{
printf("waitpid error\n");
}//of if
}//of if
}//of if
return 0;
}//of main
父进程可以通过wait()和waitpid()函数可以有效防止僵尸进程的产生,对于已存在的僵尸进程,则可通过杀死其父进程的方法解决,当僵尸进程的父进程被终止后,僵尸进程将作为孤儿进程被init进程接收,init进程会不断调用wait()函数获取子进程状态,对已处于僵尸态的进程进行处理。所以说,孤儿进程永远不会成为僵尸进程。
创建一个子进程,使父子进程分别打印不同的内容;创建一个子进程,使子进程通过exec更改代码段,执行cat命令。整合到如下:
#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=%d\n", getpid());
} else {
printf("child process:pid=%d\n", getpid());
//char *arg[]={"/home/bonjour/桌面/file", NULL};
//execvp("cat", arg);
execl("/bin/cat","cat","/home/bonjour/桌面/file",NULL);
perror("error exec\n");
printf("child process:pid=%d\n", getpid());
} //of if
return 0;
} //of main
学会了使用exec(),exit(), wait(), waitpidf() 等函数,对进程管理和进程同步有了更深的理解。