Linux操作系统学习(进程替换)
创始人
2024-05-28 19:00:14
0

文章目录

  • 进程替换
    • 进程替换是什么?
    • 替换的方法
    • 进程替换
  • 简易shell模拟

进程替换

进程替换是什么?

如下图所示:

进程替换就是,把进程B的代码和数据,替换正在执行的进程A的代码和数据在内存中的位置(若代码数据过多可能会改变页表),但进程A的整体部分不发生任何改变(task_struct、A进程地址空间等等)

其实就是用A进程的壳子执行B进程程序,不改变A进程的任何东西,只改变页表物理地址部分和内存中的数据和代码,不创建任何新的进程,并且子进程也不会退出。

替换的方法

一般用到以下六种函数

#include
int exec l(const char *path, const char *arg, …);
int exec lp(const char *file, const char *arg, …);
int exec le(const char *path, const char *arg, …,char *const envp[]);
int exec v(const char *path, char *const argv[]);
int exec vp(const char *file, char *const argv[]);
int exec ve(const char *path, char *const argv[], char *const envp[]);

命名后缀:

  • l(list) : 表示参数采用列表

  • v(vector) : 参数用数组

  • p(path) : 有p自动搜索环境变量PATH

  • e(env) : 表示自己维护环境变量

    程序运行时的环境变量信息(函数不会给你自动继承父进程的环境变量,需要手动设置)

返回值:

若替换失败则返回-1,但其实可以不用检查返回值因为:

  • 调用成功一定执行替换的程序

  • 调用失败一定执行原本的程序

  • int execl(const char *path, const char *arg, …);

void test1()    
{    
pid_t id = fork();    
if(id == 0)    
{    
printf("你好\n");    /*********************************************开始替换******************************************/execl("/usr/bin/ls","ls","-a","-l","-i",NULL);   //你要执行谁,想怎么执行(在命令行怎么执行就怎么执行),可变参数列表以NULL结尾//或者想要执行自己的程序 execl("./当前路径或者 /.../...绝对路径","可执行程序名",NULL);/*********************************************替换完成/失败******************************************/printf("hello\n");    }    sleep(1);    
printf("child exchange succeed\n");     
}    

  • int execlp(const char *file, const char *arg, …);
void test2()
{pid_t id = fork();if(id == 0){char* argv[] = {"ls","-a","-i","-l",NULL};//就是把可变参数列表以数组的形式传给execvprintf("exchange test2--->:\n");
/*********************************************开始替换******************************************/execv("/usr/bin/ls",argv);
/*********************************************替换完成/失败******************************************/printf("exchange fail\n");}sleep(1);printf("exchange succeed\n");
}

  • int execle(const char *path, const char *arg, …,char *const envp[]);
void test3()
{pid_t id = fork();if(id == 0){printf("exchange test3---->\n");
/*********************************************开始替换******************************************/execlp("ls","ls","-l","-a","-i",NULL);// 第一个你要执行的是谁但不用带路径,path会根据这个程序名去自动搜索它在什么位置,第二个是要怎么执行
/*********************************************替换完成/失败******************************************/printf("exchange fail\n");}sleep(1);printf("exchange succeed\n");}

  • int execvp(const char *file, char *const argv[]);
void test4()
{pid_t id = fork();if(id == 0){printf("exchange test4---->\n");char* argv[] = {"ls","-a","-l","-i",NULL};
/*********************************************开始替换******************************************/execvp("ls",argv); //第一个参数告诉path要执行的程序他会自动去找路径,第二个参数从可变参数列表变为自定义数组
/*********************************************替换完成/失败******************************************/printf("exchange fail\n");}sleep(1);printf("exchange succeed\n");
}

  • int execle(const char *path, const char *arg, …,char *const envp[]);
void test5()
{pid_t id = fork();if(id == 0){printf("exchange test5---->\n");
/*********************************************开始替换******************************************/char* env[] = {"my_env=hello",NULL};execle("./print","print",NULL,env);//最后一个参数env指定了新程序的环境列表。参数env对应于新程序的environ数组//传递自己的环境变量给print
/*********************************************替换完成/失败******************************************/printf("exchange fail\n");}sleep(1);printf("exchange succeed\n");}int main()
{extern char** environ;for(int i = 0;environ[i];i++){if(environ[i] == "PATH")continue;//path显示的太多,这里屏蔽掉printf("%s\n",environ[i]);}return 0;
}

  • int execve(const char *path, char *const argv[], char *const envp[]);
void test6()
{pid_t id = fork();if(id == 0){printf("exchange test5---->\n");
/*********************************************开始替换******************************************/char* argv[] = {"print",NULL};char* env[] = {"my_env=hello",NULL};execve("./print",argv,env);
/*********************************************替换完成/失败******************************************/printf("exchange fail\n");}sleep(1);printf("exchange succeed\n");}int main()
{extern char** environ;for(int i = 0;environ[i];i++){if(environ[i] == "PATH")continue;printf("%s\n",environ[i]);}return 0;
}

可以看出所有的函数都是在execve基础上封装的


进程替换

  • 子进程需要替父进程执行一些任务就需要进程替换

  • 进程替换只替换子进程在内存中的代码和数据,以及页表物理地址部分

  • 进程替换不会创建新进程,不会退出子进程

  • 虽然父子代码是共享的,但是进程替换会更改内存的代码和数据,所以要发生写实拷贝

  • fork创建子进程后,在代码中exec…只会替换子进程,因为进程具有独立性

程序替换的本质是把程序的代码数据加载到指定进程的上下文中


简易shell模拟

#include 
#include 
#include 
#include 
#include void myshell()
{char command[128];char* argv[64];while(1){command[0] = 0;printf("[awd@VM-16-4-centos myshell]----->");	//打印前缀	fflush(stdout);									//刷新缓冲区fgets(command,128,stdin);						//输入命令command[strlen(command) - 1] = 0;				//先当作整个字符串存入command,-1是除去\n//fflush(stdout);									//printf("%s\n",command);验证const  char* set = " ";							//设置分隔符argv[0] = strtok(command,set);					//把字符串拆解成指令int i = 1;								while( argv[i] = strtok(NULL,set) )				//类似strcpy,赋值到NULL退出i++;/*for(int j = 0;j < i;j++)printf("%s\n",argv[j]);验证*/if(strcmp(argv[0],"cd") == 0)					//在子进程cd影响的只是子进程,所以要再父进程处理{if(argv[1])chdir(argv[1]);continue;}if(fork() == 0)								 //创建子进程{execvp(argv[0],argv);						 //替父进程执行这些指令exit(1);								     	 //若执行到这说明替换失败,设置退出码为1}waitpid(-1,NULL,0);								//等待任意一个子进程结束int status = 0;if(strcmp(argv[0],"echo") == 0 && strcmp(argv[1],"$?") == 0)	//打印退出码和终止信号printf("exit code:%d ,exit signal:%d \n",WEXITSTATUS(status),WTERMSIG(status));}}int main()
{myshell();return 0;
}

通过这个简易shell来把之前学到的总结一下

  • 一般让子进程替父进程执行一些第三方命令,那么就需要用到 进程替换和fork
  • 子进程每次执行结束需要进程等待,为了结束他的僵尸进程并获取它的退出信息(退出码、终止信号
  • 每次进程退出后又会重新创建子进程,所以echo $? 查看的是最近一次执行的退出码
  • 证明了每一次命令行执行的指令都是一次进程,是基于bash为父进程创建的子进程

上面这个简陋shell综合了 :fork、进程替换函数、进程等待函数、进程退出函数、退出码/终止信号,加深了这些接口的理解

相关内容

热门资讯

读什么什么有感的英文 读什么什么有感的英文英语读后感标题 “读XXX有感”用英语说是 “Reading after XX...
秦岚个人资料身高体重 秦岚个人资料身高体重身高:165公分 体重:46公斤秦岚 生日:七月十七日 星座:巨蟹座 出生地:沈...
双鱼和天秤会纠缠一辈子,既相配... 双鱼和天秤会纠缠一辈子,既相配又相克,为什么?双鱼座的人和天秤座的人都是比较细心的,而且特别敏感,有...
独自一人在外怎样和别人相处? 独自一人在外怎样和别人相处?我觉得独自一个人在外面一定要好好的照顾自己,应该找一份工作,找一个住的地...
朱自清散文集有哪些写的好,值得... 朱自清散文集有哪些写的好,值得背诵的?《背影》、《 春》、《 荷塘月色》、《 匆匆》都是不错的佳...
大家最讨厌的电视剧的哪一个主角... 大家最讨厌的电视剧的哪一个主角?我觉得最讨厌的电视剧主角是容嬷嬷。都挺好,里面的苏大强就是越看越别扭...
69DT伤害怎么才能上1300... 69DT伤害怎么才能上1300 !我加点是4L1M!现在60了!伤害才800!我没大号,想买梦幻币买...
孩子上课不认真听讲 孩子上课不认真听讲我的孩子七周半,已经上二年级了,但是上课不认真听讲总是搞小动作,说了很多次也不听,...
《红脸儿》的主要内容 《红脸儿》的主要内容  红脸儿主要内容:   小说以散淡而富有诗意的语言回顾了“我”与3个小伙伴之间...
异地恋的成功例子 异地恋的成功例子 情侣异地恋8年终成正果 两人存下186张火车票见证爱情一对河南的情侣在大学恋爱时便...
小狗吃了死耗子怎么办 小狗吃了死耗子怎么办你好,没事的,放心吧,你的小狗是宠物狗还是土狗,若是宠物狗的话可能会给它造成身体...
请问有没有死亡万花筒广播剧资源... 请问有没有死亡万花筒广播剧资源?死亡万花筒,我有呀!死亡万花筒广播剧,地·址:9525.video(...
徐缺有哪些女人 徐缺有哪些女人徐缺是小说《最强反套路系统》中的角色,他有许多女性关系,其中包括:1. 林小红:徐缺的...
假如我是四大名著中的人物作文9... 假如我是四大名著中的人物作文900假如你是的林黛玉的话那你就会好好读书,不至于连900个字都写不出了...
西游记81难? 西游记81难?西游记的81难是师徒四人取经回来在河中落水经书被淹了的事
魔兽世界风暴王子问题! 魔兽世界风暴王子问题!现在3.05这版本 王子第4阶段的屏障 是不是可以被MS驱散? 屏障驱散后是...
如何评价张杰的少年中国说 如何评价张杰的少年中国说我觉得非常棒,张杰的家庭条件不好。从小就非常努力。刻苦学习音乐,经过拼搏奋斗...
智取生辰纲中杨志是怎样的人?他... 智取生辰纲中杨志是怎样的人?他失败的原因是什么?简短些志有智慧,但是他忽略了一个重要的因素:团队的合...
有一本书,名字忘记了.好象是美... 有一本书,名字忘记了.好象是美国人写的.梭罗《瓦尔登湖》 如果你用的是新教材,应该是这篇吧是 海明威...
四岁孩子看什么书 四岁孩子看什么书可以看一些带有简单数字的书、色彩鲜艳的图画、动物图画等,培养他的数字感和色彩感,尽量...