新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > exec執(zhí)行普通文件和解釋器文件的區(qū)別

exec執(zhí)行普通文件和解釋器文件的區(qū)別

作者: 時(shí)間:2016-09-12 來(lái)源:網(wǎng)絡(luò) 收藏

先解釋兩個(gè)概念;和解釋器。

l :一種文本文件,開頭通常是:#! pathname [option-argument];比較常見的是#! /bin/bash,shell腳本和python腳本都屬于

l 解釋器:解釋器文件第一行中pathname指定的程序,如bash。

3.1 解釋器文件的執(zhí)行

當(dāng)執(zhí)行()解釋器文件時(shí),系統(tǒng)調(diào)用會(huì)識(shí)別這種文件,內(nèi)核使調(diào)用函數(shù)的進(jìn)程實(shí)際執(zhí)行的并不是該解釋器文件,而是pathname指定的解釋器。

我們可以自己寫一個(gè)解釋器,如之前所寫的foo.c:

l foo.c

#include

int

main(int argc,char* argv[])

{

int i;

for(i=0;i

printf(argv[%d]: %sn,i,argv[i]);

exit(0);

}

編譯成為foo然后保存在/mnt/hgfs/VWShared/。

下面我們?cè)谧约簩懸粋€(gè)”解釋器文件”——test:

l test

#!/mnt/hgfs/VWShared/foo

3.1.1 通過(guò)命令行執(zhí)行解釋器文件

直接在命令行中鍵入:”./test”,運(yùn)行test,效果如圖5。

圖5

將test內(nèi)容修改為:#!/mnt/hgfs/VWShared/foo argA argB,再次在命令行運(yùn)行test,效果如圖6。

圖6

通過(guò)這兩個(gè)例子,可以看出命令行運(yùn)行時(shí)當(dāng)執(zhí)行文件是”解釋器文件”時(shí),參數(shù)是如何傳遞給解釋器的:

(1) 通過(guò)執(zhí)行”解釋器文件”執(zhí)行解釋器,傳遞給解釋器的第一個(gè)參數(shù)是解釋器文件的pathname,即解釋器的路徑。

(2) “解釋器文件”中pathname后的可選參數(shù)(這里的argA,argB)如果存在的話會(huì)一起作為第二個(gè)參數(shù)傳遞給解釋器。

(3) “解釋器文件”名稱會(huì)作為下一個(gè)參數(shù)傳遞給解釋器。

3.1.2 通過(guò)execl執(zhí)行解釋器文件

接下來(lái)通過(guò)execl執(zhí)行解釋器文件test,修改main中的exec語(yǔ)句如下:

execl(/mnt/hgfs/VWShared/test,arg1,”arg2”,(char*)0));然后執(zhí)行main,效果如圖7。

圖7

從這個(gè)例子可以了解當(dāng)執(zhí)行文件是解釋器文件時(shí),內(nèi)核如何處理exec函數(shù)的參數(shù)及解釋器文件第一行的可選參數(shù)。我們知道執(zhí)行解釋器文件實(shí)際是執(zhí)行解釋器,由解釋器去讀取解釋器文件中的語(yǔ)句執(zhí)行,而第一行的pathname以#開頭在執(zhí)行時(shí)會(huì)被當(dāng)做注釋忽略。下面就讓我們分析一下最終傳入解釋器foo的參數(shù)都是什么。

(1) argv[0]是該解釋器文件的pathname;

(2) argv[1]是該解釋文件中的可選參數(shù);

(3) argv[2]是解釋器文件本身名字;

(4) argv[3]是execl出入的第二個(gè)參數(shù)(第一個(gè)參數(shù)是arg1)。

那么問(wèn)題出現(xiàn)了,我們傳入execl的arg1去哪里了呢?其實(shí)這就是exec執(zhí)行”解釋器文件”和執(zhí)行一般程序的不同之處:在執(zhí)行一般程序時(shí),execl(const char* pathname,const char* arg0,...,(char*)0)中的arg0會(huì)被當(dāng)做執(zhí)行程序(pathname)的第一個(gè)參數(shù)argv[0],而在執(zhí)行解釋器文件時(shí),內(nèi)核取execl調(diào)用中的pathname而非第一個(gè)參數(shù)(arg0)作為第一個(gè)參數(shù)傳遞給解釋器,因?yàn)橐话愣?,第一個(gè)參數(shù)arg0通常是解釋器文件的名字,而pathname包含了比arg0更多的信息(解釋器文件的完整路徑)。所以當(dāng)execl執(zhí)行解釋器文件時(shí)第一個(gè)參數(shù)arg0是無(wú)效的。

為了說(shuō)明這個(gè)問(wèn)題,我們?cè)倥e一個(gè)例子,編寫python文件pyth.py如下:

l pyth.py:

#! /usr/bin/python

import sys

for i in range(0,len(sys.argv)):

print argv[%d]: %s%(i,sys.argv[i])

它的功能和foo一樣同樣是打印每個(gè)命令行參數(shù)。我們分別將main中的execl語(yǔ)句改為:

execl(/mnt/hgfs/VWShared/foo,arg1,arg2,(char*)0))和

execl(/mnt/hgfs/VWShared/pyth.py,arg1,arg2,(char*)0)),對(duì)比execl一般程序(foo)和解釋器文件(pyth.py)的效果如圖8、9。

圖8.execl(/mnt/hgfs/VWShared/foo,arg1,arg2,(char*)0))結(jié)果

圖9.execl(/mnt/hgfs/VWShared/pyth.py,arg1,arg2,(char*)0))結(jié)果

可以看出execl對(duì)于執(zhí)行和解釋器文件選取第一個(gè)參數(shù)是不同的。

3.2 execl執(zhí)行解釋器文件和命令行執(zhí)行解釋器文件的不同

我們上面已經(jīng)看到execl(/mnt/hgfs/VWShared/pyth.py,arg1,arg2,(char*)0))的結(jié)果(圖9),下面我們?cè)囈幌旅钚蟹绞剑簆yth.py arg1 arg2,結(jié)果圖10:

圖10

可以看到結(jié)果和通過(guò)execl執(zhí)行是有區(qū)別的,通過(guò)命令行執(zhí)行解釋器文件就像通過(guò)命令行執(zhí)行普通程序一樣,程序名稱作為第一個(gè)參數(shù),命令行后面依次作為后續(xù)參數(shù)。正因?yàn)閷?duì)于解釋器文件的execl方式和命令行方式執(zhí)行時(shí)選取第一個(gè)參數(shù)的方式不同,所以對(duì)于解釋器文件a.py:



關(guān)鍵詞: exec 普通文件 解釋器文件

評(píng)論


技術(shù)專區(qū)

關(guān)閉