1. 程式人生 > >20165322 第七周 mybash 的實現

20165322 第七周 mybash 的實現

全部 pwd 狀態 order 測試 pty 根據 部分 str

mybash的實現

要求

  • 使用fork,exec,wait實現mybash
  • 寫出偽代碼,產品代碼和測試代碼
  • 發表知識理解,實現過程和問題解決的博客

相關函數的作用

  • fork
    • fork()函數通過系統調用創建一個與原來進程(父進程)幾乎完全相同的進程(子進程是父進程的副本,它將獲得父進程數據空間、堆、棧等資源的副本。註意,子進程持有的是上述存儲空間的“副本”,這意味著父子進程不共享這些存儲空間。linux將復制父進程的地址空間內容給子進程,因此,子進程由了獨立的地址空間。),也就是這兩個進程做完全相同的事。
    • 在父進程中,fork返回新創建子進程的進程ID;
    • 在子進程中,fork返回0;
    • 如果出現錯誤,fork返回一個負值
      技術分享圖片
  • exec
    • exec函數族可以根據指定的文件名或目錄名找到可執行文件,並用它來取代原調用進程的數據段、代碼段和堆棧段。在執行完後,原調用進程的內容除了進程號外,其它全部被新程序的內容替換了。另外,這裏的可執行文件既可以是二進制文件,也可以是Linux下任何可執行腳本文件。
      技術分享圖片
  • wait
    • wait()會暫時停止現在進程的執行,直到有信號來到或子進程結束。假如在調用wait()時子進程已結束,則wait()會立即返回子進程結束狀態值。
      技術分享圖片

偽代碼

while(1)
{
    輸出用戶信息
    讀取用戶輸入命令存入數組和文件
    調用fork()函數,若返回值不為0,則調用wait()
    若返回值為0,調用exec()
}

產品代碼

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/wait.h>
#define N 100
#define order_length 128
#define order_num 64
#define empty 0
#define chars 1
void main()
{ 
   while(1) {
    struct passwd *my_info;
    char path[N];
    my_info = getpwuid(getuid());
    getcwd(path, sizeof(path));
    printf("[%s@%s]$ ", my_info->pw_name, path);//輸出用戶及路徑

    char str[N];
    char a[N];
    char *argv[N]={NULL};
    char *envp[]={0,NULL};
        int i,j = 0, flag=1;
    fgets(str,N,stdin);  //讀取輸入的命令
    str[N - 1] = ‘\0‘;
    if(feof(stdin))
        {
            printf("error");
            exit(0);
        }
    for(i=0;str[i]!=‘\0‘&&i<N&&j<N;i++) {
        if(str[i] == ‘ ‘ || str[i] == ‘\n‘) {
          flag=1;
          str[i] = ‘\0‘;
      }
      else if(flag==1) {
          argv[j++] = &str[i];
          flag=0;
      }
     }
     if(fork() != 0) wait(NULL);   //調用fork()
        else {
    execvp(argv[0], argv);
    perror("execlp error");
    exit(0);
     }
 }
}

測試結果

測試了ls,ls -l``tree``clear指令,測試截圖如下:
技術分享圖片

尚有一部分命令無法實現,例如“cd”等等……

20165322 第七周 mybash 的實現