1. 從一個問題開始
本文引用地址:http://www.eepw.com.cn/article/201609/304180.htm首先要從項目中遇到的一個問題說起。編寫一個python文件test.py,文件test.py內容如下:
#! /usr/bin/python
....
如果在命令行方式執行test.py的方式是:
test.py -in inputfile -out outputfile;或python test.py -in inputfile -out outputfile;
但是因為需要,用exec函數(這裡使用execl)去調用這個python文件。在項目中是這樣寫的:
execl(」test.py」,」-in」,」inputfile」,」-out」,」outputfile」,(char*)0);
但執行結果並不是預想的test.py執行,而是啟動了python交互程序,不知道是什麼原因。因為一直以為如果寫一個C程序,比如main。那麼在命令行輸入:main arg1 arg2執行的效果和execl(」main」,」arg1」,」arg2」,(char*)0)的效果應該是一樣的。
當然同時伴隨我有另一個問題:
execl(「usr/bin/python」,」test.py」,(char*)0);和輸入命令」/usr/bin/python test.py」有什麼區別?
為了回答些問題,自己通過再反覆看apue和做實驗測試,終於一點一點明白了,下面就來一點一點的分析。
2. 命令行執行程序和exec執行程序的區別
首先我們來分析一下在命令行執行一個程序和通過exec函數執行程序有什麼區別,或者說需要注意的地方(一下所有編寫的文件都在/mnt/hgfs/VWShared/目錄下)。
編寫程序foo.c如下,並編譯為可執行文件foo。它列印參數列表(argv)的所有參數.
l foo.c
#include
int
main(int argc,char* argv[])
{
int i;
for(i=0;i
printf(argv[%d]: %s\n,i,argv[i]);
exit(0);
}
再編寫main.c如下,將其編譯為可執行文件main,它使用execl調用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);
}
直接在命令行下運行foo,結果如圖1:
圖1
運行main(通過execl運行foo)結果如圖2:
圖2
可以看出直接在命令行運行foo,則」./foo」被當做argv[0],但是通過exec運行foo發現並沒有參數傳入foo(程序沒有任何輸出),也就是說argc值為0。這是什麼原因呢?我們知道argv存放的是傳遞給main函數的命令行參數,當在命令行鍵入」./foo」時,唯一的命令行參數」./foo」就被傳入給main的argv了。所以直接在命令行運行foo就列印出唯一的參數」./foo」。
那麼execl的情況呢?首先看一下execl的原型:
int execl(const char* pathname,const char* arg0,.../*(char*)0*/);
注意到了吧,第一個參數是要執行的程序名,第二個參數才是要傳入待執行程序的第一個參數,而上述main.c中沒有第二個參數(這裡說的是execl的第二個參數),也就是沒有給foo傳遞任何參數,foo的參數表argv當然就是空了,或者說argc為0。
通過這個例子我們要有以下認識:
argv[0]不一定就是所執行程序的名稱,確切的說它只是命令行的第一個參數,只是通常啟動程序是在命令行鍵入程序名稱啟動的,所以程序的名稱才成為argv[0]。但是也有情況argv[0]不是程序名稱的,如:
(1) 通過exec執行時,argv[0]是什麼要視exec的參數來定。
例如:我們將main中的execl語句改為:execl(/mnt/hgfs/VWShared/foo,xxxxx,(char*)0);
再運行main,效果如圖3:
圖3
可以看到argv[0]變為了我們傳入的參數」xxxxx」。
(2) 通過程序別名啟動時,argv[0]就是程序的別名。如我們給foo創建一個軟連接sfoo,然後執行sfoo效果如圖4:
圖4
可以看出輸出的argv[0]是./sfoo 而不是./foo,再次證明argv[0]是什麼和程序名稱無關,只是和傳入的命令行第一個參數有關。
補充:在創建上述軟連接過程中遇到了一點小問題,不妨也在這裡寫下來:
【問題】
在編譯VMware下的Linux系統對從Windows中共享過來的文件,進行編譯的時候,遇到:ln: creating symbolic link XXXXXX : Operation not supported
【解決辦法】
出現這類問題,主要是由於在編譯的時候,要用ln去建立一些軟連結,而這些文件是從Windows中,通過VMWare虛擬機共享進Linux的,而雖然此種操作在Linux系統中很常見,但Windows不支持,所以,編譯會報錯。比較方便的解決辦法是先將文件考到linux的其他目錄,再在其他非共享目錄中創建軟連接。另外還有個解決辦法就是,在VMWare下的Linux中,建立Samba服務,然後新創建新samba用戶和文件夾,然後在windows中就可以訪問到該文件夾了。然後把在Linux中,從共享目錄拷貝到你所要共享的samba目錄中,這樣,也可以實現我們所要的文件共享。此時在去編譯這些代碼的時候,由於是在Linux系統中的,所以就OK了。
3. 解釋器文件和解釋器