實驗一 實現帶參數的簡單shell

來源:互聯網
上載者:User

實驗一 實現帶參數的簡單shell

 

1、   實驗名稱,實驗編號和具體名稱

實驗一利用課本第9頁程式1-5的架構,實現帶參數的簡單shell,實現允許輸入命令帶參數的簡單shell。原來的實現是不能夠帶參數的。輸入命令所能帶的參數個數,只受到系統鍵盤輸入緩衝區長度(以及shell輸入緩衝區長度)的限制,該緩衝區的預設長度是4096個位元組。

2、   實驗內容描述

1.    正確理解並使用系統調用fork(),execve()和waitpid(),特別是execve()函數。

fork()函數建立一個新的進程。新進程就是所謂的子進程,它是執行fork()函數的進程(父進程)的“複製”,也就是說,子進程執行的程式與父進程的完全一樣。當fork()函數傳回值為0時表示處於子進程中;而傳回值大於0時表示處於父進程中,此時的傳回值是子進程的進程id。因此,fork()的傳回值可以用來劃分僅僅適合父進程和子進程執行的程式段。fork()函數傳回值為-1時表示出錯。

 

如果子進程只是運行與父進程完全一樣的程式,那用處是很有限的。要讓子進程運行不同於父進程的程式,就必須調用execve函數,它是所有其他exec函數的基礎。execve函數把調用它的進程的程式,替換成execve函數的參數所指定的程式。運行execve函數成功後,進程將開始運行新的程式,也就是execve函數的參數所指定的程式。

execve函數原型:int execve(const char *path, const char*argv[],const char *envp[]);

其中:

path:要執行的程式路徑名,比如“/bin/ls”,“cd”,“/usr/bin/gcc”等等。

argv:參數表,比如ls命令中可帶的命令列參數-l,-a等。注意,argv的第一個元素必須是要執行的程式(命令)的路徑名。

envp:環境變數表,供要執行的命令使用。實參數用NULL或系統內容變數environ均可。注意,因為environ由系統提供,屬於外部變數,所以說明時必須用“extern”修飾。

例子:

char *argv[] ={“gcc”, “-g”, “-c”, “hello.c”, NULL};

char *argv1[] = {“/bin/ls”,“-l”, “-a”, NULL};

execve(“/usr/bin/gcc”,argv, environ);      // 編譯器“hello.c”

execve(“/bin/ls”,argv1, NULL);            // 執行命令“ls –l –a”

execve(“/usr/ls”, argv1, NULL);            // 出錯,因為目錄/usr/下沒有ls程式。

// 注意,在argv1 的第一個字串“/bin/ls”中,只有ls是有用的。

 

系統調用waitpid()用於等待子進程結束、擷取子進程的運行狀態,詳細說明在第八章。本實驗僅僅用它使父進程等待子進程結束,因此維持程式1-5的用法即可。

 

(2)根據簡單shell的輸入,構造execve函數的參數。

根據程式1-5,數組buf儲存使用者的輸入,包括命令和參數。由於shell命令的命令名和各參數之間是用空格分開,因此可以用空格作為分界符。通過一個迴圈可以把buf數組中的命令和各個參數依次分離開來,並賦給數組argv的各元素適當的指標值。argv數組的最後一個指標必須是NULL。接著就可以調用execve(argv[0],argv, environ)來執行使用者輸入的命令。

 

提示:argv數組中各指標所指向的字串,可以直接利用buf的儲存空間,不需要另外分配記憶體。

3、設計和實現的主要原理、構思、演算法、執行過程或技巧,必要的注釋和說明。

 

#include "apue.h"

#include <sys/wait.h>

#include <unistd.h>

int main()

{

       charbuf[MAXLINE];

       char*envp[]={"PATH=/bin",NULL};

       char *argv[]={NULL};

       charstr[4096][256];

       inti,j,k,m,status;

       pid_t pid;

       char path[256];

       printf("%%");

       while(fgets(buf,MAXLINE,stdin)!=NULL){

              memset(path,0,sizeof(path));//初始化

              if(buf[strlen(buf)-1]=='\n')

                     buf[strlen(buf)-1]=0;

              j=i=k=0;

              while(buf[j]!='\0'){

                     if(buf[j]!='') {

                            for(i=j;buf[i]!=''&&buf[i]!='\0';i++)

                                   str[k][i-j]=buf[i];

                            str[k][i-j]='\0';

                            k++;

                            j=i;

                     }else {

                            j++;

                     }

              }

              for(i=0;i<k;i++)

                     argv[i]=str[i];

              argv[k]=NULL;

              strcat(path,argv[0]);

              if((pid=fork())<0){

                     err_sys("forkerror");

              } elseif(pid==0) {

                     execve(path,argv,envp);

                     err_ret("couldn'texecute:%s",argv[0]);

                     exit(127);

              }

              if((pid=waitpid(pid,&status,0))<0)

                     err_sys("waitpiderror");

              printf("%%");

       }

       exit(0);

}

 

3、   實驗結果

實現了常用指令如/bin/ls,/usr/bin/gcc, 輸入錯誤命令能提示出錯並進入下一輪接收命令狀態。可以用Ctrl-C和Ctrl-\結束簡單shell的運行.

來源程式名: prg1.c

可執行程式名:prg1

編譯方法:gcc prg1.c error.c –o prg1

運行樣本:./prg1

                     /bin/ls -l

 

如:

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.