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

网站建设可以买东西厦门seo公司到1火星

网站建设可以买东西,厦门seo公司到1火星,可以免费做调查问卷的网站,网站设计报价方案作者:小萌新 专栏:Linux 作者简介:大二学生 希望能和大家一起进步! 本篇博客简介:使用进程的基础知识和进程控制知识做出一个简单的shell程序 命令行解释器介绍搭架子缓冲区获取命令如何从标准输入中获取字符串解析命令…

作者:@小萌新
专栏:@Linux
作者简介:大二学生 希望能和大家一起进步!
本篇博客简介:使用进程的基础知识和进程控制知识做出一个简单的shell程序

命令行解释器

  • 介绍
  • 搭架子
    • 缓冲区
  • 获取命令
    • 如何从标准输入中获取字符串
    • 解析命令
    • strtok分隔字符串
  • 进程替换
  • 内建命令
    • 工作目录
    • chdir函数
  • 全部代码

介绍

我们从之前的学习可以知道 实际上我们的命令行解释器就是一个进程 bash
我们在执行例如 ls ll这些命令的时候实际上就是 bash 在创建子进程 让子进程执行这些命令 那么我们能不能模仿 bash 做一个简单的命令行解释器呢?
答案显然是可以的
本篇博客会使用到进程相关概念以及进程控制相关知识 如果没有前置知识的储备建议先看我之前写的两篇博客
进程相关概念
进程控制相关

搭架子

我们首先先观察我们自己使用的命令行是什么格式的

在这里插入图片描述
我们发现 这里的格式就是 用户名@主机名+地址

我们可以直接复制到我们的程序中使用

int main()    
{    while(1)    {    printf("[root@VM-8-3-centos lesson11]# ");    sleep(1);    }    return 0;    
}      

我们之后运行这个程序

在这里插入图片描述
我们发现 这个程序竟然没有任何输出的内容

这是为什么呢?

缓冲区

我们这里再次介绍下缓冲区的概念

为了提高效率 我们在打印数据的时候并不是直接打印到输出设备当中而是会先把数据存放到一个叫做输出缓冲区的地方 直到我们主动去刷新这个输出缓冲区里面的数据才会打印到输出设备
输入同理

我们平时打印语句的时候一般会在末尾加上一个 \n 换行符 实际上它就具有刷新缓冲区的功能

此外我们还可以使用fflush(stdout) 去主动刷新缓冲区

至于stdout是什么 我们在后面的基础IO部分会着重讲解

加上刷新缓冲区代码之后我们的代码如下

int main(){while(1){printf("[root@VM-8-3-centos lesson11]# ");fflush(stdout);sleep(10);                                                                           }return 0;}

之后我们再次编译运行便会出现这样的情况

在这里插入图片描述
我们现在已经可以基本模拟bash的框架了

当然为了区分我们自己的minishell和bash 我们将最前面的用户改为shy

获取命令

搭好架子之后我们就可以开始模仿bash的行为了

bash的本质是一个命令行解释器

所以说我们必须要先获命令是什么

我们可以使用字符数组来获取我们输入的命令

我们定义一个字符数组 它的默认大小为128

#define NUM = 128
char command[128];

之后我们每次输入命令之后要清空字符串 这里有一种十分简便的方式

command[0] = 0;

因为这个字符数组的第一位被设置为了0 所以说这个字符串就是为空的

如何从标准输入中获取字符串

我们可以使用c语言中的scanf来获取我们输入的字符串吗

答案显然是不行的

因为我们输入的命令是这样子的格式

ls -a -l

我们可以发现 中间使用了空格号分割 但是我们的scanf遇到空格就是停止读取

这样子我们就只能使用另外的函数

这里我们使用fgets这个函数

在这里插入图片描述
这个函数具有三个参数 我们下面分别介绍下这三个参数

char* str 是我们要读取数据到哪里

int num 是我们要读取数据的个数

FILE* stream 是我们要从哪个文件读取数据

所以我们可以这么写

  fgets(command , NUM , stdin);

它的意思是从标准输入流中读取数据 读取NUM个数据到command中

我们实验下到目前为止的代码

  8  #define NUM 1209 10 11 int main()12 {13   char command[NUM];14   while(1)15   {16     command[0] = 0;                                                                      17     printf("[shy@VM-8-3-centos lesson11]# ");18     fgets(command, NUM , stdin);19     printf("echo: %s",command);20     fflush(stdout);21     sleep(10);22   }23   return 0;24 }

我们编译运行下试试看

在这里插入图片描述
我们输入在缓冲区的数据确实是被打印到屏幕上了

可是为什么这里多打了一个换行呢?(/n)

这里其实是因为我们敲回车的时候往缓冲区多输入了一个/n

要解决这个办法也很简单 我们找到这个/n字符的所在位置 将它置0就好了

在这里插入图片描述

它在缓冲区中应该是这个样子的

我们只要将字符串有效字符后一位置0就可以了

在这里插入图片描述
我们使用strlen测出长度之后减去一便是\n的下标

将它置0就可以

代码表示如下

  command[strlen(str)-1];

在这里插入图片描述
这样就能完美获取标准输入中的字符串了

解析命令

在这里插入图片描述

我们输入的命令是这样子的格式

要将这一串字符串解析成一个个的命令我们必须要分隔字符串

在c语言中 我们使用strtok命令来分隔字符串

strtok分隔字符串

在这里插入图片描述

它的返回值会返回我们分隔字符串的第一个字符位置

它有两个参数

第一个参数 char * str 表示要分割的字符串

第二个参数 const char *delim 表示分隔符

如果我们想要一直获取同一个字符串 则第一个参数在后面的时候都要传入空指针

我们可以写一段代码验证下这个函数的使用

#include <stdio.h>
#include <string.h>int main()
{char str[] = "Hello, World! Welcome to C programming.";const char delim[] = " ,.!"; // 以空格、逗号和句号作为分隔符char *token;// 获取第一个子字符串token = strtok(str, delim);// 依次获取剩下的子字符串while (token != NULL){printf("%s\n", token);token = strtok(NULL, delim);}return 0;
}

它运行的结果如下

在这里插入图片描述
我们使用strtok去获取我们的指令到一个字符数组中

   24     int i = 1;25     char* delim = " ";26     argv[0] = strtok(command , delim);27     while(argv[i] = strtok(NULL , delim))28     {29       i++;30     } 

进程替换

我们这里要想清楚一点 绝对不能使用父进程去进行进程替换

因为如果我们使用父进程进行进程替换的话父进程的代码和数据就会全部被覆盖

这样子的话命令行就成一次性工具了

所以说我们的父进程需要创建一个子进程去做这个任务

父进程在此时等待子进程做完任务回收资源

代码表示如下

   32     if (fork() == 0)                                                              33     {                                                                             34       // child                                                                    35       execvp(aegv[0] , argv);                                                     36       exit(1);                                                                    37     }                                                                             38 39     waitpid(-1 , NULL , 0); 

此时我们的程序就基本完成了

我们运行下试试效果

在这里插入图片描述
我们发现它基本上可以模仿bash进程的各种行为了

中途有一次我敲击了 ll 命令系统没有反应是因为我们没有定义这个命令

内建命令

内建命令 就是由 Bash 自身提供的命令

但是我们目前的代码仍然会遇到一些问题

我们敲出下面的命令

在这里插入图片描述
我们发现我们使用cd … 命令之后竟然没有回到上一级目录 这是为什么呢

工作目录

实际上我们的进程中有一个叫做工作目录的东西

我们可以在 /proc/进程号中看到
在这里插入图片描述
该路径也叫做进程的当前路径

我们使用cd …命令的时候实际上就是对于这个路径在进行操作

回到我们之前的问题 为什么我们使用cd命令的时候系统不能识别呢?

因为我们是通过子进程去调用的cd命令 子进程有着自己的进程目录

它的修改经过写时拷贝不会影响父进程

所以说我们如果是遇到内建命令的话就需要父进程自己去执行之

那么我们如何改变父进程的工作目录呢?

chdir函数

我们可以通过chdir函数来改变 当前进程的工作目录

它的使用方式如下

在这里插入图片描述
我们直接在它后面输入我们要改变的路径就可以

知道如何修改之后我们继续编写代码

   32     // 内建命令33     if (strcmp(argv[0], "cd") == 0)34        {35          if (argv[1] != NULL)36          {37            chdir(argv[1]);38          }39 40          continue; // 不执行下面了                                                    41        }

在这里插入图片描述

这样子我们的所有代码就完成了

全部代码

    1 #include <stdio.h>2 #include <stdlib.h>3 #include <unistd.h>4 #include <sys/wait.h>5 #include <sys/types.h>6 #include <string.h>7 8 #define NUM 1209 #define CMD_NUM 4010 11 int main()12 {13   char command[NUM];14   char* argv[CMD_NUM];15   while(1)16   {17     command[0] = 0;18     printf("[shy@VM-8-3-centos lesson11]# ");19     fflush(stdout);20     fgets(command, NUM , stdin);21     command[strlen(command)-1] = 0;22     //  printf("echo: %s",command);23     // ½âÎöÃüÁî24     int i = 1;
W> 25     char* delim = " ";26     argv[0] = strtok(command , delim);
W> 27     while(argv[i] = strtok(NULL , delim))28     {29       i++;30     }31 32     // ÄÚ½¨ÃüÁî33     if (strcmp(argv[0], "cd") == 0)34        {35          if (argv[1] != NULL)36          {37            chdir(argv[1]);38          }39 40          continue; // ÏÂÃæ²»Ö´ÐÐÁË                                                                                                                                                                                                                      41        }42 43     if (fork() == 0)44     {45       // child 46       execvp(argv[0] , argv);47       exit(1);48     }49 50     waitpid(-1 , NULL , 0);51   }52   return 0;53 }

文章转载自:
http://wanjiagander.Ljqd.cn
http://wanjiademyelinate.Ljqd.cn
http://wanjiabookstore.Ljqd.cn
http://wanjiamissile.Ljqd.cn
http://wanjiapsychognosis.Ljqd.cn
http://wanjiadiesel.Ljqd.cn
http://wanjiacollegium.Ljqd.cn
http://wanjiaeptitude.Ljqd.cn
http://wanjialivre.Ljqd.cn
http://wanjialettic.Ljqd.cn
http://wanjiacholate.Ljqd.cn
http://wanjiacaecectomy.Ljqd.cn
http://wanjiacropless.Ljqd.cn
http://wanjiacarrier.Ljqd.cn
http://wanjianunchakus.Ljqd.cn
http://wanjiaindigestion.Ljqd.cn
http://wanjiazamboanga.Ljqd.cn
http://wanjiaexothermic.Ljqd.cn
http://wanjialigniferous.Ljqd.cn
http://wanjiarenata.Ljqd.cn
http://wanjiacumulus.Ljqd.cn
http://wanjiawillful.Ljqd.cn
http://wanjiaspotless.Ljqd.cn
http://wanjiahuttonite.Ljqd.cn
http://wanjialandship.Ljqd.cn
http://wanjiarainband.Ljqd.cn
http://wanjiaeradiation.Ljqd.cn
http://wanjiagastroenteritis.Ljqd.cn
http://wanjiasalination.Ljqd.cn
http://wanjiaswale.Ljqd.cn
http://wanjiafinecomb.Ljqd.cn
http://wanjiatrimming.Ljqd.cn
http://wanjiaisoelectronic.Ljqd.cn
http://wanjiasakyamuni.Ljqd.cn
http://wanjiagruyere.Ljqd.cn
http://wanjiaspindle.Ljqd.cn
http://wanjiaanxiolytic.Ljqd.cn
http://wanjiareckoner.Ljqd.cn
http://wanjiacableship.Ljqd.cn
http://wanjiawoundable.Ljqd.cn
http://wanjiasafeblower.Ljqd.cn
http://wanjiaabut.Ljqd.cn
http://wanjiascoresheet.Ljqd.cn
http://wanjiaconfirmed.Ljqd.cn
http://wanjiareconvence.Ljqd.cn
http://wanjiachoiceness.Ljqd.cn
http://wanjiaheterocaryon.Ljqd.cn
http://wanjiaredemptorist.Ljqd.cn
http://wanjiaproestrum.Ljqd.cn
http://wanjiasememe.Ljqd.cn
http://wanjiadithyrambic.Ljqd.cn
http://wanjiabladework.Ljqd.cn
http://wanjiabedstead.Ljqd.cn
http://wanjiaislandless.Ljqd.cn
http://wanjiasemiannual.Ljqd.cn
http://wanjiacanticle.Ljqd.cn
http://wanjiahumanitas.Ljqd.cn
http://wanjiachaldaean.Ljqd.cn
http://wanjiaashcan.Ljqd.cn
http://wanjiahourglass.Ljqd.cn
http://wanjiamuscovado.Ljqd.cn
http://wanjiafurculum.Ljqd.cn
http://wanjiacybersex.Ljqd.cn
http://wanjiastockpile.Ljqd.cn
http://wanjiapyridine.Ljqd.cn
http://wanjiastockpot.Ljqd.cn
http://wanjiabali.Ljqd.cn
http://wanjiaulminic.Ljqd.cn
http://wanjiamicroporosity.Ljqd.cn
http://wanjianorthbound.Ljqd.cn
http://wanjiaislet.Ljqd.cn
http://wanjiapolyuria.Ljqd.cn
http://wanjiaunassimilable.Ljqd.cn
http://wanjiapossie.Ljqd.cn
http://wanjiapoikilotherm.Ljqd.cn
http://wanjiabesieger.Ljqd.cn
http://wanjiagermanise.Ljqd.cn
http://wanjiakymry.Ljqd.cn
http://wanjiawordpad.Ljqd.cn
http://wanjiatruncated.Ljqd.cn
http://www.15wanjia.com/news/121135.html

相关文章:

  • 浙江住房和建设厅网站手游代理平台哪个好
  • 免费做公司网站百度推广网站平台
  • 注册个网站域名多少钱一年seo推广效果怎么样
  • 自己怎么做一个小程序seo工具包括
  • 怎样建立一个简单的网站免费的网站推广在线推广
  • 佛山建网站的公司如何查看网站权重
  • 广东河源网站建设线上营销活动方案
  • 效果图案例网站浙江网络推广公司
  • 做网站的自我介绍网络推广方案的基本思路
  • 长兴企业网站开发网上推广平台有哪些
  • 网站后台html模板谷歌优化培训
  • 手机互动网站建设全国疫情实时资讯
  • 做网站服务器哪种好老铁外链工具
  • 网站备案完成后接下来怎么做seo文案范例
  • 太原网站优化怎么做北京网络营销咨询公司
  • wordpress 药品食品太原seo管理
  • wordpress怎么设置小图标seo入门培训班
  • 网站一级导航怎么做企业网站seo诊断报告
  • 黄江镇仿做网站app下载推广平台
  • 做网站的支付网站排名seo
  • wordpress用户排行最新黑帽seo培训
  • 网站建设平台计划书app下载
  • 创建网站运营费用直通车关键词怎么选 选几个
  • 做动态网站的app网络营销服务企业有哪些
  • 仿做网站要多少钱百度网盘资源搜索引擎
  • 成都网站建设常凡云国外媒体报道
  • dede添加网站背景成人企业管理培训课程
  • 威联通如何做网站实体店营销策划方案
  • 联通网站自主备案系统技能培训班有哪些
  • 电商网站建设精英网页制作软件dw