system函数和fork-exec机制
system函數(shù)
使用man system查看幫助如下:
NAMEsystem -execute a shell commandSYNOPSIS#include<stdlib.h>intsystem(const char *command);DESCRIPTIONsystem()? executes?a command specified in command by calling/bin/sh -ccommand, and returns after the?command? has? beencompleted.?? During execution ofthe command, SIGCHLD will beblocked, andSIGINT and SIGQUIT will be ignored.RETURN VALUEThe value returned is -1 on error (e.g.? fork(2) failed), andthe? return?status? of? the?command otherwise.? This latterreturn statusis in the format specified in?wait(2).?? Thus,?the exit code of thecommand will be WEXITSTATUS(status).?Incase /bin/shcould not be executed, the exit status?will? bethat of acommand that does exit(127).If the valueof command is NULL, system() returns non-zero ifthe shell isavailable, and zero if not.system() doesnot affect the wait status of any?other? chil-dren.說明:
以/bin/sh -c command的方式執(zhí)行命令,如果命令之間用“; ”隔開,則可以執(zhí)行多條指令。
system是一個同步函數(shù),即執(zhí)行完之后才會返回,內(nèi)部實現(xiàn)也類似與fork-exec機制(執(zhí)行期間會阻塞SIGCHLD信號,同時忽略SIGINT、SIGQUIT)。
如何判斷system是否執(zhí)行成功:
1、?? fork成功:-1 != status
2、?? system命令是否正常終止:WIFEXITED(status)非0 ,非正常終止=0
3、?? 根據(jù)返回值判斷:WEXITSTATUS(status)== 0? //獲取system的返回值(低八位,可以理解為unsignedbyte);如果shell命令無法執(zhí)行,則返回127,命令檢測到有錯誤,則返回1-126
注意:
當(dāng)shell腳本不存在、沒有執(zhí)行權(quán)限等場景下時,以上前2個條件仍會成立,此時WEXITSTATUS(status)為127,126等數(shù)值。
所以,我們在shell腳本中不能將127,126等數(shù)值定義為返回值,否則無法區(qū)分中是shell的返回值,還是調(diào)用shell腳本異常的原因值。shell腳本中的返回值最好多1開始遞增。
fork-exec機制
此機制用于執(zhí)行一個新的進程。System函數(shù)的內(nèi)部實現(xiàn)采用的也是fork-exec機制,下面是fork-exec的一個示例:
#include <stdlib.h> #include <unistd.h> #include <stdio.h>int main(int argc, char *argv[]) {pid_t pid =0;pid = fork();if (pid <0){printf("forkerror!\n");exit(-1);}else if (0 ==pid){//childprocesschar* const szArgs[] = {"sleep", "10", NULL}; // bookmark:1if(-1== execvp("/bin/sleep", szArgs)){printf("execvperror!\n");_exit(-1);}}else{//parentprocesscharszCmd[64]={0};snprintf(szCmd,sizeof(szCmd), "kill -9 %d", pid); // bookmark:2//system(szCmd); //to cause unormal terminate, you canannotate it intstatus= 0;pid= wait(&status);if(WIFEXITED(status)) // normal terminate{if(0 == WEXITSTATUS(status)){printf("processexecute success, exit code=%d", status);}else{printf("processexecute failed, exit code = %d, WEXITSTATUS(status) = %d",status,WEXITSTATUS(status));}}else{printf("processterminated unormally, pid = %d, status = %d, WEXITSTATUS(status) = %d\n",pid, status, WEXITSTATUS(status));}}return 0; }運行看看,一探究竟:
1)?????? 當(dāng)把bookmark:1下面的 sleep改為ssleep時(即命令不正確),輸出結(jié)果為
execvp error!
process execute failed, exit code = 64256, WEXITSTATUS(status)= 255
表明execvp返回-1,捕獲的WEXITSTATUS(status)=255(-1), 但這種情況算正常終止,WIFEXITED(status) 非0.
2)?????? 當(dāng)把 bookmark:2 下面的system語句注釋掉,輸出結(jié)果為:
process terminated unormally, pid = 17584, status = 9,WEXITSTATUS(status) = 0
表明程序非正常終止,WIFEXITED(status) == 0.
總結(jié):
從程序運行的結(jié)果看,可以得出幾條結(jié)論:當(dāng)exec shell命令不存在或沒有執(zhí)行權(quán)限時,execvp執(zhí)行的進程仍算正常終止,而當(dāng)execvp運行期間被終止時,算異常終止。
說明:
子進程的結(jié)束狀態(tài)返回后存于status,底下有幾個宏(位于頭文件sys/wait.h)可判別結(jié)束情況:
WIFEXITED(status)如果子進程正常結(jié)束則為非0值。
WEXITSTATUS(status)取得子進程exit()返回的結(jié)束代碼,一般會先用WIFEXITED來判斷是否正常結(jié)束才能使用此宏。
WIFSIGNALED(status)如果子進程是因為信號而結(jié)束則此宏值為真
WTERMSIG(status)取得子進程因信號而中止的信號代碼,一般會先用WIFSIGNALED 來判斷后才使用此宏。
WIFSTOPPED(status)如果子進程處于暫停執(zhí)行情況則此宏值為真。一般只有使用WUNTRACED 時才會有此情況。
WSTOPSIG(status)取得引發(fā)子進程暫停的信號代碼,
參考鏈接:
http://blog.chinaunix.net/uid-10554711-id-2948333.html
http://blog.csdn.net/cheyo/article/details/6595955
轉(zhuǎn)載于:https://www.cnblogs.com/OpenLinux/p/5020702.html
總結(jié)
以上是生活随笔為你收集整理的system函数和fork-exec机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java设计模式 之 工厂方法模式
- 下一篇: 为啥泰山如此值得一游?