system() 浅析

最近有用到system()调用,对它的返回值非常模糊,先贴下源码,如下:

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被信号暂停执行,取得信号值
}


未完待续...

你可能感兴趣的:(system() 浅析)