当前位置: 首页 > wzjs >正文

wordpress 背景透明长沙关键词优化费用

wordpress 背景透明,长沙关键词优化费用,域名备案查询接口,中国建设网平台文章目录 做一个简易的shell预备知识代码实现运行结果 做一个简易的shell 重谈Shell shell是操作系统的一层外壳程序,帮我们用户执行指令, 获取到指令后,交给操作系统,操作系统执行完后,把执行结果通过shell交给用户…

文章目录

    • 做一个简易的shell
      • 预备知识
      • 代码实现
      • 运行结果

做一个简易的shell

重谈Shell

shell是操作系统的一层外壳程序,帮我们用户执行指令,

获取到指令后,交给操作系统,操作系统执行完后,把执行结果通过shell交给用户。

shell大部分执行命令时,要创建子进程(fork)。

shell/bash本身也是一个进程,执行指令的时候,本质就是自己创建子进程执行的。

考虑下面这个与shell典型的互动:

[root@localhost epoll]# ls
client.cpp readme.md server.cpp utility.h
[root@localhost epoll]# psPID TTY TIME CMD3451 pts/0 00:00:00 bash3514 pts/0 00:00:00 ps

用下图的时间轴来表示事件的发生次序。

其中时间从左向右。

shell由标识为sh的方块代表,它随着时间的流逝从左向右移动。

shell从用户读入字符串"ls"。

shell建立一个新的进程,然后在那个进程中运行ls程序并等待那个进程结束。

image-20250312144828753

然后shell读取新的一行输入,建立一个新的进程,在这个进程中运行程序 并等待这个进程结束。

所以要写一个shell,需要循环以下过程:

  1. 获取命令行

  2. 解析命令行

  3. 建立一个子进程(fork)

  4. 替换子进程(execvp)

  5. 父进程等待子进程退出(wait)

根据这些思路,和我们前面的学的技术,就可以自己来实现一个shell了。


在继续学习新知识前,我们来思考函数和进程之间的相似性

exec/exit就像call/return

一个C程序有很多函数组成。

一个函数可以调用另外一个函数,同时传递给它一些参数。

被调用的函数执行一定的操作,然后返回一个值。

每个函数都有他的局部变量,不同的函数通过call/return系统进行通信。

这种通过参数和返回值在拥有私有数据的函数间通信的模式是结构化程序设计的基础。

Linux鼓励将这种应用于程序之内的模式扩展到程序之间。

image-20250312144958240

一个C程序可以fork/exec另一个程序,并传给它一些参数。

这个被调用的程序执行一定的操作,然后通过exit(n)来返回值。

调用它的进程可以通过wait(&ret)来获取exit的返回值。


预备知识

命令函的本质就是字符串。先输出后输入。

主机名、用户名和路径都是可以通过系统调用获取的。

但是,我们也可以使用环境变量获得。使用getenv()。

image-20250320201242755

image-20250320201413053

读取一行

image-20250320203406396

Linux系统会打开三个输入输出流(所以我们可以从stdin里面读取输入)

image-20250320203929427

分割字符串strtok

image-20250320215012841

子进程执行普通命令exec*,因为有argv,所以带v、带p。

image-20250320221358808

编写cd指令时,需要用到chdir和getcwd。

chdir是改变当前的工作目录

image-20250320230829763

getcwd是获取当前的工作目录

image-20250320230858527

把一个字符串格式化到指定处

image-20250320231224528

导入环境变量的时候要注意的问题!

image-20250321164750259

代码实现

  #include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/wait.h>#include <assert.h>#include <string.h>#include <sys/types.h>#define LEFT "["#define RIGHT "]"#define LALEL "$"#define DELIM " \t"#define LINE_SIZE 1024#define ARGC_MAX 32#define EXIT_CODE 33int last_code=0;int quit=0;char commandline[LINE_SIZE];char* argv[ARGC_MAX];char pwd[LINE_SIZE];//在shell需要维护//自定义环境变量表//自定义本地变量表(一段缓冲区)char myenv[LINE_SIZE];//也可以malloc空间//或者弄成一个二维数组const char*getusername(){return getenv("USER");}const char*gethostname(){return getenv("HOSTNAME");}void getpwd(){getcwd(pwd,sizeof(pwd));}void interact(char*cline,int size){getpwd();printf(LEFT"%s@%s %s"RIGHT""LALEL" ",getusername(),gethostname(),pwd);//输入最好不要用scanf,因为它是以空格结尾//fgets可以读取一行,读取成功就为读取字符串的地址,失败返回NULLchar*s=fgets(cline,size,stdin);//sizeof是否需要-1呢//不需要,-1是防御性编程,防止\0不够放了。后面要用到系统级别的io就要考虑是否-1//fgets不可能为null,不输入,按了回车之后,也算是有字符。//输入了命令,一敲回车就会换行,但是我们不想要换行。assert(s!=NULL);//assert在debug的情况下起效果(void)s;//抵消编译器的报警//"abcd\n\0"cline[strlen(cline)-1]='\0';}int splitstring(char*_argv[],char*cline){int i=0;_argv[i++]=strtok(cline,DELIM);while(_argv[i++]=strtok(NULL,DELIM));return i-1;}void normalexcute(char*_argv[]){pid_t id=fork();if(id<0){perror("fork fail!");return;}else if(id==0){execvp(_argv[0],_argv);exit(EXIT_CODE);//替换失败我们就可以拿到子进程的退出信息。//cd echo等内建命令不能由子进程执行//子进程cd 与父进程无关!}else{int status=0;pid_t rid=waitpid(id,&status,0);if(rid==id){last_code=WEXITSTATUS(status);                }}}int buildcommand(char*_argv[],int _argc){if(_argc==2&&strcmp(_argv[0],"cd")==0){chdir(_argv[1]);getpwd();sprintf(getenv("PWD"),"%s",pwd);return 1;}//export也是内建命令//如果让子进程执行export,那么子进程的环境变量会添加,//但是与父进程无关,export导环境变量是给调用的进程导入。                                                                                                                             else if(_argc==2&&strcmp(_argv[0],"export")==0){strcpy(myenv,_argv[1]);putenv(myenv);//只是修改了一个环境变量表的指针,让该指针指向了环境变量。//但是环境变量是在argv里面的,所以,下一次argv的就会改变,//所以环境变量指针指向的内容也会改变//没有直接拷贝到系统的环境变量表中//而是把argv里面的信息导入了,argv指向的内容一直都会变化。//所以我们需要一个不变的区域。return 1;}else if(_argc==2&&strcmp(_argv[0],"echo")==0){if(strcmp(_argv[1],"$?")==0){printf("%d\n",last_code);last_code=0;}else if(*_argv[1]=='$'){char*val=getenv(_argv[1]+1);if(val) printf("%s\n",val);}else{printf("%s\n",_argv[1]);}return 1;}//给文件加颜色!if(strcmp(_argv[0],"ls")==0){_argv[_argc++]="--color";_argv[_argc]=NULL;}return 0;}int main(){while(!quit){//1.//2.交互问题,获取命令行interact(commandline,sizeof(commandline));//printf("echo :%s\n",commandline);//字符串分割 要有每个字串的地址 "ls -a -l" -> "ls" "-a" "-l"//保存在agrv(字符串数组里)//分割字串strtok 调用一次只能切割一个子串//3.字符串分割问题,解析命令行int argc=splitstring(argv,commandline);if(argc==0)continue;// for(int i=0;argv[i];i++)// {//     printf("[%d]:%s\n",i,argv[i]);// }//4.指令的判断//判断是否是内建命令,如果是就要让父进程执行相应的指令//内建命令本质就是shell内部的一个函数int n=buildcommand(argv,argc);//5.普通命令的执行if(!n)normalexcute(argv);}return 0;}

运行结果

image-20250321172332907

image-20250321172400214

image-20250321173002520

结论:

所以,当我们进行登陆的时候,系统就是要启动一个shell进程

我们shell本身的环境变量是从哪里来的?

image-20250321170235622

.bash_profile

image-20250321170525423

.bashrc

image-20250321170617366

/etc/bashrc
我们所用的环境变量都是从配置文件读的。

image-20250321170739023

当用户登陆的时候,shell会读取用户目录下的 .bash_profile 文件,里面保存了导入环境变量的方式!

shell的环境变量最终是从环境里来的。

http://www.dtcms.com/wzjs/169648.html

相关文章:

  • 电子商务网站建设与管理实训心得百度推广400电话
  • 做团购网站视频营销方案推广
  • 怎么查看网站建设时间北京seo招聘网
  • 北京做网站建设的公司哪家好百度seo优化哪家好
  • 陕西专业网站建设友链提交入口
  • 中山网站代运营湖南有实力seo优化哪家好
  • 企业做推广有几种方式百度seo规则
  • 电商网站设计seo排名点击手机
  • 毕业设计做网站论文seo服务建议
  • 做网站怎么云存储百度seo价格查询
  • 合肥平台网站建设百度竞价推广开户费用
  • 三合一网站建设多少钱浙江搜索引擎优化
  • 网站建设阶段河南关键词排名顾问
  • 微网站搭建今日头条极速版官网
  • 秦皇岛网站搜索优化站长之家
  • 东莞做公众号的网站济南百度
  • 公司做网站费用和人员配备常用seo站长工具
  • 色彩设计网站app网站
  • 三栏wordpress模板下载济南网站优化培训
  • 山东烟台城乡建设学校官方网站湛江今日头条新闻
  • 公司网站 优帮云wix网站制作
  • 广州网站建设泸州seo查询
  • 金阊seo网站优化软件steam交易链接在哪里看
  • 老k频道网站入口最新热点新闻事件
  • 设计公司调研报告大连seo
  • 网站建设中可能升级今日新闻联播
  • 网站建设怎么骗人成都seo排名
  • wordpress与Wix对比济南做seo的公司排名
  • 外贸网站怎么找客户杭州百度推广代理公司哪家好
  • 魔贝课凡seoseo网站