Linux下程序程式替換及簡單的shell的實現
阿新 • • 發佈:2018-12-10
替換原理:
用fork建立程序後執行的是和父程序相同的程式(但有可能執行不同的程式碼分支),子程序往往要呼叫exec函式以執行另一個程式。當程序呼叫一種exec函式時,該程序的使用者空間程式碼和資料完全被新程式替換。從新程序的啟動例程開始執行,呼叫exec函式並不建立新程序,所以呼叫exec函式前後程序的id並未改變。
替換函式:
有六種以exec開頭的函式,統稱exec函式:
#include<unistd.h>
int execl(const char*path,const char*arg)
int execlp(const char*file,const char*arg)
int execle(const char*path,const char*arg,...,char const envp[])
int execv(const char*path,char *const argv[])
int execvp(const char*file,char*const argv[])
int execve(const char*path,char* const argv[],char*const envp[])
這些函式如果呼叫成功則載入新的程式從啟動程式碼開始執行,不再返回。
如果調用出錯則返回-1。
所以exec函式只有出錯的返回值而沒有成功的返回值。
這些函式原型看起來很容易混淆,但只要掌握了規律就很好記。
l(list):表示引數採用列表
v(vector):引數用陣列
p(path):有p自動搜素環境變數path
e(env):表示自己維護的環境變數
事實上只有execve是真正的系統呼叫,其他幾個函式最終都呼叫execve函式。
下面使用exec函式來實現一個簡單的shell
直接上程式碼
1 //模擬shell寫一個咱們自己的微型shell 2 //功能:myshell>ls 3 //能夠執行各種命令 4 #include<stdio.h> 5 #include<unistd.h> 6 #include<stdlib.h> 7 #include<errno.h> 8 #include<string.h> 9 //1.獲取終端輸入 10 //2.解析輸入(按空格解析到一個一個的命令引數) 11 //3.建立一個子程序 12 // 在子程序中經行程式替換,讓子程序執行命令 13 //4.等待子程序執行完畢,收屍,獲取退出狀態碼 14 int argc; 15 char* argv[32]; 16 int param_parse(char *buff) 17 { 18 if(buff==NULL) 19 { 20 return -1; 21 } 22 char*ptr=buff; 23 char*tmp=ptr; 24 while((*ptr)!='\0') 25 { 26 //當遇到空格,並且下一個位置不是空格的時候 27 //將空格位置置‘\0’ 28 //不過我們將使用argv[argc]來儲存這個字串的位置 29 if(*ptr==' '&&*(ptr+1)!=' ') 30 { 31 *ptr='\0'; 32 argv[argc]=tmp; 33 tmp=ptr+1; 34 argc++; 35 } 36 ptr++; 37 } 38 argv[argc++]=tmp; 39 argv[argc]=NULL; 40 } 41 int exec_cmd() 42 { 43 int pid=0; 44 pid=fork(); 45 if(pid<0) 46 { 47 return -1; 48 } 49 else if(pid==0) 50 { 51 execvp(argv[0],argv); 52 exit(0); 53 } 54 //父程序在這裡必須等待子程序退出,來看看子程序為什麼退出了 55 //是不是出現了什麼錯誤,通過獲取狀態嗎,並且轉換一下退出碼所 56 //對應的錯誤資訊進行列印 57 int statu; 58 wait(&statu); 59 //判斷子程序是否是程式碼執行完畢退出 60 if(WIFEXITED(statu)) 61 { 62 //獲取子程序的退出碼,轉換為文字資訊列印 63 printf("%s",strerror(WEXITSTATUS(statu))); 64 } 65 return 0; 66 } 67 int main() 68 { 69 while(1) 70 { 71 printf("myshell>"); 72 char buff[1024]={0}; 73 //%[^\n]獲取資料直到遇到\n為止 74 //%*c 清空緩衝區,資料都不要了 75 scanf("%[^\n]%*c",buff); 76 // printf("%s\n",buff); 77 param_parse(buff); 78 exec_cmd(); 79 } 80 81 }