栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

系统级程序设计(3)

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

系统级程序设计(3)

文章目录
  • 学习内容
    • exec函数族
    • 进程退出
    • 特殊进程
    • wait函数和waitpid函数
  • 代码
    • exec
    • 运行结果
    • 【案例 1】
    • 【案例 2】
    • 【案例 3】
    • 【案例 4】
  • 总结


学习内容

链接:
进程管理
进程同步

exec函数族

exec:一个进程调用exec类函数,它本身就"死亡"了,系统把代码段替换成新的程序代码,废弃原有数据段和堆栈段,并为新程序分配新数据段与堆栈段
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[]);

参数说明:
(1)当参数是path,传入的为路径名;当参数是file,传入的可执行文件名;
(2)可以将exec函数族分为execl和execv两类:
execl类:函数将以列举的形式传入参数,由于参数列表的长度不定,所以要用哨兵NULL表示列举结束;
execv类:函数将以参数向量表传递参数,char * argv[]的形式传递文件执行时使用的参数,数组中最后一个参数为NULL;
(3)如果没有参数char * const envp[],则采用默认环境变量;如果有,则用传入的参数替换默认环境变量;

进程退出
#include 
void exit(int status);
特殊进程

孤儿进程:父进程负责回收子进程,如果父进程在子进程退出之前退出,子进程就会变成孤儿进程,此时init进程将代替父进程完成子进程的回收工作;

僵尸进程:调用exit函数后,该进程不会马上消失,而是留下一个称为僵尸进程的数据结构。它几乎放弃进程退出前占用的所有内存,既没有可执行代码也不能被调度,只是在进程列表中保留一个位置,记载进程的退出状态等信息供父进程回收。若父进程没有回收子进程的代码,子进程将会一直处于僵尸态。

wait函数和waitpid函数

wait函数功能:挂起进程,进程进入阻塞状态,直到子进程变为僵尸态,如果捕获到子进程的退出信息就会转为运行态,然后回收子进程资源并返回;若没有变为僵尸态的子进程,wait函数就会让进程一直阻塞。若当前进程有多个子进程,只要捕获到一个变为僵尸态的子进程,wait函数就会恢复执行态。
wait函数的缺点:当前进程有很多个子进程,wait函数无法保证所有子进程在父进程之前执行。
waitpid函数:可以应对 wait函数面临的缺点。可以等待指定的子进程,也可以在父进程不阻塞的情况下获取子进程的状态。


代码 exec
#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","-1","main.c",NULL};
execvp("ls",arg);
perror("error execn");
printf("child process:pid=%dn",getpid());
}// of if
return 0;
}// of main 
运行结果

结果如下:

【案例 1】

若子进程p 1 是其父进程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 = %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

结果如下:

【案例 2】

使用wait同步进程,并使用宏获取子进程的返回值。

#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

结果如下

【案例 3】

父进程等待进程组中指定子进程,该进程不退出,则父进程一直阻塞。

#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】

基于waitpid函数不断获取子进程的状态。

#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


总结

经过这次学习,我初步了解了exec函数族及其包含的六个函数,wait函数和waitpid函数的功能和区别,通过代码运行后对函数作用有了简单了解,以及进程退出函数的使用,特殊进程:孤儿进程,僵尸进程的概念。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/882225.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号