exec執(zhí)行普通文件和解釋器文件的區(qū)別
1. 從一個(gè)問(wèn)題開(kāi)始
本文引用地址:http://m.butianyuan.cn/article/201609/304180.htm首先要從項(xiàng)目中遇到的一個(gè)問(wèn)題說(shuō)起。編寫(xiě)一個(gè)python文件test.py,文件test.py內(nèi)容如下:
#! /usr/bin/python
....
如果在命令行方式執(zhí)行test.py的方式是:
test.py -in inputfile -out outputfile;或python test.py -in inputfile -out outputfile;
但是因?yàn)樾枰?a class="contentlabel" href="http://m.butianyuan.cn/news/listbylabel/label/exec">exec函數(shù)(這里使用execl)去調(diào)用這個(gè)python文件。在項(xiàng)目中是這樣寫(xiě)的:
execl(”test.py”,”-in”,”inputfile”,”-out”,”outputfile”,(char*)0);
但執(zhí)行結(jié)果并不是預(yù)想的test.py執(zhí)行,而是啟動(dòng)了python交互程序,不知道是什么原因。因?yàn)橐恢币詾槿绻麑?xiě)一個(gè)C程序,比如main。那么在命令行輸入:main arg1 arg2執(zhí)行的效果和execl(”main”,”arg1”,”arg2”,(char*)0)的效果應(yīng)該是一樣的。
當(dāng)然同時(shí)伴隨我有另一個(gè)問(wèn)題:
execl(“usr/bin/python”,”test.py”,(char*)0);和輸入命令”/usr/bin/python test.py”有什么區(qū)別?
為了回答些問(wèn)題,自己通過(guò)再反復(fù)看apue和做實(shí)驗(yàn)測(cè)試,終于一點(diǎn)一點(diǎn)明白了,下面就來(lái)一點(diǎn)一點(diǎn)的分析。
2. 命令行執(zhí)行程序和exec執(zhí)行程序的區(qū)別
首先我們來(lái)分析一下在命令行執(zhí)行一個(gè)程序和通過(guò)exec函數(shù)執(zhí)行程序有什么區(qū)別,或者說(shuō)需要注意的地方(一下所有編寫(xiě)的文件都在/mnt/hgfs/VWShared/目錄下)。
編寫(xiě)程序foo.c如下,并編譯為可執(zhí)行文件foo。它打印參數(shù)列表(argv)的所有參數(shù).
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);
}
再編寫(xiě)main.c如下,將其編譯為可執(zhí)行文件main,它使用execl調(diào)用foo。
l main.c
#include
#include
int main(int argc,char* argv[])
{
int n=0;
if( (n=execl(/mnt/hgfs/VWShared/foo,(char*)0))==-1 )
{
perror(execl error);
exit(0);
}
exit(1);
}
直接在命令行下運(yùn)行foo,結(jié)果如圖1:
圖1
運(yùn)行main(通過(guò)execl運(yùn)行foo)結(jié)果如圖2:
圖2
可以看出直接在命令行運(yùn)行foo,則”./foo”被當(dāng)做argv[0],但是通過(guò)exec運(yùn)行foo發(fā)現(xiàn)并沒(méi)有參數(shù)傳入foo(程序沒(méi)有任何輸出),也就是說(shuō)argc值為0。這是什么原因呢?我們知道argv存放的是傳遞給main函數(shù)的命令行參數(shù),當(dāng)在命令行鍵入”./foo”時(shí),唯一的命令行參數(shù)”./foo”就被傳入給main的argv了。所以直接在命令行運(yùn)行foo就打印出唯一的參數(shù)”./foo”。
那么execl的情況呢?首先看一下execl的原型:
int execl(const char* pathname,const char* arg0,.../*(char*)0*/);
注意到了吧,第一個(gè)參數(shù)是要執(zhí)行的程序名,第二個(gè)參數(shù)才是要傳入待執(zhí)行程序的第一個(gè)參數(shù),而上述main.c中沒(méi)有第二個(gè)參數(shù)(這里說(shuō)的是execl的第二個(gè)參數(shù)),也就是沒(méi)有給foo傳遞任何參數(shù),foo的參數(shù)表argv當(dāng)然就是空了,或者說(shuō)argc為0。
通過(guò)這個(gè)例子我們要有以下認(rèn)識(shí):
argv[0]不一定就是所執(zhí)行程序的名稱(chēng),確切的說(shuō)它只是命令行的第一個(gè)參數(shù),只是通常啟動(dòng)程序是在命令行鍵入程序名稱(chēng)啟動(dòng)的,所以程序的名稱(chēng)才成為argv[0]。但是也有情況argv[0]不是程序名稱(chēng)的,如:
(1) 通過(guò)exec執(zhí)行時(shí),argv[0]是什么要視exec的參數(shù)來(lái)定。
例如:我們將main中的execl語(yǔ)句改為:execl(/mnt/hgfs/VWShared/foo,xxxxx,(char*)0);
再運(yùn)行main,效果如圖3:
圖3
可以看到argv[0]變?yōu)榱宋覀儌魅氲膮?shù)”xxxxx”。
(2) 通過(guò)程序別名啟動(dòng)時(shí),argv[0]就是程序的別名。如我們給foo創(chuàng)建一個(gè)軟連接sfoo,然后執(zhí)行sfoo效果如圖4:
圖4
可以看出輸出的argv[0]是./sfoo 而不是./foo,再次證明argv[0]是什么和程序名稱(chēng)無(wú)關(guān),只是和傳入的命令行第一個(gè)參數(shù)有關(guān)。
補(bǔ)充:在創(chuàng)建上述軟連接過(guò)程中遇到了一點(diǎn)小問(wèn)題,不妨也在這里寫(xiě)下來(lái):
【問(wèn)題】
在編譯VMware下的Linux系統(tǒng)對(duì)從Windows中共享過(guò)來(lái)的文件,進(jìn)行編譯的時(shí)候,遇到:ln: creating symbolic link XXXXXX : Operation not supported
【解決辦法】
出現(xiàn)這類(lèi)問(wèn)題,主要是由于在編譯的時(shí)候,要用ln去建立一些軟鏈接,而這些文件是從Windows中,通過(guò)VMWare虛擬機(jī)共享進(jìn)Linux的,而雖然此種操作在Linux系統(tǒng)中很常見(jiàn),但Windows不支持,所以,編譯會(huì)報(bào)錯(cuò)。比較方便的解決辦法是先將文件考到linux的其他目錄,再在其他非共享目錄中創(chuàng)建軟連接。另外還有個(gè)解決辦法就是,在VMWare下的Linux中,建立Samba服務(wù),然后新創(chuàng)建新samba用戶(hù)和文件夾,然后在windows中就可以訪(fǎng)問(wèn)到該文件夾了。然后把在Linux中,從共享目錄拷貝到你所要共享的samba目錄中,這樣,也可以實(shí)現(xiàn)我們所要的文件共享。此時(shí)在去編譯這些代碼的時(shí)候,由于是在Linux系統(tǒng)中的,所以就OK了。
3. 解釋器文件和解釋器
評(píng)論