linux解釋器原理—— unix環境高級編程

轉自:http://blog.csdn.net/qiqijianglu/article/details/8495771

 linux解釋器原理


對於會shell編程的人肯定不會對#!/bin/sh感到陌生。這一行字符串到底意味着什麼呢?
應該明確,所謂解釋器就是指#!行後面的可執行程序。
 
我們從exec函數說起。
exec函數總共包括六個函數。
#include <unistd.h>
int execl(const char *pathname,const char *arg0,.../*(char *)0 */);
int execv(const char *pathname,char *const argv[]);
int execle(const char *pathname,const char *arg0,.../*(char *)0,char *const envp[] */);
int execve(const char *pathname,char *const argv[],char *const envp[]);
int execlp(const char *filename,const char *arg0,.../*(char *)0 */);
int execvp(const char *filename,char *const argv[]);
 
這些函數作用都是一樣:執行一段新的代碼。
其中execl函數,第一個參數path是設置了執行位的可執行文件的路徑,後面的可變參數列表分別指向了傳遞給此執行文件的參數列表,(包括了參數0,即是執行文件的名稱),最後一個參數(char *)0則表示參數列表結束。
對於解釋器,exec函數(以execl爲例)是這樣執行的,如果path是指向了一個腳本,腳本的第一行是以#!開頭,則這樣調用:
以#!後面的字符串爲命令,後面加上execl參數列表指定的參數,這樣就形成了新的程序的執行。
 
以下是unix高級環境編程中關於解釋器文件的例子。
首先我們在/home/qiqijianglu下創建一個解釋器文本:
文本的名字爲testinterp
文本里的內容如下:
#!/home/qiqijianglu/echoarg foo
----------------------------------------------------------------------------
分隔線及分隔線以下不是文本里的內容,echoarg程序內容如下:
#include "apue.h"
int main(int argc,char *argv[])
{
    int i;
    for(i=0;i<argc;i++)
    printf("argv[%d]: %s\n",i,argv[i]);
   exit(0);
}
-------------------------------------------------------------------------------
那麼echoarg就是一個解釋器,它回送每一個命令行參數。
下面我們要編寫一個執行一個解釋器文件的程序,文件名爲197.c,代碼如下:
#include "apue.h"
#include <sys/wait.h>
int main(void)
{
     pid_t pid;
     if((pid=fork())<0)
     err_sys("fork error");
     else if(pid==0)
    {
        if(execl("/home/qiqijianglu/testinterp","testinterp","myarg1","MY ARG2",(char *)0)<0)
       err_sys("execl error");
    }
   if(waitpid(pid,NULL,0)<0)
   err_sys("waitpid error");
   exit(0);
}
---------------------------------------------------------------------------------------------------
這樣我們用命令cc 197.c編譯197.c,然後運行該程序./a.out
argv[0]: /home/qiqijianglu/echoarg
argv[1]: foo
argv[2]: /home/qiqijianglu/testinterp
argv[3]: myargl
argv[4]: MY ARG2
 
 
execl是這樣執行命令的:
/home/qiqijianglu/testinterp的內容是#!/home/qiqijianglu/echoarg foo則#!後面的字符串/home/qiqijianglu/echoarg foo加上命令行參數列表組成了新的程序行/home/qiqijianglu/echoarg foo /home/qiqijianglu/testinterp myargl MY ARG2
注意,內核取execl調用中的pathname而非第一個參數testinterp,因爲一般而言,pathname包含了比第一個參數更多的信息。
對於testinterp腳本,我們在shell中調用它時,shell會調用fork,exec,wait來執行它,首先,exec函數對#!行分析後得出此腳本的解釋器爲/home/qiqijianglu/echoarg,然後就把命令行處理成了/home/qiqijianglu/echoarg foo ./testinterp
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章