南宁良庆网站建设外贸公司的网站

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

南宁良庆网站建设,外贸公司的网站,免费空间是什么意思,青海公路建设市场信用信息服务网站shell 自定义shell目标普通命令和内建命令#xff08;补充#xff09; shell实现实现原理实现代码 自定义shell 目标 能处理普通命令能处理内建命令要能帮助我们理解内建命令/本地变量/环境变量这些概念理解shell的运行 普通命令和内建命令#xff08;补充#xff09; … shell 自定义shell目标普通命令和内建命令补充 shell实现实现原理实现代码 自定义shell 目标 能处理普通命令能处理内建命令要能帮助我们理解内建命令/本地变量/环境变量这些概念理解shell的运行 普通命令和内建命令补充 在Linux系统中命令大致可以分为普通命令通常指的是外部命令和内建命令两大类。以下是关于这两类命令的详细解释 一、普通命令外部命令 定义普通命令也被称为外部命令是Linux系统中的实用程序部分。这些命令通常以单独的程序文件形式存在并存储在系统的特定目录中如/bin、/usr/bin、/sbin、/usr/sbin等。 特点 功能强大由于外部命令通常是独立的程序因此它们可以包含复杂的功能和算法。 不随系统一起加载在系统启动时外部命令并不会被加载到内存中。它们只在被需要时由shell程序通过PATH环境变量查找并加载到内存中执行。 执行速度相对较慢由于需要查找和加载程序文件以及创建子进程来执行命令因此外部命令的执行速度通常比内建命令慢。 示例常见的外部命令包括ls列出目录内容、vi文本编辑器、grep文本搜索工具等。 二、内建命令 定义内建命令是shell程序的一部分这些命令被直接集成在shell的源代码中并随着shell程序的启动而被加载到内存中。 特点 执行速度快由于内建命令是在shell程序内部执行的因此它们不需要创建子进程或查找外部程序文件从而提高了执行速度。 与shell紧密集成内建命令与shell程序紧密集成因此它们可以更方便地访问和操作shell的环境变量、函数等。 占用内存较少但相对外部命令而言虽然内建命令的执行速度更快但它们通常会占用一定的内存空间。然而由于这些命令是shell程序的一部分因此它们所占用的内存空间通常是可以接受的。 示例常见的内建命令包括cd切换目录、pwd显示当前工作目录、echo输出字符串到标准输出、history显示命令历史记录等。 三、区分方法 在Linux中可以使用type命令来区分一个命令是内建命令还是外部命令。例如 输入type cd输出结果为cd is a shell builtin表示cd是一个内建命令。 输入type ls输出结果为ls is aliased to ‘ls –colorauto’或类似信息表示ls是一个外部命令尽管这里显示了别名信息但可以通过进一步使用type -t ls或查看其路径来确认其为外部命令。 shell实现 实现原理 ⽤下图的时间轴来表⽰事件的发⽣次序。其中时间从左向右。shell由标识为sh的⽅块代表它随着时间的流逝从左向右移动。shell从⽤户读⼊字符串ls。shell建⽴⼀个新的进程然后在那个进程中运行ls程序并等待那个进程结束。
Shell的作用流程 读取输入 Shell等待用户输入命令。这可以是直接在命令行提示符下输入的命令也可以是来自脚本文件的命令。解析命令 Shell解析用户输入的命令包括命令本身、参数和选项。它会检查命令的语法是否正确以及命令是否存在。查找命令 Shell判断命令是内置命令还是外部命令。如果是内置命令则直接执行如果是外部命令则在PATH环境变量中查找相应的程序文件。执行命令 Shell将解析后的命令传递给操作系统内核执行。内核会读取命令并执行相应的操作。这包括调用系统资源、管理文件、执行程序等。返回输出 当命令执行完成后Shell会返回执行结果或错误信息给用户。这可以是命令的输出内容、状态码等。环境变量 Shell使用环境变量来存储系统配置和用户信息。这些变量在命令执行和脚本编写中起着重要作用。例如PATH变量指定了系统在哪些目录下查找可执行文件。重定向和管道 Shell支持将命令的输入和输出重定向到文件或其他设备上。同时它还支持管道操作可以将一个命令的输出作为下一个命令的输入。 实现代码 #include iostream #include cstdio #include cstdlib #include cstring #include string #include unistd.h #include sys/types.h #include sys/wait.h #include ctype.h using namespace std; const int basesize 1024; const int argvnum 64; const int envnum 64; // 全局的命令⾏参数表char *gargv[argvnum]; int gargc 0; // 全局的变量int lastcode 0; // 我的系统的环境变量char *genv[envnum]; // 全局的当前shell⼯作路径char pwd[basesize]; char pwdenv[basesize];string GetUserName() {string name getenv(USER);return name.empty() ? None : name; } string GetHostName() {string hostname getenv(HOSTNAME);return hostname.empty() ? None : hostname; } string GetPwd() {if(nullptr getcwd(pwd, sizeof(pwd))) return None;snprintf(pwdenv, sizeof(pwdenv),PWD%s, pwd);putenv(pwdenv); // PWDXXXreturn pwd;//string pwd getenv(PWD);//return pwd.empty() ? None : pwd; } string LastDir() {string curr GetPwd();if(curr / || curr None) return curr;// /home/whb/XXXsize_t pos curr.rfind(/);if(pos std::string::npos) return curr;return curr.substr(pos1); }string MakeCommandLine() {// [whbbite-alicloud myshell]\( char command_line[basesize];snprintf(command_line, basesize, [%s%s %s]# ,\GetUserName().c_str(), GetHostName().c_str(),LastDir().c_str());return command_line; } void PrintCommandLine() // 1. 命令⾏提⽰符 {printf(%s, MakeCommandLine().c_str());fflush(stdout); }bool GetCommandLine(char command_buffer[], int size) //2. 获取⽤⼾命令 {// 我们认为我们要将⽤⼾输⼊的命令⾏当做⼀个完整的字符串// ls -a -l -nchar *result fgets(command_buffer, size, stdin);if(!result){return false;}command_buffer[strlen(command_buffer)-1] 0;if(strlen(command_buffer) 0) return false;return true; }void ParseCommandLine(char command_buffer[], int len) // 3. 分析命令 {(void)len;memset(gargv, 0, sizeof(gargv));gargc 0;// ls -a -l -nconst char *sep ;gargv[gargc] strtok(command_buffer, sep);// 是刻意写的while((bool)(gargv[gargc] strtok(nullptr, sep)));gargc--;} void debug() {printf(argc: %d\n, gargc);for(int i 0; gargv[i]; i){printf(argv[%d]: %s\n, i, gargv[i]);} } bool ExecuteCommand() // 4. 执⾏命令 {// 让⼦进程进⾏执⾏pid_t id fork();if(id 0) return false;if(id 0){//⼦进程// 1. 执⾏命令execvpe(gargv[0], gargv, genv);// 2. 退出exit(1);}int status 0;pid_t rid waitpid(id, status, 0);if(rid 0){if(WIFEXITED(status)){lastcode WEXITSTATUS(status);}else{ lastcode 100;}return true;}return false; }void AddEnv(const char *item){int index 0;while(genv[index]){index;}genv[index] (char*)malloc(strlen(item)1);strncpy(genv[index], item, strlen(item)1);genv[index] nullptr;}// shell⾃⼰执⾏命令本质是shell调⽤⾃⼰的函数bool CheckAndExecBuiltCommand(){if(strcmp(gargv[0], cd) 0){// 内建命令if(gargc 2){chdir(gargv[1]);lastcode 0;}else{lastcode 1;}return true;}else if(strcmp(gargv[0], export) 0){// export也是内建命令if(gargc 2){AddEnv(gargv[1]);lastcode 0;}else{lastcode 2;}return true;}else if(strcmp(gargv[0], env) 0){for(int i 0; genv[i]; i){printf(%s\n, genv[i]);}lastcode 0;return true;}else if(strcmp(gargv[0], echo) 0){if(gargc 2){// echo \)?// echo \(PATH// echo helloif(gargv[1][0] \)){if(gargv[1][1] ?){printf(%d\n, lastcode);lastcode 0;}}else{printf(%s\n, gargv[1]);lastcode 0;}}else{lastcode 3;}return true;}return false; } void InitEnv(){extern char *environ;int index 0;while(environ[index]){genv[index] (char)malloc(strlen(environ[index])1);strncpy(genv[index], environ[index], strlen(environ[index])1);index;}genv[index] nullptr;}int main(){InitEnv();char command_buffer[basesize];while(true){PrintCommandLine(); // 1. 命令⾏提⽰符// command_buffer - outputif( !GetCommandLine(command_buffer, basesize) ) // 2. 获取⽤⼾命令{continue;}//printf(%s\n, command_buffer);ParseCommandLine(command_buffer, strlen(command_buffer)); // 3. 分析命令if ( CheckAndExecBuiltCommand() ){continue;}ExecuteCommand(); // 4. 执⾏命令}return 0;}