手机网站模板网深圳小企业网站建设

news/2025/9/22 17:48:44/文章来源:
手机网站模板网,深圳小企业网站建设,网上做设计兼职哪个网站好点,如何进行网站备案本文旨在编写一个简单的shell外壳程序#xff01;功能类似于shell的一些基本操作#xff01;虽然不能全部实现shell的一些功能#xff01;但是通过此文章#xff0c;自己写一个简单的shell程序也是不成问题#xff01;并且通过此文章#xff0c;可以让读者对linux中一些环…本文旨在编写一个简单的shell外壳程序功能类似于shell的一些基本操作虽然不能全部实现shell的一些功能但是通过此文章自己写一个简单的shell程序也是不成问题并且通过此文章可以让读者对linux中一些环境变量等基本概念有更深的理解希望读完本篇文章能对读者有一定的收获文末会附带自己编写shell的源码 好的废话少说正文开始 首先我们先来看一下linux中的shell长什么样子 这是其shell刚启动的时候的样子其外貌就是一个中括号内部加上一系列的东西其实当我们认真观察不难发现里面包括的就是“用户名““”“主机名字”“当前工作路径”那么发现了此规律之后我们不难实现此描述框那么接下来我们就着手与这些描述框的实现 linux描述框的实现 其中要想获得我们的用户名我们其实可以通过环境变量进行获取那么该如何获取环境变量的值呢这里就不得不引进一个获得环境变量的值的函数了 getenv(“USER”) 通过查询man手册我们可以发现getenv函数只需要传递一个参数即可那么此参数是什么呢其实此参数就是我们想要获得环境变量的值的名字所以要想获得用户名我们可以直接使用getenv(USER)即可获得我们想要的用户名我们可以验证一下USER对应的环境变量是否真的是我们所要的环境变量名我们可以通过echo $USER  此命令来判断是否真的是我们想要的用户名 不难看出USER对应的环境变量确实是我们的用户名 getenv(“HOSTNAME”) 既然有了用户名那么我们的主机名如何获得呢思路还是调用getenvHOSTNAME操作获取主机名同样的也可以通过echo命令进行验证这里就不再累赘了 getenv(“PWD”) 最后再来获取我们的当前工作目录也是调用getenv函数同样的可以通过echo命令进行验证 那么这些基本的环境变量都出来了,我们是否可以通过上述思路来创建一个简单的描述框呢 代码如下 其中这里为了方便起见直接将各个函数进行封装保证代码的健壮性 其中还需要扩充的几点有 为了区别与系统的shell我们在描述框后面加上一个#以区分系统的$ 这样我们的描述框已经基本实现了 获取用户指令以及将其分割 那么基本的描述框已经实现了我们还需要做的一点就是获取用户输入的指令那么如何获取用户的指令呢思路很简单定义一个数组然后将用户输入的字符放到数组中即可那么能否用scanf函数呢答案是肯定不行因为用户输入的指令一般都是指令选项其中指令和选项之间都是有着空格来间隔区分的那么应该如何获取用户的输入呢答案很简单用fgets函数即可那么接下来我们就来介绍一下fgets函数的用法 fgets函数 通过查询man手册可以看出其中fgets函数中有三个参数第一个是就是缓冲区即将要被写到哪里的地址第二个参数表示此缓冲区的大小第三个参数是用哪些流进行写入一般第三个参数我们都选择stdin标准输入流进行写入 既然介绍了fgets函数的用法那么我们就知道我们需要创建一个数组来存放即将要写入的数据数组的大小自己来定义即可 那么用户的指令获取成功之后我们需要将用户的指令进行打散然后利用execvp进行替换即可那么如何进行打散这段字符串呢这里就不得不引进我们C语言中的strtok函数了 strtok()函数 查询man手册可以得知strtok有两个参数其中第一个参数是将要打散的原字符串第二个字符串指的是用于打散的标记符都有哪些。 返回值第一次调用返回标记符第一次出现的位置然后并将标记符转化为\0此时会记住此位置然后再次使用的使用第一个参数只需要传NULL指针即可如果最终不可再进行分割的时候返回值就会返回NULL这样就可以将原字符串进行打散我们的目的是想要将其打散放在一个数组中方便之后使用所以我们还需要自己再定义一个指针数组用于存放分割后的各个字符串 通过以上的思路我们就可以将用户命令和将命令打散此功能进行实现了 代码如下 其中第60行是将最后的\n转化为\0防止其进行跳行其中在commandSplit函数中我们还设置了条件宏用于检查我们的代码是否将原字符串进行正确的打断如果最后不想要打印出分割后的字符串可以将宏定义取消即可其中char*out[]表示打散后的数组char *in 表示的是原字符串spint是一个宏定义用来标明分割字符串都有哪些,这里分割符只要空格 至此描述框和获取用户指令都已经实现了 完成进程替换 那么我们如何将用户的指令转化为shell的操作呢这里就得引进进程替换的概念我们需要将进程进行替换来让他执行我们想让他执行的代码 那么进程替换有很多中调用方式我们应该选择那种呢其实很简单我们已经将用户的命令行进行打断分散处理了所以我们完全可以根据v的特性来进行选择又因为我们并不知道用户以后需要输入的指令所以我们也不知道其指令所在路径所以我们就可以使用execvp这个系统调用来进行进程替换其中v我们已经有了p默认为我们提供了路径所以用户的指令肯定是存放在v[0]上的所以我们的进程替换就可以写出来了 需要注意的是我们要进行进程替换的时候一定不要让我们的父进程进行替换因为一旦父进程进行替换的时候如果进程挂掉了那么我们的shell不就是结束了么所以我们可以使用fork来创建子进程来进行进程替换而父进程只需要等待子进程退出回收其资源即可 下面来看一下进程替换的代码 至此进程替换的指令也可以实现了我们自定义的shell程序也能实现ls  top pwd 等操作了但是对于其他命令我们自定义的shell程序却不能正确的执行了例如cd命令还有export命令这是为什么呢这就不得不引进内建命令了 内建命令 何为内建命令呢内建命令就是这些命令只能由bash自己执行而不能让子进程进行执行那么我们常见的linux中有哪些命令是内建命令呢下面就来简单的介绍几个内建命令并且在我们自定义的shell中实现这些内建命令 cd命令 其中cd是一种常见的内建命令这个指令只能交付给父进程自己执行而不能交付给子进程让子进程执行因为cd指的就是改变当前的路径如果交给子进程进行执行那么父进程的路径将不会修改那么该如何进行编写我们shell中的cd命令呢 代码如下 其中cd主要进行的操作就是将当前的工作目录进行修改那么如何修改当前的工作目录呢这里就不得不引进chdir这个系统调用了 chdir 其中chdir函数只有一个参数这个参数代表的是将要修改的路径我们只需要定义一个字符数组然后将我们要修改的路径存放到此数组中然后将此数组就进行传递即可完成改变当前的路径其中还需要将当前的环境变量PWD也进行修改创建一个临时数组和全局数组全局用于存放环境变量的值然后将修改后的环境变量的值写入到全局数组中最后再将环境变量进行同步只需要调用putenv就可以将环境变量进行修改 export命令 还有一个常见的内建命令就是export那么什么是export呢export命令就是将我们定义的变量导入到环境变量之中下面来看一下如何实现我们自己shell的export命令 代码如下 其中我们需要定义一个全局变量的数组用于存放我们的环境变量的值如果我们使用的是局部变量的话就会导致每次用户输入命令的时候我们不更新环境变量其环境变量就会自动消失这是因为局部变量的局部性所以定义一个全局变量是最为合适的但是此代码也有一个小bug就是当再导入一个新的环境变量的时候之前的那个环境变量就会消失 既然环境变量也能导出了那么我们总得知道是否真正的将其导出了这里就得引出了echo命令了因为此命令也是内建命令所以也得交给我们的父进程自己执行下面就来写一下关于echo命令的代码 ehco命令 其中echo命令简单分为三个功能第一个是回显出退出码第二个是显示出环境变量的值第三个就是普通的回显字符串 对于第一个回显错误码我们只需要判断其分割后的第二个字符串是否是“$”即可然后根据$后面跟的字符即可判断出来如果$后面跟的是?字符的话那就是显示出退出码的信息如果“$”后面跟的不是?而是一个字符串那么就是显示出其环境变量的值最后如果连$字符都没有的话那就是简单的回显字符串了 这就是echo命令实现的简单逻辑了 但是我们写的shell还有大多数功能没有实现比如本地变量的存储以及重定向的操作对于本地变量的存储我们可以用malloc在堆内申请空间来存储变量中的值对于重定向我们可以利用dup函数进行重定向的操作下面来看一下简单的检查是否有重定向的函数吧 重定向 其中SkipSpace是一个宏其作用就是跳过空格的我们检查是否有重定向顺便也能将文件名与命令相分割然后在execu函数体内进行重定向的操作 这样我们的shell也能支持重定向的功能了 至此我们自己的shell已经初步完成了它能完成一些简单的操作希望读完本文读者也尝试写一下shell的实现 下面将源码附在下面 源码 #includestdio.h #includestring.h #includesys/types.h #includefcntl.h #includesys/stat.h #includesys/wait.h #includeunistd.h #includestdlib.h #define Size 50 #define NUM 1024 #define spint //#define debug 1#define NOredir 0 #define AppendRedir 3 #define InputRedir 1 #define OutputRedir 2#define SkipSpace(pos) do{ while(isspace(*pos)) pos; }while(0)char *filenameNULL; int redirNOredir; int lastcode0; char enval[1024]; char cwd[1024]; // char eni[1024]; const char* getUser() {char* usergetenv(USER);if(user){return user;}else{return none;}}const char*getHost() {char *hostgetenv(HOSTNAME);if(host){return host;}else{return none;} }char*gethome() {char *pwdgetenv(PWD);if(pwd){return pwd;}else{return none;} }int getcommand(char*command,int n) {printf([%s%s %s]#,getUser(),getHost(),gethome());char*rfgets(command,n,stdin);if(rNULL) return 0 ;command[strlen(command)-1]\0;return 1; }void commandSplit(char *in,char *out[]) {int argc0;out[argc] strtok(in,spint);while(out[argc]strtok(NULL,spint)); #ifdef debug int i0;for(i0;out[i];i){// printf(%d:%s\n,i,out[i]);printf(%s\n,out[i]);}// printf(\n); #endif }//只需要将用户的命令行数组指令传递过来即可 int execute(char* argv[]) {pid_t ritfork();if(rit0){int fd0;if(redirInputRedir){fd open(filename, O_RDONLY); // 差错处理我们不做了dup2(fd, 0);}else if(redirOutputRedir){fd open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);dup2(fd, 1);}else if(redirAppendRedir){fd open(filename, O_WRONLY | O_CREAT | O_APPEND, 0666);dup2(fd, 1);}else{//do nothing}//子进程用于进程切换而不是让父进程bash直接自己运行//其中进程替换直接用execvp函数即可因为我们有了用户的命令行了execvp(argv[0],argv);exit(0);//如果替换失败就会退出负责代表进程替换成功}else{int status0;//父进程只需要等待子进程退出即可!pid_t retwaitpid(rit,status,0);if(retrit){// printf(wait success\n);lastcode WEXITSTATUS(status);// printf(%d,lastcode);// return 0;}}return 0; }void cd(const char*path) {chdir(path);char tem[1024];getcwd(tem,sizeof(tem));sprintf(cwd,PWD%s,tem);putenv(cwd);} //检查是否为内建命令并执行 int dobuildin(char*argv[]) {//cd命令if(strcmp(argv[0],cd)0){char *pathNULL;if(argv[1]NULL) {pathgethome(); }else pathargv[1];cd(path);return 1;}else if(strcmp(argv[0],export)0){ if(argv[1]NULL) return 1; strcpy(enval,argv[1]);// strcpy(envir,argv[1]);// putenv(envir);//此处需要用全局变量数组来存储env 因为一旦使用局部变量的时候会随着用户输入的指令putenv(enval);//此处需要用全局变量数组来存储env 因为一旦使用局部变量的时候会随着用户输入的指令//环境变量会消失return 1;}else if(strcmp(argv[0],echo)0){//与系统中的echo保持一致if(argv[1]NULL){printf(\n);return 1;}if(*(argv[1])$strlen(argv[1])1){char *valargv[1]1;if(strcmp(val,?)0){printf(%d\n,lastcode);lastcode0;}else{char *envalgetenv(val);if(enval) printf(%s\n,enval);else{printf(\n);}// return 1;}return 1;}else{printf(%s\n,argv[1]);return 1;}// return 1;}else if(0){}return 0; }void checkRedir(char usercommand[], int len) {// ls -a -l log.txt// ls -a -l log.txtchar *end usercommand len - 1;char *start usercommand;while(endstart){if((*end) ){if(*(end-1) ){*(end-1) \0;filename end1;SkipSpace(filename);redir AppendRedir;break;}else{*end \0;filename end1;SkipSpace(filename);redir OutputRedir;break;}}else if(*end ){*end \0;filename end1;SkipSpace(filename); // 如果有空格就跳过redir InputRedir;break;}else{end--;}} }int main() {while(1){char userCommand[NUM];char* argv[Size];//显示框架!获取用户输入的指令int n getcommand(userCommand,sizeof(userCommand));// if(n0) continue;// printf(%s)//将用户的命令进行切割checkRedir(userCommand,strlen(userCommand));commandSplit(userCommand,argv);//判断命令是否为内建命令1int kdobuildin(argv);if(k) continue;//创建子进程用于进行进程替换execute(argv);}// return 0; }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/909869.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我做的静态网站怎么发布到网上手机网站规格

随着人工智能的不断发展,ChatGPT(OpenAI)和文心一言都代表了当前先进的自然语言处理技术。它们在智能回复、语言准确性和知识库丰富度等方面都有各自的优势。在下面的比较中,我们将从多个角度探讨这两个AI助手,帮助你更…

农业产品如何建网站一个空间可以做几个网站吗

FPGADDRSERDESUSB3.0方案,设备包含发送端接收端,物料上采用光纤通讯,数据只能单向传输,避免反向攻击,确保系统安全 客户应用:高安全、高可靠性要求的场景 主要性能: 1.支持USB3.0传输,实测可达到350MB/s 2.…

MyBatis-Plus 全方位深度指南:从入门到精通

在 Java 的世界里,数据持久化是任何企业级应用的基石。MyBatis 以其轻量、灵活以及对 SQL 的完全掌控而备受开发者喜爱。然而,随着项目复杂度的增加,开发者们发现自己陷入了编写大量重复性 CRUD(创建、读取、更新、…

Stm32学习过程笔记

View PostStm32学习过程笔记标准库 1.RCC时钟设置(必备) RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//APB2外设2. GPIO外设通用输入输出 GPIO_InitTypeDef GPIO_InitStructure; …

鸿蒙项目实战(十):web和js交互

1、实现android的addJavascriptInterface操作 即鸿蒙注入JavaScript对象到window对象中 javaScriptProxy javaScriptProxy(javaScriptProxy: JavaScriptProxy) // xxx.ets import { webview } from @kit.ArkWeb;class …

【9.24 直播】集群数据管理实战:时序数据库 IoTDB 数据分区、同步与备份详解

保障集群高性能、高可用与数据安全,9.24 19 点线上见!📁分布式高可用场景下,如何设计数据分区策略才能最大化系统效能? 🚀跨“端-边-云”数据同步如何保证一致性与可靠性? 🔍数据备份方案又该如何设计才能万…

影视广告制作报价单宁波seo推广开发

【电脑商网专稿】虚拟软件究竟是什么软件, 是让所有的软件都”虚拟”执行吗, 虚拟软件层究竟是怎样的一层软件? 为什么现在这么多的公司和个人都在使用这种软件, 虚拟软件能代替操作系统完全控制硬件吗? 下面就让我们逐渐的揭开虚拟化技术这一特殊软件层的秘密吧.谈到虚拟化就…

函数计算进化之路:AI 应用运行时的状态剖析

将 AI 应用运行时迁移至 Serverless 平台,是应对未来智能化浪潮、实现敏捷创新和高效运营的必由之路。作者:世如 AI 应用基础设施正在经历一场深刻的范式迁移。传统的 AI 应用工作负载部署模式,以其长期预置、“始终…

自己做网站 服务器数字展厅企业展厅

最近推送了几个Excel中最难的函数,哀嚎遍野,太难了……所以今天我们来“从万丈高楼平地起”的平地讲起!搞懂Excel单元格引用方式,是保证公式准确最最基本的条件!单元格引用方式整体分三种:相对引用(A1)绝对…

发布网站搭建教程平面设计作品集如何制作

Tkinter标准库 Tkinter是Python的标准GUI库,也是最常用的Python GUI库之一,提供了丰富的组件和功能,包括窗口、按钮、标签、文本框、列表框、滚动条、画布、菜单等,方便开发者进行图形界面的开发。Tkinter库基于Tk for Unix/Wind…

宁波建设局网站做水果代理去哪个网站

设计思想 傅里叶变换,表示能将满足一定条件的某个函数表示成三角函数(正弦和/或余弦函数)或者它们的积分的线性组合。在不同的研究领域,傅里叶变换具有多种不同的变体形式,如连续傅里叶变换和离散傅里叶变换。 快速傅…

自动全屏网站模板wordpress Apache升级

概述 之前在《【Godot4.2】Tree控件自定义树形数据ETD及其解析》一文中,实现了对带缩进的层级结构文本的解析,并将其用于Tree控件的列表项构造。 不过当时并没有实现专门的类,今天花了一点时间实现了一下。现在可以更方便的构造和解析ETD数…

利鑫做彩票网站网站规划与设计h5

一. 安全编程 rust逆向,直接动调 定位关键函数sub_7FD043E88C70 下断点跟进 观察控制台 guess number plz input 1-10 number 这时我们随便输入一个数,往下跟进 .text:00007F14B3684E9B .text:00007F14B3684E9B loc_7F14B3684E9B: .text:00007F14B…

网站免费下载安装大全手机版国外做名片网站

Android中提供的HttpURLConnection和HttpClient接口可以用来开发HTTP程序。以下是本人在学习中的总结与归纳。1. HttpURLConnection接口 首先需要明确的是,Http通信中的POST和GET请求方式的不同。GET可以获得静态页面,也可以把参数放在URL字符串后面&…

广州魔站建站企业网站实施方案

嵌入式的坑烧钱嵌入式的学习十分烧钱,这就让人有点望而却步。我是做DSP起步的,更是能体会到嵌入式绝对是一个拿钱搭梯子的学习行业。在我的学习过程中身边有不少的人投向了CS行业,也就是纯软件开发,比如网页、手机应用、数据库等。…

公司网站本地如何弄中卫市建设网站

计算机考研学院简介计算机与通信学院前身为原湖南大学计算机科学系。1978年组建计算机教研室并开办计算机本科专业,1981年5月正式成立计算科学系,2001年10月正式成立计算机与通信学院。学院现有计算机应用技术博士授权点;计算机科学与技术、信…

01_进程与线程

大部分操作系统的任务调度是采用时间片轮转的抢占式调度方式,也就是说一个任务执行一小段时间后强制暂停去执行下一个任务,每个任务轮流执行。任务执行的一小段时间叫做时间片,任务正在执行时的状态叫运行状态,任务…

第六届医学人工智能国际学术会议(ISAIMS 2025)

第六届医学人工智能国际学术会议(ISAIMS 2025) 2025 6th International Symposium on Artificial Intelligence for Medical Sciences ( ISAIMS 2025) 第六届医学人工智能国际学术会议(ISAIMS 2025)将于2025年10月24…

完整教程:Java多线程初阶

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

网站查询服务器成都网站建设公

战神4 幕后花絮 概念艺术找出Java幕后发生的事情,以及新功能如何实现 在上一篇文章中,我们介绍了即将发布的Java 9版本的新功能和尚待解决的功能,并简要提到了将新功能添加到下一个版本之前要经历的过程。 由于此过程几乎影响了所有Java开发人…