模拟实现迷你shell、系统文件I/O

1.模拟实现shell

1.1思路

1.我们的shell需要展示当前用户、主机、当前目录、等命令行提示符
我们知道,shell中命令行提示符一直在显示的,因此需要一个while循环来控制,即每次进程开始都需要打印这一串字符串

2.需要能够获取命令行
获取命令,可以建立一个字符数来存储命令行,通过fgets来从标准输入获取
需要注意的是fgets会将最后一个换行符带入字符数组中,这里需要进行处理
同时通过strtok将输入的字符串分解成标准的命令模式,使用strtok可以避免自己去处理多个连续空格的问题

3.需要能够解析执行命令行
由于命令行是可以持续输入的,因此我们将命令行解析之后,需要创建子进程来进行命令行的执行
通过调用替换函数来完成命令行的解析执行工作

4.需要获取命令实现状态
父进程通过waitpid以阻塞的方式来获取子进程的执行状态

1.2实现代码、效果展示

在这里插入图片描述

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h> 
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define SIZE 128

void Redirect(char *str)
{
  int count=0;//计数器
  char *file=NULL;//保存文件名

  while(*str)//不为\0
  {
    if(*str=='>')
    {
      *str='\0';
      str++;//往后挪动一步
      count++;

      if(*str=='>')//追加重定向
      {
        *str='\0';//将>重置为\0,避免对后面的命令解析产生干扰
        str++;
        count++;
      }      

      //文件名获取
      while(*str!='\0'&&*str==' ')//是空格,则往后移动,找到文件名为止
      {
        str++;
      }
      file=str;//得到文件名
      while(*str!='\0'&&*str!=' ')//防止后面带多个空格
      {
        str++;
      }
      *str='\0';
        
      //重定向
      int fd=0;
      if(1==count)
      {
        fd=open(file,O_CREAT |O_TRUNC | O_WRONLY,0644);
      }
      else if(2==count)
      {
         fd=open(file,O_CREAT | O_WRONLY | O_APPEND,0644);
      }
      dup2(fd,1);
      close(fd);
    }
    
    else if(*str=='<')
    {
      *str='\0';
      str++;//往后挪动一步

      //文件名获取
      while(*str!='\0'&&*str==' ')//是空格,则往后移动,找到文件名为止
      {
        str++;
      }
      file=str;//得到文件名
      while(*str!='\0'&&*str!=' ')//防止后面带多个空格
      {
        str++;
      }
      *str='\0';
        
      //重定向
      int fd=open(file,O_RDONLY);

      dup2(fd,0);
      close(fd);
    }

    else
      str++;
  }
}

int main()
{
 char str[SIZE]={0};
  while(1)
  {
    printf("[myshell@VM-0-6-centos Shell]* ");//命令行提示

     str[0]=0;//字符数组清空,字符串/0结尾,因此第一个值为0就是清空
    
    fgets(str,SIZE,stdin);//从标准输入获取字符串

    str[strlen(str)-1]='\0';//fgets会将\n带入

  char *args[SIZE]={0};//将命令解析出来


 pid_t id=fork();

    if(id<0)
    {
      perror("fork error\n"); 
    }
    
    if(id==0)//child
    {
      Redirect(str);
       
       args[0]=strtok(str," ");//以空格为分隔符解析出来
       
       int sub=1;
       do
       {
         args[sub]=strtok(NULL," ");
         if(!args[sub])
           break;//解析完毕
         sub++;
       }while(1);
    
      execvp(args[0],args);
      //调用失败
      printf("comman not found\n");
      exit(1);
  }


    //父进程不用判定,子进程调用替换函数后就被替换掉了  
    int st;
    waitpid(id,&st,0);//以阻塞的方式等待;
    printf("status_code:%d\n",st>>8&&0xff);//打印子进程状态码
  }

return 0;
}

1.3应用迷你shell

在这里插入图片描述

1.4总结

shell的本质是一个进程,这个进程在获取指令,分析指令,创建子进程执行指令
我们登录shell经过验证之后,系统就给我们创建了一个对应的进程,输出命令行提示符

经过迷你shell 的实现,可以清楚的知道,我们的进程可以fork另外一个进程,并且给他一些参数,被调用的进程来执行一些任务,该进程执行失败与否不会影响到父进程,并且父进程可以获取到子进程执行任务的状态
我们的shell本质就是这样,通过创建子进程来完成执行任务,假使任务失败或者输入无效的命令也不会导致父进程的奔溃

2.系统文件I/O接口介绍

2.1为什么默认打开三个输入输出流

不论是什么语言都会默认打开三个输入输出流,即stdin(默认输入、对应键盘),stdout(默认输出、对应显示器),stderr(标准错误、对应显示器)

首先我们的语言是人和计算机交互的工具,交互就需要有信息的传递,而三个输入输出流就是交互的最低保证,我们通过键盘输入信息给计算机,计算机通过显示器将信息传送给操作者,完成信息的交互工作

2.2接口介绍

所有的I/O操作都是和硬件进行交互,硬件是不能直接进行操控的,我们需要通过操作系统来操控硬件,方式是通过调用操作系统提供的接口来进行调用
因此一些语言的I/O操作库函数其实就是以系统调用接口为基础进行封装而成的,呈现出上下级的形式。比如我们上面调用的都是库函数,这些函数都是在系统调用的基础上进行封装而成,接下来,介绍一下系统I/O的一些基本接口

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

3.文件描述符fd

3.1文件描述符是什么

文件描述符就是调用open时候的返回值,如果创建成功这个返回值大于零,如果创建失败则返回-1
在这里插入图片描述
在这里插入图片描述

3.2文件描述符分配规则

对进程来讲默认从3开始分配描述符,因为有三个默认打开的标准输入输出流,如果关闭了,会从最小的没有被分配的开始分配

在这里插入图片描述

3.3如何理解Linux下一切皆文件

在这里插入图片描述

3.4进程是怎样找到文件的

在这里插入图片描述

3.5扩展——面向对象语言的产生

在这里插入图片描述

4.重定向

4.1什么是重定向

把本应该显示到显示器上面的内容,写到了文件里面这种就叫做文件重定向
> 跟的是文件名,子进程先把1关掉,再将文件打开,然后写入内容
在这里插入图片描述
在这里插入图片描述

4.2重定向原理

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值