system() 淺析

最近有用到system()調用,對它的返回值很是模糊,先貼下源碼,以下:shell

int system(const char *command)
{
	pid_t pid;
	sig_t intsave, quitsave;
	sigset_t mask, omask;
	int pstat;
	char *argp[] = {"sh", "-c", NULL, NULL};

	if (!command)		/* just checking... */
		return(1);

	argp[2] = (char *)command;

	sigemptyset(&mask);
	sigaddset(&mask, SIGCHLD);
	sigprocmask(SIG_BLOCK, &mask, &omask);
	switch (pid = vfork()) {
	case -1:			/* error */
		sigprocmask(SIG_SETMASK, &omask, NULL);
		return(-1);
	case 0:				/* child */
		sigprocmask(SIG_SETMASK, &omask, NULL);
		execve(_PATH_BSHELL, argp, environ); // 若是順利執行的話,該子進程上下文就被shell進程上下文給替換了
		_exit(127); //只有execve執行失敗,纔有可能執行這行代碼!
	}

	intsave = signal(SIGINT, SIG_IGN);
	quitsave = signal(SIGQUIT, SIG_IGN);
	pid = waitpid(pid, (int *)&pstat, 0); // 等待子進程退出,也有可能被信號中斷
	sigprocmask(SIG_SETMASK, &omask, NULL);
	(void)signal(SIGINT, intsave);
	(void)signal(SIGQUIT, quitsave);
	return (pid == -1 ? -1 : pstat); // 返回-1表明waitpid被信號中斷,不然返回pstat
	//這個pstat通常包含兩部分信息:最低 8 位, 表明命令是否被順利執行的信息, 再往高8位表明執行該命令的結果
}

如今讓咱們我看下返回的結果。
1 表明 command 爲 NULL
-1 表明 vfork 失敗 或者 waitpid 被中斷 
127 (0x7F) execve調用shell執行命令切換上下文不成功 (緣由多是 命令不存在或者系統沒有shell 等) 

pstat  須要經過下面幾個宏對命令是否被順利執行以及命令執行的結果

//1.肯定命令是否被順利執行
#define WIFEXITED(s)    (WTERMSIG(s) == 0) //命令被順利執行
#define WIFSTOPPED(s)   (WTERMSIG(s) == 0x7f)     //被信號暫停
#define WIFSIGNALED(s)  (WTERMSIG((s)+1) >= 2)   //被信號中斷

//2.查看命令執行的效果,以及出現沒執行完的緣由
#define WEXITSTATUS(s)  (((s) & 0xff00) >> 8)
#define WCOREDUMP(s)    ((s) & 0x80)
#define WTERMSIG(s)     ((s) & 0x7f)
#define WSTOPSIG(s)     WEXITSTATUS(s)


如來自http://my.oschina.net/renhc/blog/53580?fromerr=wEsSYHbL 的例子:函數

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被信號暫停執行,取得信號值
}


未完待續...ui

相關文章
相關標籤/搜索