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

20165322 第七週 mybash 的實現

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("[%
[email protected]
%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”等等……