《LINUX教學:進程管理之system 詳解》要點:
本文介紹了LINUX教學:進程管理之system 詳解,希望對您有用。如果有疑問,可以聯(lián)系我們。
#include<stdlib.h>
int system(const char *command);
首先要知道,system函數(shù)是c庫中的函數(shù),而不是系統(tǒng)調用.其實system函數(shù)使用起來并不復雜,難就難在對其返回值的理解.這個問題,下文會詳細分析.參數(shù)的話,很簡單,便是終端的命令即可.這是因為system函數(shù)的實現(xiàn)中調用了shell的緣故.
先寫個簡化版的system函數(shù)的實現(xiàn)過程.簡化是沒有考慮處理信號的問題.代碼如下:
#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>
int system(char * command)
{
int status;
pid_t child;
swicth(child = fork())
{
case -1:
return -1;
case 0:
execl("/bin/sh","sh","-c",command,NULL);
_exit(127);
default:
while(waitpid(child,&status,0)<0)
{
if(errno != EINTR)
{
status = -1;
break;
}
}
return status;
}
}
1)返回值為 “0” 或 “1”
這中情況一般不會出現(xiàn),只有當寫成system(NULL)時,才會出現(xiàn)這種結果.目的是為了檢測系統(tǒng)的shell是否可用.返回1表現(xiàn)shell可用,返回0表現(xiàn)shell不可用;這種情況在上訴代碼中看不出來,通過glibc庫中的源碼可以看出:
glibc-2.17/sysdeps/posix/system.c
int __libc_system(const char *line)
{
if(line == NULL)
return do_system("exit 0") == 0;
......
}
line指針指向的便是command命令行參數(shù),system函數(shù)調用do_system系統(tǒng)調用,當執(zhí)行“exit 0”(表示結束當前shell),執(zhí)行成功do_system返回0,說明shell可用.反之,shell不可用.
2)返回值為 -1
有兩個原因造成這樣的結果.第一,因為fork創(chuàng)建子進程失敗導致的.即“case -1”的情況,這中情況比較少見;第二,是不能正常處理子進程的“墓志銘”導致的,說白了,就是子進程的進程表在子進程結束時,沒有經過父進程處理,而本身銷毀了.這樣的效果是因為父進程中安插的處理SIGCHLD信號的處理函數(shù)是SIG_IGN,或者用戶設置了SA_NOCLDWAIT標志位導致,waitpid函數(shù)返回值為-1且全局變量errno的值為ECHLD;
例如:
signal(SIGCHLD,SIG_IGN); //出錯的根源
if( (status = system(command)) < 0 )
{
fprintf(stderr,"system return %d (%s)\n",status,strerror(errno));
return -2;
}
所以在使用system函數(shù)時,必定要判斷SIGCHLD是否被設置為SIG_IGN.
3)返回值為 _exit(127)的返回值
這種情況是因為程序運行到“case 0”中,execl函數(shù)執(zhí)行失敗后,執(zhí)行_exit函數(shù)導致的.闡明子進程無法執(zhí)行shell該shell命令.
4)返回值為shell執(zhí)行的過程的返回值
shell的終止狀態(tài)是其執(zhí)行最后一條命令的退出狀態(tài).這種情況下和獲取子過程的退出狀態(tài)一樣.通過如下宏獲取其退出狀態(tài):
綜上所述,可以給出一個system函數(shù)返回值斷定的例程:
if( (status == system(command))==-1 )
{
fprintf(stderr,"system() function return -1 (%s)\n",strerror(errno));
}
else if(WIFEXITED(status)&&WEXITSTATUS(status) == 127)
{
fprintf(stderr,"cannot invoke shell to exec command (%s)\n",strerror(enrrno));
}
else
print_wait_exit(status);
print_wait_exit函數(shù)就是上文中提到的獲取shell退出狀態(tài)的宏,根據(jù)必要去實現(xiàn)即可.
影響system函數(shù)執(zhí)行的旌旗燈號有三個:SIGCHLD、SIGINT和SIGQUIT旌旗燈號.
SIGCHLD信號:上文已經提過,它會影響waitpid函數(shù),發(fā)生競爭現(xiàn)象的出現(xiàn).調用system函數(shù)的進程可能還有其他的子進程,當然同樣也會有wait或waitpid函數(shù).當有SIGCHLD信號到來時,system函數(shù)中的waitpid函數(shù)和其他的wait或waitpid函數(shù)發(fā)生競爭狀態(tài),從而使得system執(zhí)行異常.所以system執(zhí)行期間會暫時屏蔽SIGCHLD信號;
SIGINT信號和SIGQUIT信號:調用system函數(shù)的進程會屏蔽這兩個信號.system函數(shù)創(chuàng)建的進程會恢復這兩個信號的默認處理狀態(tài).調用system函數(shù)的進程其實已經放棄了控制權,所以不克不及夠去終止進程.反之,system函數(shù)創(chuàng)建的進程當然就有了控制權,所以要恢復控制權.
本文永遠更新鏈接地址:
歡迎參與《LINUX教學:進程管理之system 詳解》討論,分享您的想法,維易PHP學院為您提供專業(yè)教程。