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

学做淘宝网站是骗子吗黄山seo排名优化技术

学做淘宝网站是骗子吗,黄山seo排名优化技术,漳州手机网站开发,wordpress在线考试目录 思路 创建自己的命令行 获取用户命令 分割命令 检查是否是内建命令 cd命令实现 进程程序替换执行程序 总代码 结语 思路 int main() {while (1){// 1. 自己的命令行PrintCommandLine();// 2. 获取用户命令char command[SIZE];int n GetUserCommand(command, si…

目录

思路

创建自己的命令行

获取用户命令

分割命令

检查是否是内建命令

cd命令实现

进程程序替换执行程序

总代码

结语


思路

int main()
{while (1){// 1. 自己的命令行PrintCommandLine();// 2. 获取用户命令char command[SIZE];int n = GetUserCommand(command, sizeof(command));if (n <= 0)return 1;// 3. 分割指令SplitCommand(command);// for(int i = 0; gArgv[i]; i++)//     printf("[%d]: %s\n", i, gArgv[i]);// 4. 检查是否是内建命令n = CheckBuildin();if(n) continue;// 5. 进程程序替换执行命令ExecuteCommand();}return 0;
}

上图中的五个函数,就是我们的思路

首先就是先写命令行:

就是这个,这个获取环境变量 + 指针操作 + 打印即可,较为简单

接着就是需要获取用户输入的指令,并且将其分割,放进数组里面,这里会涉及到strtok函数的使用

最后将我们的函数分割完之后,就是判断是否是内建命令了

如果是内建命令的话,这里就只实现cd和echo $?,我们就单独函数实现

如果不是内建命令的话,我们就正常进行程序替换即可

这里最关键的点就是程序替换了,因为我们要使用的所有的命令都在磁盘上保存着,这时我们fork创建子进程,并用程序替换将磁盘上待替换的程序加载到内存中并将这个子进程给覆盖,最终跑起来

创建自己的命令行

#define SkipPath(p)         \do                      \{                       \p += strlen(p) - 1; \while (*p != '/')   \p--;            \} while (0)const char *GetHome()
{const char *home = getenv("HOME");return home;
}const char *GetHostName()
{const char *hostname = getenv("HOSTNAME");return hostname;
}const char *GetCwd()
{const char *cwd = getenv("PWD");return cwd;
}const char *GetUserName()
{const char *name = getenv("USER");return name;
}void PrintCommandLine()
{char line[SIZE];const char *UserName = GetUserName();const char *Cwd = GetCwd();const char *HostName = GetHostName();SkipPath(Cwd);snprintf(line, sizeof line, "[%s@%s %s]:>", UserName, HostName, strlen(Cwd) == 1 ? "/" : Cwd + 1);printf("%s", line);fflush(stdout);
}

这里没什么好说的,主要就是getenv获取环境变量,我们的参数就是从环境变量中来

需要讲的一点就是do...while(0)那个宏,这里我们如果直接获取PWD的话,就是所有都打出来:

这个是效果

但是整体是这样的

所以我们需要将指针移动到最后面那里,然后只显示最后一段

但是这里为什么用的是宏呢?因为这里是用 c 语言实现的,写一个函数的话还要二级指针,太麻烦了,宏方便点

而使用do...while(0)是为了形成一个代码块,我们可以整体使用,并且在下面调用的时候可以随便加 “ ; ”,这样调用起来就和函数一样了

最终效果如下:

获取用户命令

int GetUserCommand(char command[], size_t n)
{char *s = fgets(command, n, stdin);if (s == NULL)return 2;// 处理 \ncommand[strlen(command) - 1] = ZERO;// printf("命令: %s", command);return strlen(command);
}

其实如果是cpp的话,就直接getline了,但是c语言实现的话我们就用 fgets 获取一行

直接获取即可,完了之后放进提前开辟并传进函数里面的数组中

需要说的一点就是,我们用户输入的指令看起来是这样的:

ls -a -l

但其实最后还会加一个回车表示确定,所以实际上就是这样子的:

ls -a -l\n

综上,我们就需要将最后一个位置设置为\0,上面的ZERO其实就是\0,只不过设置成了宏而已

分割命令

void SplitCommand(char *command)
{gArgv[0] = strtok(command, SEP);int index = 1;while (gArgv[index++] = strtok(NULL, SEP));// 在最后一次判断的时候,发现没有字符串了,strtok 就会返回NULL// 正好让 gArgv 的最后一个位置变为 NULL,这样在后面进程程序替换的时候就可以直接用
}

这里其实就是strtok函数的使用技巧

先说说为什么要分割:

我们获取了程序之后,不是说所有的功能都是我们自己写,像ls、cd、mkdir等等,这些指令在我们电脑中的磁盘上人家都帮我们写好了,shell也是调用的这些文件

所以我们要做的,就是在用户输入指令的时候,我们能将这些程序加载进来

这里就需要用到进程程序替换了,并且我们现在只有用户输入的数据,我们到后面肯定是execvp用起来最好,所以分割完直接放函数里面当参数即可,就实现这个功能了

再来说说 strtok

当你第一次使用strtok的时候,传入一个数组当参数(第一个参数位置,第二个是分隔符)

当你从第二次开始,第一个参数直接传NULL,就代表使用你一刚开始用个的那个数组

这也就是为什么一开始传command数组,后面传NULL的原因

接着最妙的就是,当strtok检测到没有可以分割的了,就会返回NULL,而我们的数组(execvp函数要求)最后一个位置必须以NULL结尾

检查是否是内建命令

int CheckBuildin()
{int yes = 0;const char *enter_cmd = gArgv[0];if(strcmp(enter_cmd, "cd") == 0){yes = 1;Cd();}else if(strcmp(enter_cmd, "echo") == 0 && strcmp(gArgv[1], "$?") == 0){yes = 1;printf("%d\n", lastcode);lastcode = 0;}return yes;
}

直接就是if、else检查判断就行,有多少个内建命令就有多少个if、else

cd命令实现

void Cd()
{const char* path = gArgv[1];if(path == NULL) path = GetHome();chdir(path);// 更新环境变量char cwd[SIZE];char temp[SIZE];getcwd(temp, sizeof temp);snprintf(cwd, sizeof(cwd), "PWD=%s", temp);setenv("PWD", cwd, 1);
}

这里主要用到的是chdir函数,ps:chdir支持直接使用 . 或者 ..

先说获取path,程序走到这里,那么用户输入的指令一定是cd,那么就会有像cd ..这样的指令

那么我们获取完之后,分割的指令中,第二个就一定是path,直接获取就好(下标是1)

当然也有可能用户直接输入一个cd,后面啥也不跟,我们随便处理一下,给他返回到家目录即可

最后我们在chdir之后,还需要更新一下路径

这里我们先获取环境变量中的PWD,然后使用snprintf写入数组中,以PWD:%s的格式

最后直接用setenv函数修改(或者说更新)环境变量即可

当然你也可以在最后使用putenv,这样的话,我们的cwd数组就需要开辟在全局,不然函数运行结束之后,cwd数组也就没了,这样putenv找不到他,就会直接异常终止我们的程序,显示段错误(Segmentation fault)

setenv就不用,这里推荐这个,因为他更现代、好用

进程程序替换执行程序

void ExecuteCommand()
{pid_t id = fork();if (id == 0){// 子进程execvp(gArgv[0], gArgv);exit(errno);}else{// 父进程int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){if(WIFEXITED(status) == 0){lastcode = WEXITSTATUS(status);printf("exit code: %d, exit signal:%d\n", WEXITSTATUS(status), WTERMSIG(status));}}}
}

就是execvp函数的使用,创建子进程直接替换,然后父进程在外面waitpid阻塞等待即可,也不用父进程干什么事情

总代码

MyShell.c

点开这个链接,里面就是代码,放在gitee里面了

结语

这篇文章到这里就结束啦!!~( ̄▽ ̄)~*

如果觉得对你有帮助的,可以多多关注一下喔

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

相关文章:

  • 为什么要用CGI做网站百度问一问免费咨询
  • 在福州做网站平台app如何推广
  • 分类信息网站如何做优化全网搜索
  • 网站开发云南泰州seo外包
  • 做视频网站用网站空间还是服务器seo和竞价排名的区别
  • 自己做服务器网站整合营销理论
  • 网站建设总结与体会seo自学
  • 做会展网站的关键词百度资源平台
  • 成都网站建设成功案例单招网seo排名优化公司
  • 产品毕业设计网站建设自己做网站需要什么条件
  • 企业网站开发费用包括哪些论坛推广怎么做
  • 普陀做网站公司引流推广公司
  • 泰安最新消息今天北京优化靠谱的公司
  • 网站地图模板.zip软文范例500字
  • wordpress 同步登陆seo网站推广经理
  • 海口网站开发百度客服24小时电话人工服务
  • 湖州做网站的公司百度推广网址
  • 织梦网站导入链接怎么做网页设计主题推荐
  • 河南汉狮做网站的公司免费的网站关键词查询工具
  • 东莞建英文网站的公司app代理推广平台
  • 做网站 php asp.net jsp建网站
  • 网站后台管理系统登录如何做谷歌优化
  • 长沙哪家公司做网站手机网页制作app
  • 开发公司出售没有规划内房屋谷歌seo搜索引擎下载
  • 济南网站的公司哪家好百度广告投放电话
  • 切图做网站过时了吗外贸推广如何做
  • 手机网站开发软件网络营销的十大特点
  • 合肥网站优化广告接单平台有哪些
  • 建筑模板尺寸和价格多少钱seo挂机赚钱
  • 网站建设需求说明书企业seo网络营销