海口顶尖网站建设,网页访客升级,网页设计心得体会结尾,个人博客网页制作模板田田田田田田田田田田打印环境变量#xff0c;把当前子进程所有环境变量打印出来
环境变量也是一张表#xff08;指针数组以null结尾#xff0c;最后条件不满足就退出了 #xff09; 用子进程调用 结论1 当我们进行程序替换的时候 #xff0c;子进程对应的环境变量#xff08;子进程的环境变…打印环境变量把当前子进程所有环境变量打印出来
环境变量也是一张表指针数组以null结尾最后条件不满足就退出了 用子进程调用 结论1 当我们进行程序替换的时候 子进程对应的环境变量子进程的环境变量是直接从父进程来的 那么父进程的环境变量是从哪里来的呢 bash父亲myprocess子mytest孙子 给bash导入一个变量 执行mytest后果然继承了bash的变量 putenv 把变量到入myprocess注意pitenv是char*类型的 子进程mytest也可以看到最终子进程的环境变量会越来越多 结论2. 环境变量被子进程继承下去是一种默认行为为什么不受程序替换的影响 原理 程序替换只替换新程序的代码和数据环境变量不会被替换 命令行参数在栈上
通过地址空间可以让子进程继承父进程的环境变量数据 子进程也可以看到 子进赋值他的pcb和进程地址空间 environ 也可以打印环境变量 execle a直接传环境变量
第一个绝对路径第二个参数以null结尾代表就三个最后一个传环境变量environ他是char**的而execle点个参数是指针数组数组传参发生降为就是char**的 b:我们想传递自己的环境变了怎么办
我们不传给他系统默认的环境变量而是自己写一个传给他自定义了一个myenv表 这就拿到了我们自己传的环境变量表 结论 选了带e的 我们可以直接构造环境变量表给子进程传递并且带e的不是在原有的环境变量基础上新增你自定义的变量表而是覆盖上去只有你的环境变量表全新的环境变量表 c当我们想在原有的基础上新增呢
当我们在父进程创建变量后直接传自己的环境变量就会把新创建的变量传递给子进程新增 结论 程序替换可以将命令行参数和环境变量通过自己的参数传递给被替换程序的main函数中 execvpe和execle 左边都是号手册只有execve是2号手册 上面个最终都会转化成execve他是真正的系统调用 都会转成execve的参数文件名命令行参数环境变量为什么呢
主要是为了满足各种调用使用场景选择合适的 自己实现shell
env查看环境变量中的USERhostnamepwd我们用getenv来获取头文件stdlib.h 如果存在return没有返回none 成功创建自己的命令行提示符下一步把光标卡在这里并不是自动调到下一行 定一个命令行usercommand[num],把输入的内凡在userconmand里面这样就可以停住了 要把\n去掉
ls -a -l回显测试 但是只显示ls 因为scanf遇到 空格 就结束了所以我们不用scanf 直接用fgets/gets 获取成功了就是字符串的起始地址失败就是none stream(stdin)读到缓冲区char*,int size
c语言默认会打开三个输入输出流 stdin键盘 stdout显示器 stderr显示器他们的类型FILE* 可以用sizeof直接求数组大小么一般是sizeof(usercommand)是可以的 获取成功返回r失败返回1然后printf回显打印出来但是多了一个空行 去掉prif中\n虽然没有换行但是重新另起一个命令行了因为最终你输入ls-a-l 还有一个\n 怎么去掉最后一个\n呢他是最后一个字符 把\n的位置改成\0,但是会不会越界呢 strlen(userconmand)-10? 不会 因为敲完命令最少有一个\n 完成获得了命令行输出 封装上面代码 1 打印提示符获取用户命令字符串获取成功 2 分割字符串
分割成 ls-a,-l 首先定义一个指针数组以null结尾怎么切割呢每个子串后面加\0独立起来
我们用c的话用分割函数1变多 size定义成64把argv初始化为空 strtok 把字符串按照 指定的 分隔符打散成子串 截取成功返回起始地址失败返回null 每次按照分隔符提取一个子串然后后面的传null就会继续分割后序的子串 当前子串在usercommand【num】里面 然后后面的传null就会继续分割后序的子串
截取成功返回起始地址失败返回null最后一次截取正好为null让argv以null结尾
此时argv里面存的就是 ls,-a ,-l ,null 截取测试 截取成功 封装字符串切割函数 至此切割完成 3 执行分割命令 当前是一个进程用fork函数 让子进程去执行 exec command 调用程序替换接口 创建子进程不让子进程往后走用exit1 父进程做的是等待子进程 此时引入 waitpid(等待的id退出码退出方式) 然后用子进程调用程序替换函数接口我们选择做更少的工作不用导环境变量
我们选择execvp argv[0]就是ls我们想怎么执行程序在命令行怎么传就用 argv
但是我们的命令行只能跑一次 用while循环套起来就可以一直执行了 当我们一直敲回车r就会返回1 把获取到的字符串的长度返回可能为0空串可能大于0 获取返回的长度如果n0说明获取失败(-1)或者是空串 那么就continue跳出下面的语句 执行命令封装
ido创建子进程失败返回-1 cd..路径并没有不变为什么呢 是子进程执行的cd..当我们自己执行命令时候是bash环境中进行的 shell的内建命令 (就是bash自己执行的类似于自己内部的一个函数 所以有一批命令不能交给子进程执行只能由父进程来执行 所有执行命令前要知道他是否是 内建命令所以我们要检查 只有带color我们执行的命令才会带颜色按照颜色方式执行
4.检查是否是内建命令 ndoBuildfinargv 1表示是内建命令 0表示不是内建命令 首先确认是否 是内建命令用strcmp跟内建命令比较 比如跟cd比较 是cd并且执行cd 并返回1 是内建命令就continue不继续往下走了 循环看下一个指令 如果不是就返回0 继续往下走 如果argv[1]参数没有设置cd后加没有命令没东西走到cd parh一定不为空 来到cd函数我们要切换哪一个路径呢 怎么样让自己对应的当前进程去执行一个接口能够把我们当前的路径变了 chdir 谁调用chdir就把谁当前的工作路径更改所以我们改argv[1] 更改后 chdir谁就改成了谁的路径 但是我们命令行的路径没有变为什么呢
因为我们吗每次执行时候获取的环境变量都没有变 方法二
sprintf
把格式化的字符串format往str里面打印 当前环境变量叫做pwd 把对应的格式化的内容“PWD%s”导入到cwd里面去同时用putenv导入到当前环境变量谁掉putenv就导入到谁中此时路径确实变了此时env找不到pwd了因为路径已经变了 因为环境变量的存储空间不能在临时空间里面去存必须永久有效
函数调用时有putenv导入后只是把cwd【】的地址导进去了表里面但是地址没有 所以改成全局变量 此时env可以看到pwd了 getcwd 把当前进程所在的绝对路径放在缓冲区里面返回值是获取成功时获取的内容 获取当前绝对路径后再通过sprintf把格式化的字符串format往str里面打印放在cwd里面
此时cwd拿的就是chdir之后的 当前进程的 绝对工作路径经过getcwd这次不怕临时空间了因为我们把整个emp格式化到cwd里面了再putenv 重新导入 让子进程导入export第一次env可以看到 但是再次env就看不到6666666666666666了
因为argv[1]是由 *argv【size】指向的而该指针数组指向的是usercommand【num】里面子串
而usercommand【num】每次都再输入指令是都会覆盖写入下次usercommand【num】里面的缓冲区已经被改变了所以将环境变量不能用临时缓冲器缓冲比如刚才全局变量cwd
所以我们定义一个大的全局变量表导入进去 导环境变量的动作 用strcpy
此时我们就存到我们定义的enval里面然后导出就导出我们的envalenval不受其他用户影响 如果export后是空就退出ruturn 1 提取最近一个进程退出时的退出码echo $?/$PATH argv[1]应该指向$1就指向PATH后面的是?
既如果argv[1]是?就是查看退出码是PATH就是查看环境变量用getenv获取 效果代码 新增
内建命令判断附加