给我一个网站图片,长沙装修公司哪家好,wordpress个人简历,网络营销推广形式文章目录 进程程序替换替换原理进程替换的理解 环境变量与进程替换命令行解释器实现逻辑 进程程序替换
前面已经学习了子进程的创建#xff0c;但是子进程的创建不管怎么说#xff0c;都是父进程代码的一部分#xff0c;那么实际上如果想要子进程执行新的程序呢#xff1f… 文章目录 进程程序替换替换原理进程替换的理解 环境变量与进程替换命令行解释器实现逻辑 进程程序替换
前面已经学习了子进程的创建但是子进程的创建不管怎么说都是父进程代码的一部分那么实际上如果想要子进程执行新的程序呢
也就是说执行全新的代码和访问全新的数据不再和父进程有瓜葛呢这个时候就引入了关于进程替换的概念
替换原理 用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变
进程替换的理解
首先演示基本用法
单进程下的用法
#include stdio.h
#include unistd.h
#include stdlib.hint main()
{printf(execl begin:\n);execl(/usr/bin/ls, ls, -a, -l, -n, NULL);printf(execl end:\n);return 0;
}调用结果
[testVM-16-11-centos 11-8]$ ./myprocess
execl begin:
total 28
drwxrwxr-x 2 1003 1003 4096 Nov 9 10:50 .
drwxrwxrwt 16 1003 1003 4096 Nov 8 20:40 ..
-rw-rw-r-- 1 1003 1003 74 Nov 8 20:41 Makefile
-rwxrwxr-x 1 1003 1003 8416 Nov 9 10:50 myprocess
-rw-rw-r-- 1 1003 1003 175 Nov 9 10:47 myprocess.c从中看出它的基本原理就是在进程中进行进程的替换
为什么最后输出的printf不被调用呢
这是因为执行到进程替换函数的时候如果成功整个进程的代码和数据都会被替换为所需替换的目标代码和数据这样在后续执行的时候都会使用这份新的代码和数据因此不会调用后续出现的代码
多进程版本的程序替换
将上述的代码更改为含有子进程的代码具体如下
#include stdio.h
#include unistd.h
#include stdlib.h
#include sys/types.h
#include sys/wait.hint main()
{pid_t id fork();if(id 0){// childprintf(pid:%d,begin to exec!\n,getpid());sleep(3);execl(/usr/bin/ls,ls,-a,-l,NULL);printf(pid:%d,end to exec!\n,getpid());}else {// fatherprintf(wait child\n);pid_t rid waitpid(-1,NULL,0);if(rid 0){printf(wait success\n);}}return 0;
}实验结果如下
[testVM-16-11-centos 11-8]$ ./myprocess
wait child
pid:18212,begin to exec!
total 28
drwxrwxr-x 2 test test 4096 Nov 9 11:05 .
drwxrwxrwt 16 test test 4096 Nov 8 20:40 ..
-rw-rw-r-- 1 test test 74 Nov 8 20:41 Makefile
-rwxrwxr-x 1 test test 8672 Nov 9 11:05 myprocess
-rw-rw-r-- 1 test test 695 Nov 9 11:05 myprocess.c
wait success从中看出多进程替换中增加了父进程对子进程的等待和回收的部分功能
那在多进程下应该如何理解进程替换呢用下面图示的过程来演示 从这里的进程替换中可以发掘出一些东西替换的是进程而不是代码所以这里可以替换的内容有很多甚至可以是Java写的程序运行起来的进程等等看下面的实验
下面实现一个cpp程序
#include iostreamint main()
{std::coutthis is a cpp programstd::endl;return 0;
}对前面的程序进行修改
#include stdio.h
#include unistd.h
#include stdlib.h
#include sys/types.h
#include sys/wait.hint main()
{pid_t id fork();if(id 0){// childprintf(pid:%d,begin to exec!\n,getpid());sleep(3);execl(./cpptest,./cpptest,NULL);//execl(/usr/bin/ls,ls,-a,-l,NULL);printf(pid:%d,end to exec!\n,getpid());}else {// fatherprintf(wait child\n);pid_t rid waitpid(-1,NULL,0);if(rid 0){printf(wait success\n);}}return 0;
}对Makefile进行修改
.PHONY:all
all:myprocess cpptestcpptest:cpptest.cc g -o $ $^myprocess:myprocess.cgcc -o $ $^
.PHONY:clean
clean:rm -rf myprocess cpptest这里利用的是Makefile自带的自我推演能力使用Makefile进行自我推演可以推演出现在需要myprocess和cpptest而这两个程序又会分别进行执行运行
此时进行运行此时会做出如下的实验结果
[testVM-16-11-centos 11-8]$ ./myprocess
wait child
pid:23071,begin to exec!
this is a cpp program
wait success从中不难看出确实实现了进程的替换而且替换的还是其余进程
这也就解释了在不同的公司中是可以存在分块进行构建模块功能的最后都可以通过进程的形式链接起来
从某种意义来说进程的替换已经可以被看成是一种系统调用了站在系统的视角看内存中的所谓进程实际上是一样的系统高于一切它可以对进程进行调度和分配
环境变量与进程替换
当进行进程替换的过程中对于环境变量的角度来讲是以什么样的情况进行的传递呢
结论是子进程对应的环境变量是可以直接从父进程来的
对这个结论进行验证
有关进程替换的一些函数
execl函数需要找到命令所在的文件目录使用方法如下
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/wait.hint main()
{pid_t id fork();if(id 0){// child// 进行进程替换execl(/usr/bin/ls, ls, -a, -l, -d, NULL);}else {// parent// 对子进程回收pid_t rid waitpid(-1, NULL, 0);if(rid 0){printf(wait success\n);}}return 0;
}execlp函数会到系统默认的路径下寻找命令
execlp(ls, ls, -a, -l, -d, NULL);execle函数用一个程序调用另外一个程序但环境变量是自己的环境变量不是系统的通过获取环境变量查看
如何在进程中添加一个环境变量用到的是putenv函数
void *putenv(char *name)
由此可以写出下面的程序
#include iostreamint main(int argc, char* argv[], char* env[])
{// 输出命令行参数for(int i 0; argv[i]; i){std::cout i - argv[i] std::endl;}std::cout ############## std::endl;// 输出环境变量for(int i 0; env[i]; i){std::cout i - env[i] std::endl;}return 0;
}上面是用于进程替换的函数在这个基础上对原程序进行修改
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/wait.hint main()
{// 在程序中新增环境变量char* myenv MYVAL1 11111111;putenv(myenv);pid_t id fork();if(id 0){// child// 进行进程替换execl(./myprocess, myprocess, NULL);}else {// parent// 对子进程回收pid_t rid waitpid(-1, NULL, 0);if(rid 0){printf(wait success\n);}}
}运行程序如下 从中看出在子进程中是出现了新增的这个环境变量的由此可以基本验证在父进程中添加的环境变量会继承到子进程中
那么父进程的父进程是谁呢答案是bash那么是不是在bash中添加的环境变量也会继承到子进程中
再对上面的程序进行修改
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/wait.hint main(int argc, char* argv[], char* env[])
{// 输出环境变量for(int i 0; env[i]; i){printf(%d - %s\n, i, env[i]);}// 在程序中新增环境变量char* myenv {MYVAL1 11111111,MYVAL2 22222222,NULL};putenv(myenv);pid_t id fork();if(id 0){// child// 进行进程替换execl(./mytest, mytest, NULL);}else {// parent// 对子进程回收pid_t rid waitpid(-1, NULL, 0);if(rid 0){printf(wait success\n);}}
}由此可以得出这样的一条线索化的示意图 再次回到这张图 下面看execle函数
环境变量的传递方式
前面的例子证明子进程的环境变量是由父进程传递的而execle函数就是一个显示传递环境变量的函数它的第三个参数是envp[]实际上就是环境变量
那如何进行使用看下面的程序
#include stdio.h
#include unistd.h
#include sys/types.h
#include sys/wait.hint main(int argc, char* argv[], char* env[])
{// 在程序中新增环境变量char* const myenv[] {MYVAL1 11111111,MYVAL2 22222222,NULL};pid_t id fork();if(id 0){// child// 进行进程替换execle(./mytest, mytest, NULL, myenv);}else {// parent// 对子进程回收pid_t rid waitpid(-1, NULL, 0);if(rid 0){printf(wait success\n);}}return 0;
}运行结果如下 从中看出通过这个函数可以把环境变量进行显示传递给子进程并且是一种覆盖式传递
到此有关进程替换的基本逻辑已经结束那进程替换可以做什么实际的东西呢
命令行解释器
在前面的认知中命令行解释器也就是bash可以把用户在命令行中敲的命令转换成命令再输出而实际上这是一个逻辑很简单的过程
bash程序相当于是一个一直在后台运行的程序而当用户敲了一些命令行后bash创建子进程就将这些命令行转换为一个字符串数组采用进程替换的方式就可以把要找的命令和选项替换到前台那依据这个原理其实我们自己也能实现一个命令行解释器
实现逻辑
#include stdio.h
#include stdlib.h
#include string.h
#include unistd.h
#include sys/types.h
#include sys/wait.h#define NUM 1024
#define SIZE 64
#define SEP char cwd[1024];
char enval[1024];
int lastcode 0;const char *getUsername()
{const char *name getenv(USER);if(name) return name;else return none;
}const char *getHostname()
{const char *hostname getenv(HOSTNAME);if(hostname) return hostname;else return none;
}const char *getCwd()
{const char *cwd getenv(PWD);if(cwd) return cwd;else return none;
}int getUserCommand(char *command, int num)
{printf([%s%s %s]# , getUsername(), getHostname(), getCwd());char *r fgets(command, num, stdin);if(r NULL) return -1;command[strlen(command) - 1] \0;return strlen(command);
}void commandSplit(char *in, char *out[])
{int argc 0;out[argc] strtok(in, SEP);while(out[argc] strtok(NULL, SEP));
}int execute(char *argv[])
{pid_t id fork();if(id 0) {return -1;}else if(id 0){execvp(argv[0], argv);exit(1);}else{int status 0;pid_t rid waitpid(id, status, 0);if(rid 0){lastcode WEXITSTATUS(status);}}return 0;
}void cd(const char *path)
{chdir(path);char tmp[1024];getcwd(tmp, sizeof(tmp));sprintf(cwd, PWD%s, tmp);putenv(cwd);
}int doBuildin(char *argv[])
{if(strcmp(argv[0], cd) 0){char *path NULL;if(argv[1] NULL) path .;else path argv[1];cd(path);return 1;}else if(strcmp(argv[0], export) 0){if(argv[1] NULL) return 1;strcpy(enval, argv[1]);putenv(enval); // ???return 1;}else if(strcmp(argv[0], echo) 0){char *val argv[1] 1;if(strcmp(val, ?) 0){printf(%d\n, lastcode);lastcode 0;}else{printf(%s\n, getenv(val));}return 1;}else if(0){}return 0;
}int main()
{while(1){char usercommand[NUM];char *argv[SIZE];// 1. 打印提示符获取用户命令字符串获取成功int n getUserCommand(usercommand, sizeof(usercommand));if(n 0) continue;// 2. 分割字符串// ls -a -l - ls -a -lcommandSplit(usercommand, argv);// 3. check build-in commandn doBuildin(argv);if(n) continue;// 4. 执行对应的命令execute(argv);}
}
文章转载自: http://www.morning.rrhfy.cn.gov.cn.rrhfy.cn http://www.morning.nsjpz.cn.gov.cn.nsjpz.cn http://www.morning.jkpnm.cn.gov.cn.jkpnm.cn http://www.morning.xwlhc.cn.gov.cn.xwlhc.cn http://www.morning.rdxp.cn.gov.cn.rdxp.cn http://www.morning.bpknt.cn.gov.cn.bpknt.cn http://www.morning.zpzys.cn.gov.cn.zpzys.cn http://www.morning.gkfwp.cn.gov.cn.gkfwp.cn http://www.morning.yuminfo.com.gov.cn.yuminfo.com http://www.morning.sgwr.cn.gov.cn.sgwr.cn http://www.morning.bhdtx.cn.gov.cn.bhdtx.cn http://www.morning.tnktt.cn.gov.cn.tnktt.cn http://www.morning.wdhhz.cn.gov.cn.wdhhz.cn http://www.morning.cthkh.cn.gov.cn.cthkh.cn http://www.morning.zqdzg.cn.gov.cn.zqdzg.cn http://www.morning.zlxkp.cn.gov.cn.zlxkp.cn http://www.morning.nsncq.cn.gov.cn.nsncq.cn http://www.morning.tjqcfw.cn.gov.cn.tjqcfw.cn http://www.morning.lbbgf.cn.gov.cn.lbbgf.cn http://www.morning.lqchz.cn.gov.cn.lqchz.cn http://www.morning.jkzjs.cn.gov.cn.jkzjs.cn http://www.morning.ztqj.cn.gov.cn.ztqj.cn http://www.morning.pynzj.cn.gov.cn.pynzj.cn http://www.morning.xqbbc.cn.gov.cn.xqbbc.cn http://www.morning.mzgq.cn.gov.cn.mzgq.cn http://www.morning.wnnfh.cn.gov.cn.wnnfh.cn http://www.morning.datadragon-auh.cn.gov.cn.datadragon-auh.cn http://www.morning.fppzc.cn.gov.cn.fppzc.cn http://www.morning.qpmwb.cn.gov.cn.qpmwb.cn http://www.morning.mtbsd.cn.gov.cn.mtbsd.cn http://www.morning.ymjrg.cn.gov.cn.ymjrg.cn http://www.morning.ptmgq.cn.gov.cn.ptmgq.cn http://www.morning.nzfqw.cn.gov.cn.nzfqw.cn http://www.morning.nsrtvu.com.gov.cn.nsrtvu.com http://www.morning.mrkbz.cn.gov.cn.mrkbz.cn http://www.morning.brwwr.cn.gov.cn.brwwr.cn http://www.morning.cwskn.cn.gov.cn.cwskn.cn http://www.morning.cjwkf.cn.gov.cn.cjwkf.cn http://www.morning.cfnht.cn.gov.cn.cfnht.cn http://www.morning.bmmyx.cn.gov.cn.bmmyx.cn http://www.morning.nrydm.cn.gov.cn.nrydm.cn http://www.morning.lhytw.cn.gov.cn.lhytw.cn http://www.morning.ltdxq.cn.gov.cn.ltdxq.cn http://www.morning.lqljj.cn.gov.cn.lqljj.cn http://www.morning.bzbq.cn.gov.cn.bzbq.cn http://www.morning.qnhpq.cn.gov.cn.qnhpq.cn http://www.morning.cfccp.cn.gov.cn.cfccp.cn http://www.morning.xtgzp.cn.gov.cn.xtgzp.cn http://www.morning.thwcg.cn.gov.cn.thwcg.cn http://www.morning.jfymz.cn.gov.cn.jfymz.cn http://www.morning.khtjn.cn.gov.cn.khtjn.cn http://www.morning.joinyun.com.gov.cn.joinyun.com http://www.morning.youngbase.cn.gov.cn.youngbase.cn http://www.morning.bkfdf.cn.gov.cn.bkfdf.cn http://www.morning.tgmfg.cn.gov.cn.tgmfg.cn http://www.morning.lsmnn.cn.gov.cn.lsmnn.cn http://www.morning.psxcr.cn.gov.cn.psxcr.cn http://www.morning.blzrj.cn.gov.cn.blzrj.cn http://www.morning.fpkpz.cn.gov.cn.fpkpz.cn http://www.morning.zbjfq.cn.gov.cn.zbjfq.cn http://www.morning.wwthz.cn.gov.cn.wwthz.cn http://www.morning.dmthy.cn.gov.cn.dmthy.cn http://www.morning.zcrjq.cn.gov.cn.zcrjq.cn http://www.morning.thzgd.cn.gov.cn.thzgd.cn http://www.morning.jikuxy.com.gov.cn.jikuxy.com http://www.morning.dncgb.cn.gov.cn.dncgb.cn http://www.morning.gwqq.cn.gov.cn.gwqq.cn http://www.morning.ndlww.cn.gov.cn.ndlww.cn http://www.morning.attorneysportorange.com.gov.cn.attorneysportorange.com http://www.morning.kzpy.cn.gov.cn.kzpy.cn http://www.morning.lwdzt.cn.gov.cn.lwdzt.cn http://www.morning.twpq.cn.gov.cn.twpq.cn http://www.morning.hytr.cn.gov.cn.hytr.cn http://www.morning.rhzzf.cn.gov.cn.rhzzf.cn http://www.morning.lveyue.com.gov.cn.lveyue.com http://www.morning.pbmg.cn.gov.cn.pbmg.cn http://www.morning.lynkz.cn.gov.cn.lynkz.cn http://www.morning.bkslb.cn.gov.cn.bkslb.cn http://www.morning.roymf.cn.gov.cn.roymf.cn http://www.morning.ykrck.cn.gov.cn.ykrck.cn