L001 Linux和android ndk 外部程序調(diào)用popen 和system的用法

我們支持,linux常用的調(diào)用外部指令,有兩個接口ppen和system

popen的使用

函數(shù)原型

#include <stdio.h>
FILE * popen ( const char * command , const char * type );
int pclose ( FILE * stream );

說明

popen() 函數(shù)通過創(chuàng)建一個管道,調(diào)用 fork 產(chǎn)生一個子進程,執(zhí)行一個 shell 以運行命令來開啟一個進程。這個進程必須由 pclose() 函數(shù)關(guān)閉,而不是 fclose() 函數(shù)。pclose() 函數(shù)關(guān)閉標準 I/O 流,等待命令執(zhí)行結(jié)束,然后返回 shell 的終止狀態(tài)。如果 shell 不能被執(zhí)行,則 pclose() 返回的終止狀態(tài)與 shell 已執(zhí)行 exit 一樣。

type 參數(shù)只能是讀或者寫中的一種,得到的返回值(標準 I/O 流)也具有和 type 相應的只讀或只寫類型。如果 type 是 "r" 則文件指針連接到 command 的標準輸出;如果 type 是 "w" 則文件指針連接到 command 的標準輸入。

command 參數(shù)是一個指向以 NULL 結(jié)束的 shell 命令字符串的指針。這行命令將被傳到 bin/sh 并使用-c 標志,shell 將執(zhí)行這個命令。

popen 的返回值是個標準 I/O 流,必須由 pclose 來終止。前面提到這個流是單向的。所以向這個流寫內(nèi)容相當于寫入該命令的標準輸入;命令的標準輸出和調(diào)用 popen 的進程相同。與之相反的,從流中讀數(shù)據(jù)相當于讀取命令的標準輸出;命令的標準輸入和調(diào)用 popen 的進程相同。

返回值

如果調(diào)用 fork() 或 pipe() 失敗,或者不能分配內(nèi)存將返回NULL,否則返回標準 I/O 流。
返回錯誤
popen 沒有為內(nèi)存分配失敗設(shè)置 errno 值。
如果調(diào)用 fork() 或 pipe() 時出現(xiàn)錯誤,errno 被設(shè)為相應的錯誤類型。
如果 type 參數(shù)不合法,errno將返回EINVAL。

使用舉例

/**運行命令
 *1. cmd    要執(zhí)行的命令
 *2. 參數(shù)type可使用“r”代表讀取,“w”代表寫入。
 */
int runShell(const char *cmd,const char *type,char *resultBuffer,int len)
{   
    int ret;    
    
    FILE * pp=popen(cmd,type);          
    ret = fread ( resultBuffer, 1, len, pp );  
    pclose(pp);  

    return ret;
}

如果想看到標準出錯的信息呢?

只需在命令中加入重定向 例如:

cp -f 2>&1

system調(diào)用

system()會調(diào)用fork()產(chǎn)生子進程,由子進程來調(diào)用/bin/sh-c string來執(zhí)行參數(shù)string字符串所代表的命令,此命>令執(zhí)行完后隨即返回原調(diào)用的進程。在調(diào)用system()期間SIGCHLD 信號會被暫時擱置,SIGINT和SIGQUIT 信號則會被忽略。
返回值

=-1:出現(xiàn)錯誤
=0:調(diào)用成功但是沒有出現(xiàn)子進程
>0:成功退出的子進程的id 

命令執(zhí)行的返回值獲取可參考我的如下例程:

int mysystem(char *cmd)
{
    pid_t status;  
  
    status = system(cmd);  
    if (-1 == status)  
    {  
        D("system error! status=%d\n",status);  
    }  
    else  
    {  
        
        if (WIFEXITED(status))  
        {  
            if (0 == WEXITSTATUS(status))  
            {  
                D("run shell script successfully.\n");  
                return 0;
            }  
            else  
            {  
                E("run script fail, script exit code: %d\n", WEXITSTATUS(status));  
                return WEXITSTATUS(status);
            }  
        }  
        else  
        {  
            D("exit  %d\n", WEXITSTATUS(status));  
            return WEXITSTATUS(status);
        }  
    }  
}

system調(diào)用總是返回-1的原因

返回-1的原因是因為進程將SIGCHLD屏蔽了!

確實我的程序在main函數(shù)里面就調(diào)用signal(SIGCHLD, SIG_IGN);將SIGCHLD屏蔽了!
system的調(diào)用過程主要是調(diào)三個函數(shù)

  1. fork()
  2. execl()
  3. wait()

wait需要依賴SIGCHLD信號,所以屏蔽了SIGCHLD信號就永遠得不到system正確的返回值了!

參考鏈接

  1. Linux的system()和popen()差異
  2. system調(diào)用總是返回-1
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容