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函數簇個,過程比前兩者稍微復雜。

1.1 system()

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

https://www.daimajiaoliu.com/daima/479716eaf100420


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM