c语言调用shell命令一 popen使用以及获取命令返回值
? ? ? 產(chǎn)品升級,新增網(wǎng)卡,原先的產(chǎn)品是arm平臺,新網(wǎng)卡是mips平臺,需要開發(fā)網(wǎng)卡的配置程序,該程序原計(jì)劃是以守護(hù)進(jìn)程的形式后臺執(zhí)行,不過測試過程中發(fā)現(xiàn)系統(tǒng)不是特別穩(wěn)定,導(dǎo)致程序時(shí)不時(shí)奔潰下,一時(shí)半會兒無法解決,只能先給該程序加個(gè)殼,以系統(tǒng)調(diào)用的方式來執(zhí)行,如果出現(xiàn)問題的話重復(fù)調(diào)用就可以了。
? ? ? 以前在程序里調(diào)用系統(tǒng)命令的話,使用的是system()函數(shù),不過system函數(shù)無法獲取命令的輸出,查了下資料,發(fā)現(xiàn)有個(gè)popen調(diào)用,和system類似,也能夠執(zhí)行系統(tǒng)命令,區(qū)別在于它能夠獲取命令的輸出或者給系統(tǒng)命令傳遞參數(shù),類似與管道的作用。
popen接口定義:
#include <stdio.h> FILE *popen(const char *command, const char *type); int pclose(FILE *stream);popen函數(shù)會創(chuàng)建一個(gè)管道,并且創(chuàng)建一個(gè)子進(jìn)程來執(zhí)行shell,shell會創(chuàng)建一個(gè)子進(jìn)程來執(zhí)行command, 根據(jù)type的值不同,分成兩種情況:如果type是r: command執(zhí)行的標(biāo)準(zhǔn)輸出,就會寫入管道,從而被調(diào)用popen的進(jìn)程讀到,通過對popen返 回的FILE類型指針執(zhí)行read或fgets操作,就可以讀取到command的標(biāo)準(zhǔn)輸出。如果type是w:調(diào)用popen的進(jìn)程可以通過對FILE類型指針執(zhí)行write、fputs等操作,負(fù)責(zé)往管道里面寫 入,寫入的內(nèi)容經(jīng)過管道傳遞給執(zhí)行command的進(jìn)程,作為命令的的輸入。popen函數(shù)成功時(shí),會返回stdio庫封裝的FILE類型的指針,失敗時(shí)會返回NULL,并且設(shè)置errno, 常見的失敗有fork失敗、pipe失敗,或者分配內(nèi)存失敗。I/O結(jié)束后,可以調(diào)用pclose函數(shù)來關(guān)閉管道,并且等待子進(jìn)程的退出。pclose函數(shù)成功時(shí)會返回 子進(jìn)程shell的終止?fàn)顟B(tài)。popen函數(shù)和system函數(shù)類似,如果command對應(yīng)命令無法執(zhí)行,就如同 執(zhí)行了exit(127)一樣,如果發(fā)生其它錯(cuò)誤,pclose函數(shù)則返回-1.可以從errno中獲取到失敗的原因。命令執(zhí)行后需要獲取命令的返回值,可以通過如下幾個(gè)宏來獲取:
1. 進(jìn)程正常退出 WIFEXITED(status) : 如果子進(jìn)程正常退出,則返回true,否則返回false WEXITSTATUS(status):如果子進(jìn)程正常退出,則本宏用來獲取進(jìn)程的退出狀態(tài)2. 進(jìn)程收到信號,導(dǎo)致退出 WIFSIGNALED(status) : 如果進(jìn)程是被信號殺死的,則返回true,否則返回false WTREMSIG(status):如果進(jìn)程是被信號殺死的,則返回殺死進(jìn)程信號的值 WCOREDUMP(status) : 如果子進(jìn)程產(chǎn)生了core dump,則返回true,否則返回false測試用例:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h> #include<errno.h> #include<sys/wait.h> #include<signal.h>#define MAX_LINE_SIZE 8192/* 打印shell返回結(jié)果 */ void print_wait_exit(int status) {/* shell正常退出,即便命令執(zhí)行異常,shell也有可能是正常退出的 */if(WIFEXITED(status)) {printf("normal termination, exit status = %d\n", WEXITSTATUS(status));}/* shell異常退出 */else if(WIFSIGNALED(status)){printf("abnormal terminatio, signal number = %d\n", WTERMSIG(status));} }int main(int argc, char *argv[]) {FILE *fp = NULL;char command[MAX_LINE_SIZE], buffer[MAX_LINE_SIZE];if(argc != 2){fprintf(stderr, "Usage : %s filename \n", argv[0]);exit(1);}snprintf(command, sizeof(command), "%s", argv[1]);fp = popen(command, "r");if (fp == NULL){fprintf(stderr, "popen failed (%s)", strerror(errno));exit(2); }while (fgets(buffer, MAX_LINE_SIZE,fp) != NULL){fprintf(stdout, "%s",buffer);}int ret = pclose(fp);if (ret == 127){fprintf(stderr, "bad command :%s \n",command);exit(3);}else if (ret == -1){fprintf(stderr, "failed to get child status :%s \n",strerror(errno));exit(4);}else{print_wait_exit(ret);}exit(0); }運(yùn)行截圖:
參考資料:
1. 《Linux環(huán)境編程 從應(yīng)用到內(nèi)核》高峰,李彬著
總結(jié)
以上是生活随笔為你收集整理的c语言调用shell命令一 popen使用以及获取命令返回值的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 年息5%是什么意思 存贷款利息按年利率为
- 下一篇: 股票佣金是什么时候收