1. 程式人生 > 其它 >Linux C/C++呼叫shell命令後獲取shell返回值

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防止子程序變成”殭屍”狀態。