Linux---制作简易shell

考虑下面这个与shell典型的互动:
在这里插入图片描述

用下图的时间轴来表示事件的发生次序。其中时间从左向右。shell由标识为sh的方块代表,它随着时间的流逝从左向右移动。shell从用户读入字符串"ls"。shell建立一个新的进程,然后在那个进程中运行ls程序并等待那个进程结束。
在这里插入图片描述
然后shell读取新的一行输入,建立一个新的进程,在这个进程中运行程序并等待这个进程结束。所以要写一个shell,需要循环以下过程:

1.打印命令提示符[用户名@主机名 当前目录] 提示符(对于普通用户$,对于root用户显示#)
2. 解析命令行
3. 建立一个子进程(fork)
4. 替换子进程(execvp)
5. 父进程等待子进程退出(wait)

根据这些思路,和我们前面的学的技术,就可以自己来实现一个shell了。

 #include<stdio.h>                                                                                                                                                                     
 #include<string.h>
 #include<stdlib.h>
 #include<unistd.h>
 #define SIZE 256
 #define NUM 16
int main()
 {
    
    
   //命令行的获取
   char cmd[SIZE];
   //这里是可以通过查看系统调用接口来获取这里的用户名、主机名、和当前目录的,但是这里省略了,在后续需要补充
   const char* cmd_line = "[temp@VM-8-3-centos lesson_15]# ";
   while(1){
    
    
     cmd[0] = 0; //对于字符串来说以'\0'结束,把第一个位置设置为'\0',其余的就都是了
     printf("%s",cmd_line);
     //char *fgets(char *s,int size,FILE * stream);//获得一个字符串,放到缓冲区;这个缓冲区有多大;从哪里流方式获得
     fgets(cmd,SIZE,stdin);
     cmd[strlen(cmd)-1] = '\0';//因为你的fgets在获取字符串的时候,最后将回车敲下之后补了'\0'结束,所以你的字符串的最后是以n\0结束的
    //命令行解析 strtok() 把命令行拆解为多个字符串,然后把每个字符串放在一个对于的字符指针数组里面,那么访问这个数组的下标就可以拿到对应的命令行内容
    char *args[NUM];
 
     args[0] = strtok(cmd," ");
     int i = 1;
     do{
    
    
         args[i] = strtok(NULL," ");
         if(args[i] == NULL){
    
    
           break;
         }
         ++i;
     }while(1);
 
      //创建子进程
     pid_t id = fork();
     if(id < 0){
    
    
       perror("fork error\n");
       continue;
     }
 
     if(id == 0){
    
    
       //child
       execvp(args[0],args);
       //只要子进程替换失败,就直接让它退出
       exit(1);
     }
     
     //parent
     int status = 0;
     pid_t ret = waitpid(id,&status,0);
     if(ret > 0 ){
    
    
       printf("status exit code : %d\n",(status>>8)&0xff);
     }
   }  
   return 0;
 }                                                       

在这里插入图片描述
系统调用获取用户名 、主机名、和当前目录
可以查阅CSDN的centos7如何得到“系统调用获取用户名 、主机名、和当前目录”,目前这里没有找到很好的链接。
需要补充的知识点:
char *fgets(char *s,int size,FILE * stream);
获得一个字符串,放到缓冲区;这个缓冲区有多大;从哪种流方式获得
①fgets()函数
cmd[strlen(cmd)-1] = '\0';这句,对于你的命令行来说,你按下回车键作为了结束,但是你的命令行将他识别为了’\n’,所以你的cmd中存储的字符串最终是‘\n\0’结尾的,所以这里你在调用的时候就需要用ls ‘- -’(两个’-‘来执行命令),所以为了避免这样,就把最后一个’\n’的地方替换为’\0’就好了
③strtok字符串函数
字符串详解链接: link.
④continue:再循环体中会跳过剩下的语句,而直接回到最初重新进行程序的判断,break是直接跳出循环体,不再执行

猜你喜欢

转载自blog.csdn.net/MEANSWER/article/details/115078772