system函数和fork-exec机制
system函數
使用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的方式執行命令,如果命令之間用“; ”隔開,則可以執行多條指令。
system是一個同步函數,即執行完之后才會返回,內部實現也類似與fork-exec機制(執行期間會阻塞SIGCHLD信號,同時忽略SIGINT、SIGQUIT)。
如何判斷system是否執行成功:
1、?? fork成功:-1 != status
2、?? system命令是否正常終止:WIFEXITED(status)非0 ,非正常終止=0
3、?? 根據返回值判斷:WEXITSTATUS(status)== 0? //獲取system的返回值(低八位,可以理解為unsignedbyte);如果shell命令無法執行,則返回127,命令檢測到有錯誤,則返回1-126
注意:
當shell腳本不存在、沒有執行權限等場景下時,以上前2個條件仍會成立,此時WEXITSTATUS(status)為127,126等數值。
所以,我們在shell腳本中不能將127,126等數值定義為返回值,否則無法區分中是shell的返回值,還是調用shell腳本異常的原因值。shell腳本中的返回值最好多1開始遞增。
fork-exec機制
此機制用于執行一個新的進程。System函數的內部實現采用的也是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)?????? 當把bookmark:1下面的 sleep改為ssleep時(即命令不正確),輸出結果為
execvp error!
process execute failed, exit code = 64256, WEXITSTATUS(status)= 255
表明execvp返回-1,捕獲的WEXITSTATUS(status)=255(-1), 但這種情況算正常終止,WIFEXITED(status) 非0.
2)?????? 當把 bookmark:2 下面的system語句注釋掉,輸出結果為:
process terminated unormally, pid = 17584, status = 9,WEXITSTATUS(status) = 0
表明程序非正常終止,WIFEXITED(status) == 0.
總結:
從程序運行的結果看,可以得出幾條結論:當exec shell命令不存在或沒有執行權限時,execvp執行的進程仍算正常終止,而當execvp運行期間被終止時,算異常終止。
說明:
子進程的結束狀態返回后存于status,底下有幾個宏(位于頭文件sys/wait.h)可判別結束情況:
WIFEXITED(status)如果子進程正常結束則為非0值。
WEXITSTATUS(status)取得子進程exit()返回的結束代碼,一般會先用WIFEXITED來判斷是否正常結束才能使用此宏。
WIFSIGNALED(status)如果子進程是因為信號而結束則此宏值為真
WTERMSIG(status)取得子進程因信號而中止的信號代碼,一般會先用WIFSIGNALED 來判斷后才使用此宏。
WIFSTOPPED(status)如果子進程處于暫停執行情況則此宏值為真。一般只有使用WUNTRACED 時才會有此情況。
WSTOPSIG(status)取得引發子進程暫停的信號代碼,
參考鏈接:
http://blog.chinaunix.net/uid-10554711-id-2948333.html
http://blog.csdn.net/cheyo/article/details/6595955
轉載于:https://www.cnblogs.com/OpenLinux/p/5020702.html
總結
以上是生活随笔為你收集整理的system函数和fork-exec机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java设计模式 之 工厂方法模式
- 下一篇: 为啥泰山如此值得一游?