1. 程式人生 > >程序程式替換以及簡易shell的實現

程序程式替換以及簡易shell的實現

一、程序程式替換 程序程式替換: 程序程式替換過程只是將程式碼和資料替換,並沒有建立新的程序,pid不變。 Linux作業系統中的shell就是運用這個原理處理客戶請求的,不是每個請求都是shell親力親為的,所以shell會建立子程式替換他,在實現shell的過程中我們會用到exec函式,所以我們先了解一下exec函式族並對其每個的用法用程式碼實現一遍。 exec函式家族包括6種:execlexeclpexecleexecvexecvpexecve,如下: 它們有什麼區別呢? 函式名中: l(list):引數採用列表 v(vector):引數採用陣列 p(path):由p自動搜尋環境變數(path) e(env):表示自己維護環境變數 所以,各函式的區別如下:

這些函式如果呼叫成功,則載入新的程式從啟動程式碼開始執行,不再返回; 如果調用出錯則返回-1; 也就是說exec函式只有出錯返回值,沒有成功返回值。 exec函式應用舉例:
#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 }                                                     
結果如下: