微网站ui多少钱,网站建设与维护 唐清安,凡科网 小程序,金融中介做网站需要#x1f44d;作者主页#xff1a;进击的1 #x1f929; 专栏链接#xff1a;【1的Linux】 文章目录 一#xff0c;什么是进程替换二#xff0c;替换函数三#xff0c;实现我们自己的shell 一#xff0c;什么是进程替换
我们创建出来进程是要其做事情的#xff0c;它可… 作者主页进击的1 专栏链接【1的Linux】 文章目录 一什么是进程替换二替换函数三实现我们自己的shell 一什么是进程替换
我们创建出来进程是要其做事情的它可以去调用函数或者是执行其他的程序子进程通过exec函数族执行其他的程序就叫做进程替换。也就是在调用进程内部执行一个可执行文件。当进程调用一种exec函数时该进程的代码和数据完全被新程序替换新程序从main函数开始执行由于未创建新进程所以替换前后进程的id等并不改变。 在加载新程序之前父子进程的关系是代码共享数据写时拷贝。 当子进程加载新程序的时候就是一种“写入”此时代码也就需要进行写时拷贝进行分离
二替换函数
下面是六种exec开头的函数统称exec函数。 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[]); 其中只有execve()是真正意义上的系统调用其它都是在此基础上经过包装的库函数。 这些函数如果调用成功则加载新的程序开始执行不再返回若调用失败则返回-1 。 下面是这些函数的演示:
#includestdio.h
#includeunistd.h
int main()
{//execl---带路径,参数包传参//execl(/usr/bin/ps,ps,-ef,NULL);// execlp(ls,-l,NULL);char* env[]{PATH/bin:/usr/bin,NULL};char* argv[]{ls,-l,NULL};// execv(/usr/bin/ls,argv);// execle(./mike,mike,NULL,env);// execvp(ls,argv);execve(/usr/bin/ls,argv,env);return 0;
}
execl运行结果要写路径参数格式未列表) execlp运行结果带p的可以使用环境变量PATH,无需写路径 execle运行结果 execv运行结果 execvp运行结果 execve运行结果 我们总结以下 带p可以使用环境变量PATH,无需写完整路径 带e自己组装环境变量。// 改变替换程序的环境变量正确来说让替换程序只保留 env 的环境变量 带l参数格式为列表 带v参数格式为数组 事实上,只有execve是真正的系统调用,其它五个函数最终都调用 execve,所以execve在man手册 第2节,其它函数在man手册第3节。
exec*实际上就是一个加载器的底层接口。
三实现我们自己的shell
代码如下
#includestdio.h
#includeunistd.h
#includesys/wait.h
#includesys/types.h
#includestdlib.h
#includestring.h
#define NUM 32
char cmd_line[NUM];
char* _argv[32];
char myval[32];//这个buffer用来保存我们添加的环境变量不然保存在cmd_line中会被覆盖。
int main()
{extern char** environ;//是一个外部的全局变量储存着系统的全局变量。while(1){//打印提示信息printf([hyp myshell]#);fflush(stdout);memset(cmd_line,\0,sizeof(cmd_line));//用户输入if(fgets(cmd_line,sizeof(cmd_line),stdin)NULL){continue;}cmd_line[strlen(cmd_line)-1]\0;//分割字符_argv[0]strtok(cmd_line, );int i0;if(strcmp(_argv[0],ls)0)//加颜色{_argv[i]--colorauto;}if(strcmp(_argv[0],ll)0){_argv[0]ls;_argv[i]--colorauto;_argv[i]-l;}while(_argv[i])//分割{i;_argv[i]strtok(NULL, );}if(strcmp(_argv[0],export)0 _argv[1]!NULL){strcpy(myval,_argv[1]);int retputenv(myval);if(ret0){printf(%s export success\n,myval);}continue;}if(strcmp(_argv[0],cd)0){if(_argv[1]!NULL){//内置命令让父进程自己执行的命令本质就是shell的一个函数调用。chdir(_argv[1]);//改变当前工作目录}continue;}int idfork();if(id0)//child{printf(child MYVAL:%s\n,getenv(MYVAL));printf(PATH:%s\n,getenv(PATH));execvp(_argv[0],_argv);exit(1);}//fatherint status0;int retwaitpid(id,status,0);if(ret0){printf(退出码%d\n,WEXITSTATUS(status));}}return 0;
}