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

基于drupal系统的网站开发-毕业论文站内营销推广方案

基于drupal系统的网站开发-毕业论文,站内营销推广方案,图库网站cms,两学一做 山西答题网站Linux自定义shell编写 一.最终版本展示1.动图展示2.代码展示 二.具体步骤1.打印提示符2.解析命令行3.分析是否是内建命令1.shell对于内建名令的处理2.cd命令3.cd函数的实现4.echo命令的实现5.export命令的实现6.内建命令函数的实现 4.创建子进程通过程序替换执行命令5.循环往复…

Linux自定义shell编写

  • 一.最终版本展示
    • 1.动图展示
    • 2.代码展示
  • 二.具体步骤
    • 1.打印提示符
    • 2.解析命令行
    • 3.分析是否是内建命令
      • 1.shell对于内建名令的处理
      • 2.cd命令
      • 3.cd函数的实现
      • 4.echo命令的实现
      • 5.export命令的实现
      • 6.内建命令函数的实现
    • 4.创建子进程通过程序替换执行命令
    • 5.循环往复即可
  • 三.shell运行原理

经过了创建进程,终止进程,进程等待和进程程序替换之后,
我们就可以借助这些知识实现一个简单的shell命令行解释器了

温馨提示:
建议大家自己写一遍,这些代码分块之后每一个函数都很简单,
不过实现过程中可能会有各种各样非常细枝末节的地方被我们所忽视
因此可能会发生一看就懂,一写就废的情况…

一.最终版本展示

输入命令行时想要删除字符时不能直接按backspace,而是要按ctrl+backspace才能成功删除

1.动图展示

在这里插入图片描述

2.代码展示

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
//#define DEBUG 1
#define SEP " "char cwd[1024]={'\0'};
int lastcode=0;//上一次进程退出时的退出码char env[1024][1024]={'\0'};
int my_index=0;const char* getUsername()
{const char* username=getenv("USER");if(username==NULL) return "none";return username;
}const char* getHostname()
{const char* hostname=getenv("HOSTNAME");if(hostname==NULL) return "none";return hostname;
}const char* getPwd()
{const char* pwd=getenv("PWD");if(pwd==NULL) return "none";return pwd;
}//分割字符串填入usercommand数组当中
//例如: "ls -a -l" 分割为"ls" "-a" "-l"
void CommandSplit(char* usercommand[],char* command)
{int i=0;usercommand[i++]=strtok(command,SEP);while(usercommand[i++]=strtok(NULL,SEP));
}//解析命令行
void GetCommand(char* command,char* usercommand[])
{command[strlen(command)-1]='\0';//清理掉最后的'\0'CommandSplit(usercommand,command);
#ifdef DEBUGint i=0;while(usercommand[i]!=NULL){printf("%d : %s\n",i,usercommand[i]);i++;}
#endif
}//创建子进程,完成任务
void Execute(char* usercommand[])
{pid_t id=fork();if(id==0){//子进程执行部分execvp(usercommand[0],usercommand);//如果子进程程序替换失败,已退出码为1的状态返回exit(1);}else{//父进程执行部分int status=0;//阻塞等待pid_t rid=waitpid(id,&status,0);if(rid>0){lastcode=WEXITSTATUS(status);}}
}void cd(char* usercommand[])
{chdir(usercommand[1]);char tmp[1024]={'\0'};getcwd(tmp,sizeof(tmp));sprintf(cwd,"PWD=%s",tmp);putenv(cwd);lastcode=0;
}   int echo(char* usercommand[])
{//1.echo后面什么都没有,相当于'\n'if(usercommand[1]==NULL){printf("\n");lastcode=0;return 1;}//2.echo $?  echo $PWD echo $char* cmd=usercommand[1];int len=strlen(cmd);if(cmd[0]=='$' && len>1){//echo $?if(cmd[1]=='?'){printf("%d\n",lastcode);lastcode=0;}//echo $PWDelse{char* tmp=cmd+1;const char* env=getenv(tmp);//找不到该环境变量,打印'\n',退出码依旧为0if(env==NULL){printf("\n");}else{printf("%s\n",env);}lastcode=0;}}else{printf("%s\n",cmd);}return 1;
}void export(char* usercommand[])
{//exportif(usercommand[1]==NULL){lastcode=0;return;}strcpy(env[my_index],usercommand[1]);putenv(env[my_index]);my_index++;
}int doBuildIn(char* usercommand[])
{//cdif(strcmp(usercommand[0],"cd")==0){if(usercommand[1]==NULL) return -1;cd(usercommand);return 1;}//echoelse if(strcmp(usercommand[0],"echo")==0){return echo(usercommand);}//exportelse if(strcmp(usercommand[0],"export")==0){export(usercommand);}return 0;
}int main()
{while(1){//1.打印提示符信息并获取用户的指令printf("[%s@%s %s]$ ",getUsername(),getHostname(),getPwd());char command[1024]={'\0'};fgets(command,sizeof(command),stdin);char* usercommand[1024]={NULL};//2.解析command字符串,放入usercommand指针数组当中GetCommand(command,usercommand);//3.检测并执行内建命令,如果是内建命令并成功执行,返回1,未成功执行返回-1,不是内建返回0int flag=doBuildIn(usercommand);//返回值!=0说明是内建命令,无需执行第4步if(flag!=0) continue;//4.创建子进程,交由子进程完成任务Execute(usercommand);}return 0;
}

二.具体步骤

1.打印提示符

在这里插入图片描述

const char* getUsername()
{const char* username=getenv("USER");if(username==NULL) return "none";return username;
}const char* getHostname()
{const char* hostname=getenv("HOSTNAME");if(hostname==NULL) return "none";return hostname;
}const char* getPwd()
{const char* pwd=getenv("PWD");if(pwd==NULL) return "none";return pwd;
}int main()
{while(1){//1.打印提示符信息并获取用户的指令printf("[%s@%s %s]$ ",getUsername(),getHostname(),getPwd());char command[1024]={'\0'};fgets(command,sizeof(command),stdin);}return 0;
}

注意:
1.因为scanf默认读取到空格或者’\n’时就会停止继续读取,
可是我们命令行中要求读取到空格也不能停止,(否则我们的指令就无法带选项了,因为选项之间是用空格来分割的)
因此我们需要fgets函数

char command[1024]={'\0'};
fgets(command,sizeof(command),stdin);

从命令行当中读取一行字符串
在这里插入图片描述
2.因为我们用户输入的时候在最后的时候一定会输入一个’\n’,因此我们需要把’\n’置为’\0’

command[strlen(command)-1]='\0';//去除我们最后输入的'\n'

把’\n’置为’\0’的操作我们放到了下一个函数当中来完成

2.解析命令行

因为有些命令带有选项:例如 “ls -a -l”
我们在进行程序替换的时候需要分别传入"ls" “-a” "-l"这几个字符串,所以需要把用户输入的字符串分割为若干个字符串存放到一个指针数组当中,可以使用strtok字符串切割函数
在这里插入图片描述

#define DEBUG 1
#define SEP " "//分割字符串填入usercommand数组当中
//例如: "ls -a -l" 分割为"ls" "-a" "-l"
void CommandSplit(char* usercommand[],char* command)
{int i=0;usercommand[i++]=strtok(command,SEP);while(usercommand[i++]=strtok(NULL,SEP));
}//解析命令行
void GetCommand(char* command,char* usercommand[])
{command[strlen(command)-1]='\0';//清理掉最后的'\0'CommandSplit(usercommand,command);
#ifdef DEBUGint i=0;while(usercommand[i]!=NULL){printf("%d : %s\n",i,usercommand[i]);i++;}
#endif
}

我们可以使用条件编译来方便我们自由选择是否需要打印
解析命令行后的usercommand数组中的内容

3.分析是否是内建命令

1.shell对于内建名令的处理

在这里插入图片描述
下面我们就一起来实现一下
cd,echo,export这几个内建命令

2.cd命令

在这里插入图片描述
可是如果shell进行进程程序替换了,那么shell执行完之后不就没了吗?
因此shell执行内建命令时直接封装函数调用系统调用接口即可

内建命令的个数是有限的,所以shell是可以对内建命令进行穷举的

因此我们就能更好地理解内建命令了:

内建命令:不需要创建子进程执行,shell自己执行,本质就是调用系统调用接口

3.cd函数的实现

对于cd而言,我们可以调用chdir这个系统调用接口来改变当前进程的工作目录
在这里插入图片描述
同时也可以设置一个全局的char类型的数组cwd来保存当前路径
每次cd之后用cwd来记录新路径,然后通过putenv来修改环境变量PWD
让我们第一步打印的提示符中的PWD路径可以动态调整

//cwd:存放当前路径,是一个全局变量
char cwd[1024]={'\0'};void cd(char* usercommand[])
{//1.chdir改变当前进程的工作目录chdir(usercommand[1]);//2.获取当前进程所在工作目录到tmp数组当中char tmp[1024]={'\0'};getcwd(tmp,sizeof(tmp));//3.把tmp数组中的内容格式化为"PWD=tmp数组中的内容"放到cwd数组当中sprintf(cwd,"PWD=%s",tmp);//4.导入环境变量putenv(cwd);//5.最后一次进程的退出码置为0(是为了echo $?获取最后一次进程的退出码的实现,跟cd无关)lastcode=0;
}  

注意:cwd数组必须是全局变量,如果cwd是局部变量,那么出了cd这个函数之后cwd数组就会销毁,其中的内容也将会消失
而我们putenv导入环境变量时其实是把cwd的地址放入了环境变量当中,
而不是拷贝一份这个cwd放入环境变量当中,因此cwd数组销毁时,对应导入的环境变量中的内容就不是原来的内容了

4.echo命令的实现

echo命令也是一个内建命令

echo 空串      打印换行
echo $ ?      打印上次进程退出时的退出码
echo $环境变量  打印环境变量
echo 字符串    打印字符串
注意:
echo $       打印$这个字符串
因此即使判断了$,还要继续判断$后面还有没有字符
//全局变量
int lastcode=0;//上一次进程退出时的退出码int echo(char* usercommand[])
{//1.echo后面什么都没有,相当于'\n'if(usercommand[1]==NULL){printf("\n");lastcode=0;return 1;}//2.echo $?  echo $PWD echo $char* cmd=usercommand[1];int len=strlen(cmd);if(cmd[0]=='$' && len>1){//echo $?if(cmd[1]=='?'){printf("%d\n",lastcode);lastcode=0;}//echo $PWDelse{char* tmp=cmd+1;const char* env=getenv(tmp);//找不到该环境变量,打印'\n',退出码依旧为0if(env==NULL){printf("\n");}else{printf("%s\n",env);}lastcode=0;}}else{printf("%s\n",cmd);}return 1;
}

5.export命令的实现

export导入环境变量
注意:
1.刚才介绍cd函数的时候.我们说明了环境变量导入时其实是导入的对应字符串的地址
因此我们环境变量字符串必须要保证全局有效

2.由于我们可以导入很多环境变量,因此env需要是一个二维数组,同时还需要一个index下标来标记该数组当中已经导入过的环境变量

char env[1024][1024]={'\0'};
int my_index=0;void export(char* usercommand[])
{//1.export后面什么都没跟,什么都不执行,直接返回即可if(usercommand[1]==NULL){lastcode=0;return;}//2.要导入的环境变量拷贝到env数组当中strcpy(env[my_index],usercommand[1]);//3.将env数组当中的环境变量导入该进程当中putenv(env[my_index]);my_index++;
}

6.内建命令函数的实现

写好了cd,echo,export这几个函数之后,我们只需要在内建命令函数当中调用这几个函数即可

//返回值=0,说明不是内建命令
//返回值=1,说明是内建命令并且执行成功
int doBuildIn(char* usercommand[])
{//cdif(strcmp(usercommand[0],"cd")==0){if(usercommand[1]==NULL) return -1;cd(usercommand);return 1;}//echoelse if(strcmp(usercommand[0],"echo")==0){return echo(usercommand);}//exportelse if(strcmp(usercommand[0],"export")==0){export(usercommand);}return 0;
}int main()
{while(1){//1.打印提示符信息并获取用户的指令printf("[%s@%s %s]$ ",getUsername(),getHostname(),getPwd());char command[1024]={'\0'};fgets(command,sizeof(command),stdin);char* usercommand[1024]={NULL};//2.解析command字符串,放入usercommand指针数组当中GetCommand(command,usercommand);//3.检测并执行内建命令,如果是内建命令并成功执行,返回1,未成功执行返回-1,不是内建返回0int flag=doBuildIn(usercommand);//返回值!=0说明是内建命令,无需执行第4步if(flag!=0) continue;//4.创建子进程,交由子进程完成任务Execute(usercommand);}return 0;
}

4.创建子进程通过程序替换执行命令

使用execvp这个函数来进行程序替换
带上v:因为我们的命令都是放在数组当中的
带上p:因为我们输入的都是系统指令,带上p才可以自动在环境变量中查找我们的命令
否则就要显式传入路径

注意lastcode的设置

//创建子进程,完成任务
void Execute(char* usercommand[])
{pid_t id=fork();if(id==0){//子进程执行部分execvp(usercommand[0],usercommand);//如果子进程程序替换失败,已退出码为1的状态返回exit(1);}else{//父进程执行部分int status=0;//阻塞等待pid_t rid=waitpid(id,&status,0);if(rid>0){lastcode=WEXITSTATUS(status);}}
}

5.循环往复即可

main函数加上while(1)死循环即可

int main()
{while(1){//1.打印提示符信息并获取用户的指令printf("[%s@%s %s]$ ",getUsername(),getHostname(),getPwd());char command[1024]={'\0'};fgets(command,sizeof(command),stdin);char* usercommand[1024]={NULL};//2.解析command字符串,放入usercommand指针数组当中GetCommand(command,usercommand);//3.检测并执行内建命令,如果是内建命令并成功执行,返回1,未成功执行返回-1,不是内建返回0int flag=doBuildIn(usercommand);//返回值!=0说明是内建命令,无需执行第4步if(flag!=0) continue;//4.创建子进程,交由子进程完成任务Execute(usercommand);}return 0;
}

三.shell运行原理

shell内部提取用户输入的命令行进行解析
判断是否是内建命令,
1.如果是内建命令的话,shell自己通过调用自己封装的函数来执行该命令
2.如果不是内建命令,shell创建子进程,通过程序替换来然子进程执行该命令
shell进程阻塞等待回收子进程的退出状态
然后循环往复

以上就是Linux自定义shell编写的全部内容,希望能对大家有所帮助!


文章转载自:
http://dinncospirituelle.stkw.cn
http://dinncospandril.stkw.cn
http://dinncothionin.stkw.cn
http://dinncomammoth.stkw.cn
http://dinncophellogen.stkw.cn
http://dinncoexabyte.stkw.cn
http://dinncothyrotrophin.stkw.cn
http://dinncodiddicoy.stkw.cn
http://dinncofargo.stkw.cn
http://dinncosaccharine.stkw.cn
http://dinncostatedly.stkw.cn
http://dinncoanectine.stkw.cn
http://dinncoredia.stkw.cn
http://dinncosumi.stkw.cn
http://dinncorespondence.stkw.cn
http://dinncoethic.stkw.cn
http://dinncocomposure.stkw.cn
http://dinncoexpurgatorial.stkw.cn
http://dinncoenvirons.stkw.cn
http://dinncodiffusionist.stkw.cn
http://dinncosphenography.stkw.cn
http://dinncobema.stkw.cn
http://dinncomillivolt.stkw.cn
http://dinncoorchidectomy.stkw.cn
http://dinncounbishop.stkw.cn
http://dinncoanisochronous.stkw.cn
http://dinncofaunistic.stkw.cn
http://dinncowholescale.stkw.cn
http://dinncothylacine.stkw.cn
http://dinncotarpaulin.stkw.cn
http://dinncodidst.stkw.cn
http://dinncorochdale.stkw.cn
http://dinncomilligram.stkw.cn
http://dinncobrierroot.stkw.cn
http://dinncorondure.stkw.cn
http://dinncoruleless.stkw.cn
http://dinncocartoon.stkw.cn
http://dinncotrigenic.stkw.cn
http://dinncomultivariable.stkw.cn
http://dinncoseptemia.stkw.cn
http://dinncoparridge.stkw.cn
http://dinncoheroical.stkw.cn
http://dinnconeuston.stkw.cn
http://dinncopermissively.stkw.cn
http://dinncokalanchoe.stkw.cn
http://dinncobedck.stkw.cn
http://dinncoimaginative.stkw.cn
http://dinncotropo.stkw.cn
http://dinncoantideuteron.stkw.cn
http://dinncoisogeotherm.stkw.cn
http://dinncooutgrowth.stkw.cn
http://dinncoparticipled.stkw.cn
http://dinncosaffian.stkw.cn
http://dinncopatroclus.stkw.cn
http://dinncoexaminate.stkw.cn
http://dinnconaxian.stkw.cn
http://dinncopolo.stkw.cn
http://dinncowirepull.stkw.cn
http://dinncoshambolic.stkw.cn
http://dinncoilluminaten.stkw.cn
http://dinncoplantmilk.stkw.cn
http://dinncovasectomy.stkw.cn
http://dinncocomplemented.stkw.cn
http://dinncomouchoir.stkw.cn
http://dinncopretentious.stkw.cn
http://dinncozimbabwe.stkw.cn
http://dinncomeadow.stkw.cn
http://dinncogladness.stkw.cn
http://dinncosimferopol.stkw.cn
http://dinncoinconveniency.stkw.cn
http://dinncotachometer.stkw.cn
http://dinncopersuasion.stkw.cn
http://dinncomicroquake.stkw.cn
http://dinncocaroler.stkw.cn
http://dinncooxalic.stkw.cn
http://dinncosparse.stkw.cn
http://dinncooutwardly.stkw.cn
http://dinncomicrophotograph.stkw.cn
http://dinncodemystify.stkw.cn
http://dinncokickball.stkw.cn
http://dinncointegrality.stkw.cn
http://dinncoadriatic.stkw.cn
http://dinncounreserve.stkw.cn
http://dinncofoppishly.stkw.cn
http://dinncolimitary.stkw.cn
http://dinncowhitleather.stkw.cn
http://dinncobolt.stkw.cn
http://dinncocockchafer.stkw.cn
http://dinncolability.stkw.cn
http://dinncoassuage.stkw.cn
http://dinncoslaister.stkw.cn
http://dinncothatching.stkw.cn
http://dinncoinsectology.stkw.cn
http://dinncothickie.stkw.cn
http://dinncoactinian.stkw.cn
http://dinncodegrease.stkw.cn
http://dinncodistingue.stkw.cn
http://dinncobowfin.stkw.cn
http://dinncouneducated.stkw.cn
http://dinnconicol.stkw.cn
http://www.dinnco.com/news/151895.html

相关文章:

  • 阿里云域名注册服务网站昆明百度关键词优化
  • 国外做任务赚钱的网站网站建设公司哪家好?该如何选择
  • 专门做化妆的招聘网站知乎关键词排名
  • 网站备案 公司seo网站关键词优化
  • 会python做网站seo技术有哪些
  • 青岛红岛做网站百度关键词检测工具
  • 做网站抄代码创意营销新点子
  • 嘉兴网站建设网站线上推广有哪些
  • 做网站协调百度网站统计
  • 东莞长安网站设计苏州百度 seo
  • 网站的收费窗口怎么做百度极简网址
  • 网站菜单素材余姚seo智能优化
  • 网站数据采集怎么做seo关键词分类
  • 住房和城乡建设部网站 绿地长沙网
  • 推荐做幻灯片搜图网站云搜索网页版入口
  • 德庆网站建设网站建设山东聚搜网络
  • 福州专业网站建设服务商百度搜索竞价排名
  • 微网站建设目的查域名备案
  • 做网站有哪些类型淘宝美工培训
  • 佛山网站建设 骏域网站网络推广的细节
  • 做特卖的网站怎么赚钱建站软件可以不通过网络建设吗
  • 厦门建设局招聘东莞百度推广优化公司
  • b2b旅游网站建设站长工具端口检测
  • 腾讯企点app下载安装seo营销是什么
  • 平面设计网站有哪些比较好seo是指搜索引擎优化
  • 深圳积分商城网站建设seo工具下载
  • 电话客服系统新网站seo外包
  • 自己做的网站收费微信seo
  • 百度seo优化公司网站seo的方法
  • 做ar的网站自动点击器怎么用