【Linux】模拟实现一个简单的minishell

【Linux】模拟实现一个简单的minishell_第1张图片


目录

从显示屏获取输入字符流

分割字符串 取出命令名称及选项

去除输入时多按的那个换行符

创建子进程,实现程序替换

如果替换失败,进程终止exit

查看子进程情况

实现echo $?功能

实现cd

最终代码


基本思路 让父进程创建一个子进程,由这个子进程进行程序替换。父进程要对这个进程进行追踪、回收。具体实现模块如下:


从显示屏获取输入字符流

【Linux】模拟实现一个简单的minishell_第2张图片

【Linux】模拟实现一个简单的minishell_第3张图片

 char* s=fgets(buffer,sizeof (buffer)-1,stdin);
    assert(s!=NULL);
    buffer[strlen (buffer)-1]=0;
    (void*)s;

分割字符串 取出命令名称及选项

【Linux】模拟实现一个简单的minishell_第4张图片

//切割字符串
    myargv[0]=strtok(buffer," ");
    int i=0;

    if(myargv[0] != NULL && strcmp(myargv[0], "ls") == 0)
    {
      myargv[++i] = (char*)"--color=auto";
    }

    while(myargv[i]!=NULL)
    {
      myargv[++i]=strtok(NULL," ");
    }

创建子进程,实现程序替换

【Linux】模拟实现一个简单的minishell_第5张图片

pid_t id =fork();
    if(id==0)
    {
      //子进程
      //程序替换
      execvp(myargv[0],myargv); 
      //如果走到这里表示替换失败
      exit(1);
    }

查看子进程情况

【Linux】模拟实现一个简单的minishell_第6张图片

//父进程
   int status=0;
   pid_t ret= waitpid(id,&status,0);
   assert(ret > 0);
   (void)ret;
   quitcode=(status>>8)&0XFF;
   quitsignal= (status & 0x7F);

实现echo $?功能

【Linux】模拟实现一个简单的minishell_第7张图片

【Linux】模拟实现一个简单的minishell_第8张图片

 //实现echo $?功能
    if(myargv[0]!=NULL&&myargv[1]!=NULL&&strcmp(myargv[0],"echo")==0)
    {
      if(strcmp(myargv[1],"$?")==0)
      {
        //输出上一个进程的退出码
        printf("退出码为:%d\n",quitcode);

      }
      else
      {
        printf("%s\n",myargv[1]);
      }
      continue;

    }

实现cd

【Linux】模拟实现一个简单的minishell_第9张图片

 //实现cd功能
    if(myargv[0] != NULL &&strcmp(myargv[0],"cd")==0)
    {
      if(myargv[1]!=NULL)
      {

        chdir(myargv[1]);
      }
      continue;
    }

最终代码

#include
#include
#include
#include
#include
#include
#include


#define B_NUM 1024
#define ARGV_NUM 10

char buffer[B_NUM];
char* myargv[ARGV_NUM];
int quitcode;
int quitsignal;


int main()
{
  while(1)
  {
    printf("【用户名@服务器 当前目录】$");
    fflush(stdout);

    char* s=fgets(buffer,sizeof (buffer)-1,stdin);
    assert(s!=NULL);
    buffer[strlen (buffer)-1]=0;
    (void*)s;
   
    //切割字符串
    myargv[0]=strtok(buffer," ");
    int i=0;

    if(myargv[0] != NULL && strcmp(myargv[0], "ls") == 0)
    {
      myargv[++i] = (char*)"--color=auto";
    }

    while(myargv[i]!=NULL)
    {
      myargv[++i]=strtok(NULL," ");
    }

    //实现cd功能
    if(myargv[0] != NULL &&strcmp(myargv[0],"cd")==0)
    {
      if(myargv[1]!=NULL)
      {

        chdir(myargv[1]);
      }
      continue;
    }
    //实现echo $?功能
    if(myargv[0]!=NULL&&myargv[1]!=NULL&&strcmp(myargv[0],"echo")==0)
    {
      if(strcmp(myargv[1],"$?")==0)
      {
        //输出上一个进程的退出码
        printf("退出码为:%d\n",quitcode);

      }
      else
      {
        printf("%s\n",myargv[1]);
      }
      continue;

    }

    pid_t id =fork();
    if(id==0)
    {
      //子进程
      //程序替换
      execvp(myargv[0],myargv); 
      //如果走到这里表示替换失败
      exit(1);
    }

   //父进程
   int status=0;
   pid_t ret= waitpid(id,&status,0);
   assert(ret > 0);
   (void)ret;
   quitcode=(status>>8)&0XFF;
   quitsignal= (status & 0x7F);

  }
  return 0;
}

最后

加油

【Linux】模拟实现一个简单的minishell_第10张图片

你可能感兴趣的:(Linux的蜕变之路,linux,学习,shell,程序替换,进程)