超简单的SHELL(有纠结的BUG)

    首先增加一个应用程序,即pwd,由于我们的文件系统只有根目录这一个文件夹,所以此应用程序只打印一个“/”。

    在command中建立pwd.c:

Code:
  1. /*  
  2.     By Marcus Xing  
  3.     command/pwd.c  
  4.     pwd命令执行体  
  5. */  
  6.   
  7. /* 函数声明 */  
  8. int Printf(const char *fmt,...);   
  9.   
  10. /*--------------------------------------------------------------------------Main  
  11.     pwd命令执行体,模仿LINUX中pwd命令  
  12. */  
  13. int Main(int argc,char *argv[])   
  14. {   
  15.     Printf("//n");   
  16.     return 0;   
  17. }   

    打入cmd.tar包,运行,出错,原来是cmd.tar已经达到了10K,我们需要改动一个文件占据的扇区数,原来只有10个扇区,忒小了,改为100个吧。。

Code:
  1. #define DEF_FILE_SEC_NUM    100         /* 每个普通文件占用的固定的扇区数量 */  

    还有两处BUG,也是前面遗留的内存空间转换问题,在输入退格键时也有BUG,也改了:

    kernel/tty.c

    TTY_Write函数中:

Code:
  1. p = tty->tty_buf + tty->tty_already_byte_num;   
  2. /* 复制到缓冲区中 */  
  3. Memory_Copy(Virtual_Addr_2_Linear_Addr(tty->tty_user_pid,p),&key,1);  

    TTY_Read函数中:

Code:
  1. u8 *buf = Virtual_Addr_2_Linear_Addr(m->i2,m->p1);  /* 取出要写的数据的缓冲区首址 */  

    下面就是SHELL了,封装成一个函数:

    lib/lib_kernel_in_c.c

Code:
  1. /*-------------------------------------------------------------------------Shell  
  2.     建立一个指定TTY的SHELL  
  3. */  
  4. void Shell(const char *tty_name)   
  5. {   
  6.     int is_word;   
  7.     int tty_read_fd;   
  8.     int tty_write_fd;   
  9.     int argv_index,times;   
  10.     int argc;   
  11.     int read_bytes;   
  12.     int exit_status;   
  13.     char *argv[10];   
  14.     char *p;   
  15.     char *s;   
  16.     char c;   
  17.     char path[MAX_PATH_SIZE];   
  18.     char cmd_buf[80];   
  19.        
  20.     /* 读TTY FD */  
  21.     tty_read_fd = Open(tty_name,O_RDWR);   
  22.     Assert(tty_read_fd != -1);   
  23.        
  24.     /* 写TTY FD */  
  25.     tty_write_fd = Open(tty_name,O_RDWR);   
  26.     Assert(tty_write_fd != -1);   
  27.        
  28.     /* 死循环 */          
  29.     while(1)   
  30.     {   
  31.         is_word = 0;   
  32.         argv_index = times = 0;   
  33.                
  34.         Write_File(tty_write_fd,"$ ",2);   
  35.         read_bytes = Read_File(tty_read_fd,cmd_buf,80); /* 等待用户输入 */  
  36.         cmd_buf[read_bytes] = '/0';   
  37.         argc = 0;   
  38.         p = cmd_buf;   
  39.                
  40.         do  
  41.         {   
  42.             c = *p;   
  43.             /* 读到结束退出 */       
  44.             if(c == '/0')   
  45.             {   
  46.                 break;   
  47.             }   
  48.             /* 表示一个单词的开始 */    
  49.             if((c != '/0') && (c != ' ') && (is_word == 0))   
  50.             {   
  51.                 /* argc赋值 */  
  52.                 if(times == 1)   
  53.                 {   
  54.                     argc = c - '0';   
  55.                 }   
  56.                 /* 第一个单词,即应用程序名 */  
  57.                 else if(times == 0)   
  58.                 {   
  59.                     s = p;   
  60.                 }   
  61.                 /* 否则就是普通的参数 */  
  62.                 else  
  63.                 {   
  64.                     argv[argv_index++] = p;    
  65.                 }   
  66.                 times++;        /* 第几个单词 */  
  67.                 is_word = 1;    /* 在单词之内 */  
  68.             }   
  69.             /* 单词结束 */  
  70.             if(((c == '/0') || (c == ' ')) && is_word)   
  71.             {   
  72.                 *p = '/0';      /* 单词结尾 */  
  73.                 is_word = 0;    /* 单词之外 */  
  74.             }   
  75.             p++;    /* 移动到下一个字符 */  
  76.         }while(1);   
  77.            
  78.         /* 填充path为应用程序路径 */  
  79.         Memory_Set(path,0,MAX_PATH_SIZE);   
  80.         Sprintf(path,"/%s",s);   
  81.            
  82.         argv[argv_index] = 0;   /* 指针数组结尾 */  
  83.            
  84.         /* 打开应用程序文件 */  
  85.         int fd1 = Open(path,O_RDWR);   
  86.         /* 存在 */  
  87.         if(fd1 != -1)   
  88.         {   
  89.             Close(fd1);   
  90.             /* 建立子进程 */  
  91.             pid = Fork();   
  92.             if(pid > 0)   
  93.             {      
  94.                 /* 等待子进程结束 */  
  95.                 pid = Wait(&exit_status);   
  96.                 if(pid != -1)   
  97.                 {   
  98.                     Printf("child proc{%d} exit status is:%d/n",pid,exit_status);   
  99.                 }   
  100.             }   
  101.             else if(pid == 0)   
  102.             {      
  103.                 /* 子进程执行 */  
  104.                 Execv(path,argc,argv);     
  105.             }   
  106.         }   
  107.         /* 不存在 */  
  108.         else  
  109.         {   
  110.             Close(fd1);   
  111.             Printf("COMMAND NOT FOUND!/n");   
  112.         }   
  113.     }   
  114. }   

    修改Proc A进程:

Code:
  1. /*------------------------------------------------------------------------Proc_A  
  2.     进程A的执行体   
  3. */  
  4. void Proc_A()   
  5. {      
  6.     int fd = Open("/cmd.tar",O_CREATE);   
  7.   
  8.     Assert(fd != -1);   
  9.        
  10.     Un_Tar("/cmd.tar");   
  11.        
  12.     int pid = Fork();   
  13.     int ret_status;   
  14.   
  15.     if(pid > 0)   
  16.     {   
  17.         while(1)   
  18.         {   
  19.             pid = Wait(&ret_status);   
  20.             if(pid != -1)   
  21.             {   
  22.                 Printf("child proc{%d} exit status is:%d",pid,ret_status);   
  23.             }   
  24.         }   
  25.     }   
  26.     else if(pid == 0)   
  27.     {   
  28.         Shell("/tty0");   
  29.     }   
  30. }  

    运行结果如下:

    先实验echo命令,接着是pwd命令,最后是个不存在的命令。

    这里之所以成功是因为链接echo和pwd的时候-Ttext参数使用了不同的地址,如果地址一样就出现BUG。

    但是如果使用不同的子进程来装载这两个命令又不会出错。

    找了4天都没个结果。。纠结。。

    马上就考软设了,这个项目就暂时放一放。。还剩最后一章的收尾工作比如安装到真实的机器上和一些扩展比如再增加ls,rm命令。。搞完软设再弄吧。。

    就这样。。晚节不保。。纠结的暂时告一段落。。

   

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值