程序程式替換以及簡易shell的實現
阿新 • • 發佈:2019-02-15
一、程序程式替換
程序程式替換:
程序程式替換過程只是將程式碼和資料替換,並沒有建立新的程序,pid不變。
Linux作業系統中的shell就是運用這個原理處理客戶請求的,不是每個請求都是shell親力親為的,所以shell會建立子程式替換他,在實現shell的過程中我們會用到exec函式,所以我們先了解一下exec函式族並對其每個的用法用程式碼實現一遍。
exec函式家族包括6種:execl、execlp、execle、execv、execvp、execve,如下:
它們有什麼區別呢?
函式名中:
l(list):引數採用列表
v(vector):引數採用陣列
p(path):由p自動搜尋環境變數(path)
e(env):表示自己維護環境變數
所以,各函式的區別如下:
其實,只有execve是真正的系統呼叫,其他五個函式最終都呼叫execve。
二、編寫一個簡易shell 1、看一下簡易shell的編寫 2、瞭解shell的工作過程 時間從左向右,如圖: shell從使用者讀入字串“ls",shell建立一個新的程序,用來執行ls的程式並等待此程序結束。 然後shell讀取新的一行輸入,建立一個新的程序,在這個程序執行程式,並等待其結束。 所以我們知道,要寫一個shell,需要迴圈以下過程: a)獲取命令列 b)解析命令列 c)建立一個子程序(fork) d)替換子程序(execvp) e)父程序等待子程序退出(wait) 實現程式碼:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h> int main(){ char *const argv[]={"ps","-ef",NULL}; char *const envp[]={"PATH=/bin:/usr/bin","TERM=console",NULL}; execl("/bin/ps","ps","-ef",NULL); //帶p,可以使用環境變數PATH,無需寫全路徑 execlp("ps","ps","-ef",NULL); //帶e,需要自己組裝環境變數 execle("ps","ps","-ef",NULL,envp); execv("/bin/ps",argv); //帶p,可以使用環境變數PATH,無需寫全路徑 execvp("ps",argv); //帶e,需要自己組裝環境變數 execve("/bin/ps",argv,envp); exit(0); }
其實,只有execve是真正的系統呼叫,其他五個函式最終都呼叫execve。
二、編寫一個簡易shell 1、看一下簡易shell的編寫 2、瞭解shell的工作過程 時間從左向右,如圖: shell從使用者讀入字串“ls",shell建立一個新的程序,用來執行ls的程式並等待此程序結束。 然後shell讀取新的一行輸入,建立一個新的程序,在這個程序執行程式,並等待其結束。 所以我們知道,要寫一個shell,需要迴圈以下過程: a)獲取命令列 b)解析命令列 c)建立一個子程序(fork) d)替換子程序(execvp) e)父程序等待子程序退出(wait) 實現程式碼:
結果如下:1 #include<unistd.h> 2 #include<sys/wait.h> 3 #include<stdio.h> 4 #include<stdlib.h> 5 #include<string.h> 6 7 char *argv[8]; 8 int argc=0; 9 10 void do_parse(char *buf){ 11 int i; 12 int status=0; 13 14 for(argc=i=0;buf[i];i++){ 15 if(!isspace(buf[i])&&status==0){ 16 argv[argc++]=buf+i; 17 status=1; 18 } 19 else if(isspace(buf[i])){ 20 status=0; 21 buf[i]=0; 22 } 23 } 24 argv[argc]=NULL; 25 } 26 27 void do_execute(void){ 28 pid_t pid=fork(); 29 30 switch(pid){ 31 case -1: 32 perror("fork"); 33 exit(EXIT_FAILURE); 34 break; 35 case 0: 36 execvp(argv[0],argv); 37 perror("execvp"); 38 exit(EXIT_FAILURE); 39 default: 40 { 41 int st; 42 while(wait(&st)!=pid) 43 ; 44 } 45 } 46 } 47 48 int main(){ 49 char buf[1024]={}; 50 while(1){ 51 printf("myshell> "); 52 scanf("%[^\n]%*c",buf); 53 do_parse(buf); 54 do_execute(); 55 } 56 }