日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

【C/C++】Linux下使用system()函数一定要谨慎

發(fā)布時(shí)間:2023/12/2 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C/C++】Linux下使用system()函数一定要谨慎 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
曾經(jīng)的曾經(jīng),被system()函數(shù)折磨過,之所以這樣,是因?yàn)閷ystem()函數(shù)了解不夠深入。只是簡單的知道用這個(gè)函數(shù)執(zhí)行一個(gè)系統(tǒng)命令,這遠(yuǎn)遠(yuǎn)不夠,它的返回值、它所執(zhí)行命令的返回值以及命令執(zhí)行失敗原因如何定位,這才是重點(diǎn)。當(dāng)初因?yàn)檫@個(gè)函數(shù)風(fēng)險(xiǎn)較多,故拋棄不用,改用其他的方法。這里先不說我用了什么方法,這里必須要搞懂system()函數(shù),因?yàn)檫€是有很多人用了system()函數(shù),有時(shí)你不得不面對它。
先來看一下system()函數(shù)的簡單介紹: ?
1 2 #include <stdlib.h> int system(const char *command);

system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.

system()函數(shù)調(diào)用/bin/sh來執(zhí)行參數(shù)指定的命令,/bin/sh 一般是一個(gè)軟連接,指向某個(gè)具體的shell,比如bash,-c選項(xiàng)是告訴shell從字符串command中讀取命令; 在該command執(zhí)行期間,SIGCHLD是被阻塞的,好比在說:hi,內(nèi)核,這會(huì)不要給我送SIGCHLD信號,等我忙完再說; 在該command執(zhí)行期間,SIGINT和SIGQUIT是被忽略的,意思是進(jìn)程收到這兩個(gè)信號后沒有任何動(dòng)作。
再來看一下system()函數(shù)返回值: The value returned is -1 on error (e.g. fork(2) failed), and the return status of the command otherwise. This latter return status is in the format specified in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status). In case /bin/sh could not be executed, the exit status will be that of a command that does exit(127). If the value of command is NULL, system() returns nonzero if the shell is available, and zero if not. 為了更好的理解system()函數(shù)返回值,需要了解其執(zhí)行過程,實(shí)際上system()函數(shù)執(zhí)行了三步操作: 1.fork一個(gè)子進(jìn)程; 2.在子進(jìn)程中調(diào)用exec函數(shù)去執(zhí)行command; 3.在父進(jìn)程中調(diào)用wait去等待子進(jìn)程結(jié)束。 對于fork失敗,system()函數(shù)返回-1。 如果exec執(zhí)行成功,也即command順利執(zhí)行完畢,則返回command通過exit或return返回的值。 (注意,command順利執(zhí)行不代表執(zhí)行成功,比如command:"rm debuglog.txt",不管文件存不存在該command都順利執(zhí)行了) 如果exec執(zhí)行失敗,也即command沒有順利執(zhí)行,比如被信號中斷,或者command命令根本不存在,system()函數(shù)返回127. 如果command為NULL,則system()函數(shù)返回非0值,一般為1.
看一下system()函數(shù)的源碼 看完這些,我想肯定有人對system()函數(shù)返回值還是不清楚,看源碼最清楚,下面給出一個(gè)system()函數(shù)的實(shí)現(xiàn): ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 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執(zhí)行失敗返回127,注意exec只在失敗時(shí)才返回現(xiàn)在的進(jìn)程,成功的話現(xiàn)在的進(jìn)程就不存在啦~~ } else //父進(jìn)程 { ????while(waitpid(pid, &status, 0) < 0) ????{ ????????if(errno != EINTR) ????????{ ????????????status = -1; //如果waitpid被信號中斷,則返回-1 ????????????break; ????????} ????} } ????return status; //如果waitpid成功,則返回子進(jìn)程的返回狀態(tài) }

仔細(xì)看完這個(gè)system()函數(shù)的簡單實(shí)現(xiàn),那么該函數(shù)的返回值就清晰了吧,那么什么時(shí)候system()函數(shù)返回0呢?只在command命令返回0時(shí)。
看一下該怎么監(jiān)控system()函數(shù)執(zhí)行狀態(tài) 這里給我出的做法: ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 int status; if(NULL == cmdstring) //如果cmdstring為空趁早閃退吧,盡管system()函數(shù)也能處理空指針 { ????return XXX; } status = system(cmdstring); if(status < 0) { ????printf("cmd: %s\t error: %s", cmdstring, strerror(errno)); // 這里務(wù)必要把errno信息輸出或記入Log ????return XXX; } if(WIFEXITED(status)) { ????printf("normal termination, exit status = %d\n", WEXITSTATUS(status)); //取得cmdstring執(zhí)行結(jié)果 } 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被信號暫停執(zhí)行,取得信號值 }

到于取得子進(jìn)程返回值的相關(guān)介紹可以參考另一篇文章:http://my.oschina.net/renhc/blog/35116

?

system()函數(shù)用起來很容易出錯(cuò),返回值太多,而且返回值很容易跟command的返回值混淆。這里推薦使用popen()函數(shù)替代,關(guān)于popen()函數(shù)的簡單使用也可以通過上面的鏈接查看。

popen()函數(shù)較于system()函數(shù)的優(yōu)勢在于使用簡單,popen()函數(shù)只返回兩個(gè)值:
成功返回子進(jìn)程的status,使用WIFEXITED相關(guān)宏就可以取得command的返回結(jié)果;
失敗返回-1,我們可以使用perro()函數(shù)或strerror()函數(shù)得到有用的錯(cuò)誤信息。

這篇文章只涉及了system()函數(shù)的簡單使用,還沒有談及SIGCHLD、SIGINT和SIGQUIT對system()函數(shù)的影響,事實(shí)上,之所以今天寫這篇文章,是因?yàn)轫?xiàng)目中因有人使用了system()函數(shù)而造成了很嚴(yán)重的事故。現(xiàn)像是system()函數(shù)執(zhí)行時(shí)會(huì)產(chǎn)生一個(gè)錯(cuò)誤:“No child processes”。

關(guān)于這個(gè)錯(cuò)誤的分析,感興趣的朋友可以看一下:http://my.oschina.net/renhc/blog/54582

?

2012-04-14 qdurenhongcai@163.com

轉(zhuǎn)載請注明出處。

總結(jié)

以上是生活随笔為你收集整理的【C/C++】Linux下使用system()函数一定要谨慎的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。