關於linux下system()函式的總結
導讀 | 曾經的曾經,被system()函式折磨過,之所以這樣,是因為對system()函式了解不夠深入。這裡必須要搞懂system()函式,因為有時你不得不面對它。 |
#include int system(const char *command)
system()函式呼叫/bin/sh來執行引數指定的 ,/bin/sh 一般是一個軟連線,指向某個具體的 ,比如bash,-c選項是告訴shell從字串command中讀取 ; 在該command執行期間,SIGCHLD是被阻塞的,好比在說:hi,核心,這會不要給我送SIGCHLD訊號,等我忙完再說; 在該command執行期間,SIGINT和SIGQUIT是被忽略的,意思是程式收到這兩個訊號後沒有任何動作。
為了更好的理解system()函式返回值,需要了解其執行過程,實際上system()函式執行了三步操作:
- fork一個子程式;
- 在子程式中呼叫exec函式去執行command;
- 在父程式中呼叫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.
看完這些,我想肯定有人對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時。
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次就會至少導致程式掛掉一次.連續不停頓的呼叫)。
原文來自:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2930903/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 史上最全關於sorted函式的10條總結函式
- linux下時間有關的函式和結構體Linux函式結構體
- 關於字串的功能函式小結字串函式
- python中關於時間和日期函式的常用計算總結Python函式
- tensorflow相關函式學習總結函式
- 【Linux】關於Linux的系統程式設計總結Linux程式設計
- MySQL 字串擷取相關函式總結MySql字串函式
- 總結常用的字串函式字串函式
- Sigmoid函式總結Sigmoid函式
- Linux下getopt函式的使用Linux函式
- 關於count函式的理解函式
- 關於近期的總結
- spark中的聚合函式總結Spark函式
- JS 中的函式 this 指向總結JS函式
- mysql日期函式總結MySql函式
- PHP常用函式總結PHP函式
- 關於學習 Linux 系統結構的一些總結Linux
- 關於建構函式與解構函式的分享函式
- 關於函式指標函式指標
- linux之系統命令command和系統呼叫system calls及函式function之間的關係Linux函式Function
- mysql關於variable的總結MySql
- sqlserver關於always on的總結SQLServer
- 關於學習-Linux-系統結構的一些總結Linux
- php 驗證格式的函式總結PHP函式
- Python函式引數總結Python函式
- mysql函式全面總結KSVMMySql函式
- 關於cuda中的函式問題函式
- python關於函式形參Python函式
- sqlserver 關於DBCC CHECKDB的總結SQLServer
- sqlserver關於mirror映象的總結SQLServer
- 關於golang的time包總結Golang
- C++ sort排序函式的用法總結C++排序函式
- python函式與方法的區別總結Python函式
- php之正規表示式函式總結PHP函式
- 關於Servlet小總結Servlet
- PHP 學習總結之函式PHP函式
- js常見函式總結(一)JS函式
- MySQL視窗函式用法總結MySql函式