歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> 學習Linux >> 關於linux下system()函數的總結

關於linux下system()函數的總結

日期:2017/3/3 17:48:27   编辑:學習Linux

關於linux下system()函數的總結

關於linux下system()函數的總結


導讀曾經的曾經,被system()函數折磨過,之所以這樣,是因為對system()函數了解不夠深入。這裡必須要搞懂system()函數,因為有時你不得不面對它。

關於linux下system()函數的總結關於linux下system()函數的總結

先來看一下system()函數的簡單介紹:
#includeint system(const char *command)

system()函數調用/bin/sh來執行參數指定的命令,/bin/sh 一般是一個軟連接,指向某個具體的shell,比如bash,-c選項是告訴shell從字符串command中讀取命令; 在該command執行期間,SIGCHLD是被阻塞的,好比在說:hi,內核,這會不要給我送SIGCHLD信號,等我忙完再說; 在該command執行期間,SIGINT和SIGQUIT是被忽略的,意思是進程收到這兩個信號後沒有任何動作。

再來看一下system()函數返回值:

為了更好的理解system()函數返回值,需要了解其執行過程,實際上system()函數執行了三步操作:

  1. fork一個子進程;
  2. 在子進程中調用exec函數去執行command;
  3. 在父進程中調用wait去等待子進程結束。 對於fork失敗,system()函數返回-1。 如果exec執行成功,也即command順利執行完畢,則返回command通過exit或return返回的值。 (注意,command順利執行不代表執行成功,比如command:"rm debuglog.txt",不管文件存不存在該command都順利執行了) 如果exec執行失敗,也即command沒有順利執行,比如被信號中斷,或者command命令根本不存在,system()函數返回127. 如果command為NULL,則system()函數返回非0值,一般為1.

關於linux下system()函數的總結關於linux下system()函數的總結

看一下system()函數的源碼

看完這些,我想肯定有人對system()函數返回值還是不清楚,看源碼最清楚,下面給出一個system()函數的實現:

int system(const char * cmdstring){    pid_t pid;    int status;    if(cmdstring == NULL)    {        return (1); //如果cmdstring為空,返回非零值,一般為1    }    if((pid = fork())<0)    {        status = -1; //fork失敗,返回-1    }    else if(pid == 0)    {        execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);        _exit(127); // exec執行失敗返回127,注意exec只在失敗時才返回現在的進程,成功的話現在的        進程就不存在啦~~    }    else //父進程    {        while(waitpid(pid, &status, 0) < 0)        {            if(errno != EINTR)            {                status = -1; //如果waitpid被信號中斷,則返回-1                break;            }        }    }    return status; //如果waitpid成功,則返回子進程的返回狀態}

仔細看完這個system()函數的簡單實現,那麼該函數的返回值就清晰了吧,那麼什麼時候system()函數返回0呢?只在command命令返回0時。

看一下該怎麼監控system()函數執行狀態 這裡給我出的做法:
int status;if(NULL == cmdstring) //如果cmdstring為空趁早閃退吧,盡管system()函數也能處理空指針{    return XXX;}status = system(cmdstring);if(status < 0){    printf("cmd: %s\t error: %s", cmdstring, strerror(errno)); // 這裡務必要把errno信息輸出或    記入Log    return XXX;}if(WIFEXITED(status)){    printf("normal termination, exit status = %d\n", WEXITSTATUS(status)); //取得cmdstring執行結果 }    else if(WIFSIGNALED(status)){    printf("abnormal termination,signal number =%d\n", WTERMSIG(status)); //如果cmdstring被信號中    斷,取得信號值}else if(WIFSTOPPED(status)){    printf("process stopped, signal number =%d\n", WSTOPSIG(status)); //如果cmdstring被信號暫停執    行,取得信號值}

system()函數用起來很容易出錯,返回值太多,而且返回值很容易跟command的返回值混淆。這裡推薦使用popen()函數替代,關於popen()函數的簡單使用可以自己查下資料。

popen()函數較於system()函數的優勢在於使用簡單,popen()函數只返回兩個值: 成功返回子進程的status,使用WIFEXITED相關宏就可以取得command的返回結果; 失敗返回-1,我們可以使用perro()函數或strerror()函數得到有用的錯誤信息。

這篇文章只涉及了system()函數的簡單使用,還沒有談及SIGCHLD、SIGINT和SIGQUIT對system()函數的影響,事實上,之所以今天寫這篇文章,是因為項目中因有人使用了system()函數而造成了很嚴重的事故。現像是system()函數執行時會產生一個錯誤:“No child processes”。此時調用my_system()來執行system函數的功能(my_system函數中是使用popen()函數來實現的), 測試了一天,沒有再次出現程序突然死掉的問題(修改前連續循環調用system()函數測試,每10次就會至少導致程序掛掉一次.連續不停頓的調用)。

原文來自:https://my.oschina.net/renhc/blog/53580

本文地址:http://www.linuxprobe.com/linux-system-constructors.html


http://xxxxxx/Linuxjc/1184673.html TechArticle

Copyright © Linux教程網 All Rights Reserved