Linux-簡單的shell實現

當我們在Linux下打開一個終端時,可以通過在上面輸入一些命令,來實現與終端的互動。例如:
這裏寫圖片描述
可以看到,當我們輸入一條命令後,終端會等待下一條命令的輸入。這就類似於一個死循環,不停的輸入命令。
在編寫shell解釋器之前,我們先看一下shell腳本執行過程:
這裏寫圖片描述
fork創建子進程後執行的是和父進程相同的程序(但有可能是不同的代碼分支),子進程調用exec函數以執行另一個程序。此時,該進程的用戶空間代碼和數據完全被新進程替換,從新進程的啓動開始執行。這裏需要注意的是:調用exec函數並不創建新進程,所以調用exec前後該進程的id並未改變。
因此,我們可以通過進程創建和進程替換來實現一個簡單的shell。
需要循環以下過程:
· 獲取命令行
· 解析命令行
· 創建子進程(fork)
· 替換子進程(execvp)
· 父進程等待子進程退出(wait)
具體實現:

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

int main()
{
   char cmd[128];
   char *my_arg[32];

   while(1)
   {
        printf("[myshell#] ");
        fgets(cmd,sizeof(cmd),stdin);//獲取命令行

        pid_t id = fork();//創建子進程
        if(id == 0)//子進程
        {
             cmd[strlen(cmd)-1] = 0;

             char *p = cmd;
             int i = 1;
             my_arg[0] = cmd;
             while(*p)
             {
                  if(isspace(*p))
                  {
                       *p = 0;
                       p++;
                       my_arg[i++] = p;
                  }
                  else
                  { 
                       p++;
                  }
             }
             my_arg[i] = NULL;
             execvp(my_arg[0],my_arg);//進程替換
        }
        else
        {          //父進程
             int status = 0;
             pid_t ret = waitpid(id,&status,0);//父進程等待子進程退出
             if(ret>0)
             {
                    printf("sig: %d,exit code: %d\n",status&0x7F,(status>>8)&0xFF);
             } 
             else
             {
                    printf("waitpid running error\n");
             }
        }
   }
    return 0;
 }

我們在這裏只是實現了一個簡單的shell,不支持管道和重定向。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章