Ubuntu下Shell的簡單實現(C語言)


    最近在操作系統的實驗課上要求在Linux下實現Shell的簡單功能,做了實驗感覺挺有收獲的,就在這分享一下,歡迎指出問題。

  廢話不多說,先看main()函數。

 1 int main()  
 2 {  
 3     char inputBuffer[MAXLINE];  
 4     char *argv[MAXLINE/2 - 1];  
 5   
 6     while (1)  
 7     {  
 8         printf("COMMAND->");  
 9         fgets(inputBuffer,80,stdin); 
10         setup(inputBuffer, argv);  
11   
12     }  
13     return 0;  
14 }

 

    main函數中,通過fgets(inputBuffer,80,stdin)函數獲得用戶的輸入,並通過setup(inputBuffer,argv)函數分割輸入的字串,將命令語句和參數分別提取出來。這里用到了fgets()函數,說一下用fgets(inputBuffer,80,stdin)、gets(inputBuffer)的不同,這會影響到接下來setup函數的寫法。

    gets()函數用來從標准輸入設備(鍵盤)讀取字符串直到換行符結束,但換行符會被丟棄,然后在末尾添加'\0'字符。注意在c中需要加頭文件#include<string.h>,在c++中不需要。

    fgets函數用來從文件中讀入字符串。fgets函數的調用形式如下:fgets(str,n,fp);此處,fp是文件指針;str是存放在字符串的起始地址;n是一個int類型變量。函數的功能是從fp所指文件中讀入n-1個字符放入str為起始地址的空間內;如果在未讀滿n-1個字符之時,已讀到一個換行符或一個EOF(文件結束標志),則結束本次讀操作,讀入的字符串中最后包含讀到的換行符。因此,確切地說,調用fgets函數時,最多只能讀入n-1個字符。讀入結束后,系統將自動在最后加'\0',並以str作為函數值返回。

    也就是說我們在輸入命令行,例如“ls”的時候,輸入完之后會按下一個回車執行,用gets的話,那么存在inputBuffer中的字符串為“ls\0”換行符是要被丟棄的,但是如果使用fget函數的話,那么讀取的字符串為“ls\n\0”,換行符是不會被丟棄的,這一點一定要注意。

    接下來看fget函數:

 1 //p是一個全局char型指針char *p
 2 void setup(char inputBuffer[], char *argv[])  
 3 {  
 4     int i, j;  
 5     i = 0;  
 6     for(p = inputBuffer;*p!='\0' ;p++)//輸入字符分開
 7     {  
 8         argv[i++] = p; 
 9         while(*p != ' ' && *p != '\0' && *p != '\n')  
10             p++;  
11 
12         *p = '\0';  
13     }  
14     argv[i] = NULL;//參數要以NULL為結尾
15 
16     pid_t pid;
17     pid = fork();//創建子進程
18 
19     if(pid == 0)//子進程對輸入命令操作
20     {  
21              execvp(argv[0], argv);     
22         printf("command error\n");//execvp返回-1,執行失敗,命令有錯誤
23     }  
24   
25     else if( pid > 0 )//父進程
26     {  
27      wait(NULL);//父進程等待子進程結束,回收子進程  
28     }  
29   
30     else  
31     {  
32      printf("fork error\n");  
33     }  
34 }

     execve()用來執行參數filename字符串所代表的文件路徑,第二個參數是利用數組指針來傳遞給執行文件,並且必須以空指針(NULL)結束,最后一個參數則為傳遞給執行文件的新環境變量數組。

     因此首先將命令行和參數分隔開來,分別傳入execve函數中去執行,但是要注意的是獲取用戶的字符串輸入用的是fgets,那么在最后肯定是有一個換行符的,如果不舍棄掉這個換行符的話,例如輸入的是'ls'命令,那么傳入arg[0]指向'ls'的首地址,arg[1]指向\0',argv[2]指向'NULL',execve函數在執行到arg[1]的時候便會停止,沒有執行到NULL,會報錯,因此在使用fgets函數的時候要舍棄掉最后的一個換行符。

     execvp如果執行成功則函數不會返回,執行失敗則直接返回-1,失敗原因存於errno中。由於執行成功了,這個進程就結束了,也代表這個程序也完了,所以它不會返回至主程序,這就是要創建子進程的原因,執行命令在子進程中,父進程負責函數的返回。

參考文章:http://blog.csdn.net/lishuhuakai/article/details/11928055


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM