Linux C/C++呼叫shell命令後獲取shell返回值
Linux C/C++呼叫shell命令後獲取shell返回值
專案中C/C++呼叫shell命令後,某系處理返回值的過程是以“臨時檔案”的方式進行;即shell命令執行後將返回值存放在臨時檔案(如temp.txt),C/C++程式再訪問檔案,獲取shell的返回值。最經典的就是呼叫WiFi(iwlist wlan0 scan )掃描指令查詢WiFi節點,然後解析獲取WiFi數量、名稱、訊號強度、加密方式等資訊。
通過“臨時檔案”的方式互動資料,是比較簡單、易用和易理解的方式,在多程序間、多執行緒間也可以使用,但一般不會使用。共享“臨時檔案”有個弊端就是效率上不比較低,建立檔案、刪除檔案然後是訪問,都是訪問儲存器(磁碟、flash),加上檔案系統的一層封裝和儲存介質對映,訪問速度不如訪問記憶體快。
“臨時檔案”的方式,個人覺得不是很好,通過該案例總結下C/C++呼叫shell命令知識。
1.C/C++呼叫shell命令方式
Linux 系統中使用 C/C++ 呼叫 shell 命令常用方式:
- system()函式
- popen()函式
- exec函式簇
system()函式最常用,簡單高效; popen() 執行 shell 命令的開銷比 system() 小;system()和popen()都封裝了程序建立、釋放,內部實質呼叫的是exec函式簇;exec需手動fork程序進,然後再呼叫exec函式簇個,過程比前兩者稍微複雜。
C語言執行linux shell命令,對於沒有返回結果的,可直接使用system()函式,對於有返回結果的,可以用popen命令,對其封裝後,可以獲取相應的返回資訊。
函式原型:
FILE * popen ( const char * command , const char * type );
int pclose ( FILE * stream );
command:要執行shell命令
type:建立的管道的讀寫型別("r" 或者 "w")
1.type為“r”時,管道連線到shell子程序的標準輸出,
2.type為“w”時,管道連線到shell子程序的標準輸入
“r”就能獲取shell命令的執行輸出結果了。返回值為FILE *檔案指標,使用fread即可從檔案流指標
中讀出輸出結果。
例項:
#include <stdio.h> int main(void) { FILE *fp = NULL; char buf[100]={0}; fp = popen("ps", "r"); if(fp) { int ret = fread(buf,1,sizeof(buf)-1,fp); if(ret > 0) { printf("%s",buf); } pclose(fp); printf("\n"); } return 0; }
1.popen()會呼叫fork()產生子程序,然後從子程序中呼叫/bin/sh -c來執行引數command的指令。
2.popen函式還建立一個管道用於父子程序間通訊。子程序要麼從管道讀資訊,要麼向管道寫資訊,至於是讀
還是寫取決於父程序呼叫popen時傳遞的引數。
3.pclose()用來關閉由popen所建立的管道及檔案指標
popen是不堵塞的,也就是說不會等待子程序的結束並殺死子程序,即不會管理程序。這樣就需要人為的去
殺死或忽略子程序等操作。還有就是popen會將執行的結果返回到buffer中。在執行期間呼叫程序會一直等
待shell命令執行完成。popen :沒有對訊號做任何的處理。popen()函式中沒有遮蔽SIGINT、SIGQUIT的
原因是因為popen是”並行的”,不能影響其它”並行”程序。
system是堵塞的,完成後會自動對程序進行管理,無需再去對程序進行管理。另外,system不會返回執行的
結果,只是會返回執行是否成功。system:對SIGCHLD、SIGINT、SIGQUIT都做了處理,system()呼叫對
訊號遮蔽的原因是因為system能夠及時的退出並且能夠正確的獲取子程序的退出狀態(成功回收子程序)。
主要區別:system函式呼叫shell命令,但是無法獲得執行的shell命令執行的輸出結果。而使用popen
能夠獲取到輸出結果。 popen後需要呼叫pclose防止子程序變成”殭屍”狀態。