您的位置:首页 > 房产 > 家装 > 隐私浏览器_宁波seo在线优化方案公司_企业网站的推广方式和手段有哪些_外链代发2分一条

隐私浏览器_宁波seo在线优化方案公司_企业网站的推广方式和手段有哪些_外链代发2分一条

2024/12/23 16:40:16 来源:https://blog.csdn.net/2301_77239666/article/details/143091275  浏览:    关键词:隐私浏览器_宁波seo在线优化方案公司_企业网站的推广方式和手段有哪些_外链代发2分一条
隐私浏览器_宁波seo在线优化方案公司_企业网站的推广方式和手段有哪些_外链代发2分一条

欢迎来到博主的专栏:从0开始Linux
博主ID:代码小豪

文章目录

    • bash
    • myshell
    • 源码

bash

什么?我写bash?bash作为一个大型的shell程序,甚至已经成为一种语言。博主当然没能力复刻。

博主这里写了一个仿bash的shell程序。主要目的是仿制bash的命令行是如何执行命令的,但是bash的功能远超于此。相当于是博主在班门弄斧了。这里先带大家了解一下bash。

bash是linux系统下的默认shell程序。比如我们登录linux系统后,显示出来的命令行,其实就是bash程序的命令行模式
在这里插入图片描述
我们在命令行中写的指令,其实都是交给bash解析的。而且我们在命令行中启动的程序,其父进程都是bash。因此,我们打开linux系统所见的那个黑乎乎的命令行,其实就是bash,换句话说,我们在使用linux的时候,其实一直都在使用bash程序,只是我们对其不了解罢了。

myshell

博主将这个自己写的shell程序,命名为myshell,既然myshell要仿bash的命令行模式,首先我们要搞清楚bash的功能有什么。

首先是命令行,我们要先提示用户,当前我们处于命令行模式,请用户输入指令。因此,我们要先写出myshell的命令行提示符。为了和bash做出区分,因此命令行设计也要和bash不同才行。
在这里插入图片描述
其具体格式为[用户名@主机名 当前工作文件]:,而这些信息都在环境变量当中,因此需要用到getenv()函数获取这些数据。

//博主在文章末尾会附上完整代码,因此这里只展示部分,以提供思路参考

std::string getusr()//获取用户名
{std::string name=getenv("USER");return name.empty()?"None":name;
}void  PrintCommandLine()//打印命令行提示符        
{                                                 char buf[BASE_SIZE]={0};                       snprintf(buf,BASE_SIZE,"[%s@%s %s]:"\          ,getusr().c_str(),gethost().c_str(),getcwd().c_str());//获取这些环境变量,并且将其输出到buf中fputs(buf,stdout);                             fflush(stdout);                               
}

接下来,命令行可以接收用户输入的命令,我们将其保存在一个字符数组当中。

int main()
{char commandbuf[BASE_SIZE];//保存用户命令EnvInit();//初始化环境变量while(true){//1. 命令行提示符PrintCommandLine();//2. 获取用户命令if(GetUsrCommand(commandbuf)==false){continue;}//3. 解析用户命令ParseUsrCommand(commandbuf);//4. 执行用户命令ExecuteUsrCommand();}return 0;
}

第三步是解析用户命令行参数,比如ls -a -l --color,我们应该将每个单独的字符串(即空格隔开的字符串),按照顺序保存在一个字符型指针数组当中。
在这里插入图片描述
第四步是执行用户命令,在前面的进程章节中,博主提到,在命令行执行的程序,实际上都是bash创建的子进程,但是bash是如何创建的呢?其实原理很简单,bash使用fork函数,创建一个子进程,接着用execvpe函数,切换到用户想要启动的进程,比如bash执行ls指令,本质上就是bash先fork出一个子进程,接着execvpe("ls",gargv,environ)的方式创建的。具体的细节大家可以去看看博主前面写的,与进程相关的文章,实际上博主写这个myshell的本质是想让大家将进程系列的知识串联起来。

void ExecuteUsrCommand()//执行用户命令
{pid_t id=fork();//创建一个bash子进程if(id==0){execvpe(gargv[0],gargv,env);//切换到用户的命令进程exit(1);}else if(id>0){int status=0;waitpid(id,&status,0);//回收创建的子进程,避免产生僵尸进程                                                                                                                                        lastcode=WEXITSTATUS(status);                            }                                                            
}

但是有些命令,是不能通过创建子进程的方式执行的,比如cd指令,我使用这个指令是想让bash切换工作路径,而是让子进程切换路劲,因此如果解析出用户使用cd指令,我们应该让bash自己去执行,而非创建子进程执行,这种命令,我们称其为内建命令。bash的内建命令比较多,博主只写了其中几个。

bool CheckAndExecuteBulitCommand()//判断一下用户输入的是否是内建命令
{if(gargc==2&&strcmp(gargv[0],"cd")==0)//cd是内建命令{if(chdir(gargv[1])==-1)//切换myshell的当前工作路径{printf("No such file of dirtory");lastcode=ERROR;return true;}lastcode=0;return true;}else if(strcmp(gargv[0],"export")==0){addenv(gargv[1]);return true;}else if(strcmp(gargv[0],"env")==0)//显示myshell当前的环境变量{for(int i=0;env[i]!=nullptr;i++){printf("env[%d]:%s\n",i,env[i]);}return true;}else if(gargc==2&&strcmp(gargv[0],"echo")==0){if(strcmp(gargv[1],"$?")==0){printf("%d\n",lastcode);}else{printf("%s\n",gargv[1]);}lastcode=0;return true;}else if(strcmp(gargv[0],"exit")==0){printf("thank you for your using myshell\n");exit(0);}return false;
}

到此,一个简单的shell程序myshell就已经写好了,下面是实际使用的演示。

myshell

源码

点击下面链接获取源码与程序
简单的仿bash的shell程序

或:

#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<unistd.h>
#include<sys/wait.h>#define BASE_SIZE 256
//命令行参数与环境变量
char *gargv[BASE_SIZE];
int gargc;
char* env[BASE_SIZE];
extern char** environ;
//最近一次进程的运行结果
int lastcode=0;
#define ERROR 1//当前文件路径
char cwd[BASE_SIZE];
char cwdenv[BASE_SIZE];
void EnvInit()
{int index=0;while(environ[index]!=nullptr){env[index]=(char*)malloc(strlen(environ[index])+1);strcpy(env[index],environ[index]);index++;}env[index]=nullptr;
}void addenv(char* item)//增加环境变量
{int index=0;while(env[index]!=nullptr){index++;}env[index]=(char*)malloc(strlen(item)+1);strcpy(env[index],item);env[index+1]=nullptr;
}std::string getusr()//获取用户名
{std::string name=getenv("USER");return name.empty()?"None":name;
}std::string gethost()//获取主机名
{std::string hostname=getenv("HOSTNAME");return hostname.empty()?"None":hostname;
}std::string getcwd()//获取当前工作文件
{if( getcwd(cwd,BASE_SIZE)==nullptr){strcpy(cwd,"Node");}snprintf(cwdenv,BASE_SIZE,"PWD=%s",cwd);putenv(cwdenv);return cwd;
}
void  PrintCommandLine()//打印命令行提示符
{char buf[BASE_SIZE]={0};snprintf(buf,BASE_SIZE,"[%s@%s %s]:"\,getusr().c_str(),gethost().c_str(),getcwd().c_str());//获取这些环境变量,并且将其输出到buf中fputs(buf,stdout);fflush(stdout);
}bool GetUsrCommand(char commandbuf[])
{if(fgets(commandbuf,BASE_SIZE,stdin)==nullptr){return false;}commandbuf[strlen(commandbuf)-1]='\0';return true;}void ParseUsrCommand(char* commandbuf)
{memset(gargv,0,BASE_SIZE*sizeof(commandbuf[0]));gargc=0;gargv[gargc++]=strtok(commandbuf," ");while(bool(gargv[gargc]=strtok(nullptr," "))){gargc++;}
}bool CheckAndExecuteBulitCommand()//判断一下用户输入的是否是内建命令
{if(gargc==2&&strcmp(gargv[0],"cd")==0)//cd是内建命令{if(chdir(gargv[1])==-1)//切换myshell的当前工作路径{printf("No such file of dirtory");lastcode=ERROR;return true;}lastcode=0;return true;}else if(strcmp(gargv[0],"export")==0){addenv(gargv[1]);return true;}else if(strcmp(gargv[0],"env")==0)//显示myshell当前的环境变量{for(int i=0;env[i]!=nullptr;i++){printf("env[%d]:%s\n",i,env[i]);}return true;}else if(gargc==2&&strcmp(gargv[0],"echo")==0){if(strcmp(gargv[1],"$?")==0){printf("%d\n",lastcode);}else{printf("%s\n",gargv[1]);}lastcode=0;return true;}else if(strcmp(gargv[0],"exit")==0){printf("thank you for your using myshell\n");exit(0);}return false;
}void ExecuteUsrCommand()//执行用户命令
{pid_t id=fork();//创建一个bash子进程if(id==0){execvpe(gargv[0],gargv,env);//切换到用户的命令进程exit(1);}else if(id>0){int status=0;waitpid(id,&status,0);//回收创建的子进程,避免产生僵尸进程lastcode=WEXITSTATUS(status);}
}void debug()
{int i=0;while(gargv[i]){printf("%s\n",gargv[i]);i++;}printf("%d\n",gargc);
}int main()
{char commandbuf[BASE_SIZE];EnvInit();//初始化环境变量while(true){//1. 命令行提示符PrintCommandLine();//2. 获取用户命令if(GetUsrCommand(commandbuf)==false){continue;}//3. 解析用户命令ParseUsrCommand(commandbuf);//4. 执行用户命令if(CheckAndExecuteBulitCommand())//判断一下用户输入的是否是内建命令{continue;}ExecuteUsrCommand();}return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com