當前位置:首頁 > 嵌入式 > 嵌入式軟件
[導讀] 1. 從一個問題開始首先要從項目中遇到的一個問題說起。編寫一個python文件test.py,文件test.py內容如下:#! /usr/bin/python....如果在命令行方式執(zhí)行test.py的方式是:t

 1. 從一個問題開始

首先要從項目中遇到的一個問題說起。編寫一個python文件test.py,文件test.py內容如下:

#! /usr/bin/python

....

如果在命令行方式執(zhí)行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);

但執(zhí)行結果并不是預想的test.py執(zhí)行,而是啟動了python交互程序,不知道是什么原因。因為一直以為如果寫一個C程序,比如main。那么在命令行輸入:main arg1 arg2執(zhí)行的效果和execl(”main”,”arg1”,”arg2”,(char*)0)的效果應該是一樣的。

當然同時伴隨我有另一個問題:

execl(“usr/bin/python”,”test.py”,(char*)0);和輸入命令”/usr/bin/python test.py”有什么區(qū)別?

為了回答些問題,自己通過再反復看apue和做實驗測試,終于一點一點明白了,下面就來一點一點的分析。

2. 命令行執(zhí)行程序和exec執(zhí)行程序的區(qū)別

首先我們來分析一下在命令行執(zhí)行一個程序和通過exec函數執(zhí)行程序有什么區(qū)別,或者說需要注意的地方(一下所有編寫的文件都在/mnt/hgfs/VWShared/目錄下)。

編寫程序foo.c如下,并編譯為可執(zhí)行文件foo。它打印參數列表(argv)的所有參數.

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);

}

再編寫main.c如下,將其編譯為可執(zhí)行文件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發(fā)現并沒有參數傳入foo(程序沒有任何輸出),也就是說argc值為0。這是什么原因呢?我們知道argv存放的是傳遞給main函數的命令行參數,當在命令行鍵入”./foo”時,唯一的命令行參數”./foo”就被傳入給main的argv了。所以直接在命令行運行foo就打印出唯一的參數”./foo”。

那么execl的情況呢?首先看一下execl的原型:

int execl(const char* pathname,const char* arg0,.../*(char*)0*/);

注意到了吧,第一個參數是要執(zhí)行的程序名,第二個參數才是要傳入待執(zhí)行程序的第一個參數,而上述main.c中沒有第二個參數(這里說的是execl的第二個參數),也就是沒有給foo傳遞任何參數,foo的參數表argv當然就是空了,或者說argc為0。

通過這個例子我們要有以下認識:

argv[0]不一定就是所執(zhí)行程序的名稱,確切的說它只是命令行的第一個參數,只是通常啟動程序是在命令行鍵入程序名稱啟動的,所以程序的名稱才成為argv[0]。但是也有情況argv[0]不是程序名稱的,如:

(1) 通過exec執(zhí)行時,argv[0]是什么要視exec的參數來定。

例如:我們將main中的execl語句改為:execl("/mnt/hgfs/VWShared/foo","xxxxx",(char*)0);

再運行main,效果如圖3:

圖3

可以看到argv[0]變?yōu)榱宋覀儌魅氲膮?rdquo;xxxxx”。

(2) 通過程序別名啟動時,argv[0]就是程序的別名。如我們給foo創(chuàng)建一個軟連接sfoo,然后執(zhí)行sfoo效果如圖4:

圖4

可以看出輸出的argv[0]是./sfoo 而不是./foo,再次證明argv[0]是什么和程序名稱無關,只是和傳入的命令行第一個參數有關。

補充:在創(chuàng)建上述軟連接過程中遇到了一點小問題,不妨也在這里寫下來:

【問題】

在編譯VMware下的Linux系統(tǒng)對從Windows中共享過來的文件,進行編譯的時候,遇到:ln: creating symbolic link XXXXXX : Operation not supported

【解決辦法】

出現這類問題,主要是由于在編譯的時候,要用ln去建立一些軟鏈接,而這些文件是從Windows中,通過VMWare虛擬機共享進Linux的,而雖然此種操作在Linux系統(tǒng)中很常見,但Windows不支持,所以,編譯會報錯。比較方便的解決辦法是先將文件考到linux的其他目錄,再在其他非共享目錄中創(chuàng)建軟連接。另外還有個解決辦法就是,在VMWare下的Linux中,建立Samba服務,然后新創(chuàng)建新samba用戶和文件夾,然后在windows中就可以訪問到該文件夾了。然后把在Linux中,從共享目錄拷貝到你所要共享的samba目錄中,這樣,也可以實現我們所要的文件共享。此時在去編譯這些代碼的時候,由于是在Linux系統(tǒng)中的,所以就OK了。

3. 解釋器文件和解釋器[!--empirenews.page--]

先解釋兩個概念;解釋器文件和解釋器。

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

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

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

當執(zhí)行(exec)"解釋器"文件時,exec系統(tǒng)調用會識別這種文件,內核使調用exec函數的進程實際執(zhí)行的并不是該"解釋器文件",而是pathname指定的解釋器。

我們可以自己寫一個解釋器,如之前所寫的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/。

下面我們在自己寫一個”解釋器文件”——test:

l test

#!/mnt/hgfs/VWShared/foo

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

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

圖5

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

圖6

通過這兩個例子,可以看出命令行運行時當執(zhí)行文件是”解釋器文件”時,參數是如何傳遞給解釋器的:

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

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

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

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

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

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

圖7

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

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

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

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

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

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

為了說明這個問題,我們再舉一個例子,編寫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一樣同樣是打印每個命令行參數。我們分別將main中的execl語句改為:

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

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

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

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

可以看出execl對于執(zhí)行普通文件和解釋器文件選取第一個參數是不同的。

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

我們上面已經看到execl("/mnt/hgfs/VWShared/pyth.py","arg1","arg2",(char*)0))的結果(圖9),下面我們試一下命令行方式:pyth.py arg1 arg2,結果圖10:

圖10

可以看到結果和通過execl執(zhí)行是有區(qū)別的,通過命令行執(zhí)行解釋器文件就像通過命令行執(zhí)行普通程序一樣,程序名稱作為第一個參數,命令行后面依次作為后續(xù)參數。正因為對于解釋器文件的execl方式和命令行方式執(zhí)行時選取第一個參數的方式不同,所以對于解釋器文件a.py:[!--empirenews.page--]

(1) 在命令行輸入:./a.py arg1 arg2;

(2) execl("./a.py","arg1","arg2",(char*)0));

(3) execl("./a.py",”xxx”,"arg1","arg2",(char*)0));

方式(1)和方式(2)不等價,因為方式(1)中arg1會被當做第二個參數傳遞給解釋器,而方式(2)中arg2會被當做第二個參數傳遞給解釋器。方式(1)和方式(3)是等價的。

對于普通文件foo:

(1) 在命令行輸入: ./foo arg1 arg2;

(2) execl("./foo","arg1","arg2",(char*)0))

方式(1)和方式(2)是等價的。

4. 回答開始的問題

為了達到命令行方式:test.py arg1 arg2的效果,使用execl("test.py","arg1","arg2",(char*)0))肯定是不行的,因為arg1會被忽略,提示缺少參數。正確的方式是:execl("test.py",”xxx”,"arg1","arg2",(char*)0)),這里”xxx”代表任意字符串,不過一般會使用解釋器文件名,即”test.py”。

為了達到命令行方式:python test.py arg1 arg2的效果,使用execl("python",”test.py”,"arg1","arg2",(char*)0))也是不行的,因為test.py會被忽略,arg1會被當做第一個參數傳給python解釋器。正確方式是:

execl(“python",”xxx”,”test.py”,"arg1","arg2",(char*)0)),這里”xxx”代表任意字符串,不過一般會使用解釋器文件名,即”test.py”。

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據媒體報道,騰訊和網易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數據產業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數據產業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數字經濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉