inux 下system函数原型:http://blog.chinaunix.net/uid-29191363-id-4020441.html
2015-10-02 14:28
459 查看
inux 下system函数原型:
#include
int system(const char *command);
system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.
system函数的返回值比较多,且存在相同的值却代表着不同的意思,针对以上问题对源码进行分析。
Libc-2.9 下sysdeps\posi\system.c源码:
点击(此处)折叠或打开
int system (const char *line)
{
return __libc_system (line);
}
int __libc_system (const char *line) /*system函数实际上调用的是do_system函数*/
{
if (line == NULL)
/* Check that we have a command processor available. It might
?not be available after a chroot(), for example. */
return do_system ("exit 0") == 0; /* 当line为NULL时,返回值为0,及执行bash
–c exit 0*/
if (SINGLE_THREAD_P)
return do_system (line);
/*GCC cleanup exception range can cover the
LIBC_CANCEL_ASYNC() and LIBC_CANCEL_RESET():http://sourceware.org/ml/libc-alpha/2011-08/msg00063.html */
int oldtype = LIBC_CANCEL_ASYNC ();
int result = do_system (line);
LIBC_CANCEL_RESET (oldtype);
return result;
}
weak_alias (__libc_system, system) /* weak_alias
别名 */
/*通过以上分析system函数实际上调用的是do_system函数, 以下对do_system函数进行分析,以下列出主要函数:*/
/* Execute LINE as a shell command, returning its status. */
do_system (const char *line)
{
int status, save;
pid_t pid;
struct sigaction sa;
#ifndef _LIBC_REENTRANT
struct sigaction intr, quit;
#endif
sigset_t omask;
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
__sigemptyset (&sa.sa_mask);
DO_LOCK (); /* mutex
lock*/
if (ADD_REF () == 0)
{
if (__sigaction (SIGINT, &sa, &intr) < 0) /*执行时
SIGINT被忽略*/
{
SUB_REF ();
goto out;
}
if (__sigaction (SIGQUIT, &sa, &quit) < 0) /*执行时
SIGQUIT被忽略*/
{
save = errno;
SUB_REF ();
goto out_restore_sigint;
}
}
DO_UNLOCK ();
/* We reuse the bitmap in the 'sa' structure. */
__sigaddset (&sa.sa_mask, SIGCHLD);
save = errno;
if (__sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0) /*执行时设置SIG_BLOCK标志位,SIGCHLD被阻塞,执行失败,则恢复之前的信号的bitmap*/
{
#ifndef _LIBC
if (errno == ENOSYS)
__set_errno (save);
else
#endif
{
DO_LOCK ();
if (SUB_REF () == 0)
{
save = errno;
(void) __sigaction (SIGQUIT, &quit, (struct
sigaction *) NULL);
out_restore_sigint:
(void) __sigaction (SIGINT, &intr, (struct
sigaction *) NULL);
__set_errno (save);
}
out:
DO_UNLOCK ();
return -1;
}
}
#ifdef CLEANUP_HANDLER
CLEANUP_HANDLER;
#endif
/*执行成功,调用fork,生成子进程执行command命令*/
#ifdef FORK
pid = FORK (); /*调用SYS_CALL生成子进程*/
#else
pid = __fork ();
#endif
if (pid == (pid_t) 0) //
{
/* Child side. */
const char *new_argv[4];
new_argv[0] = SHELL_NAME;
new_argv[1] = "-c";
new_argv[2] = line;
new_argv[3] = NULL;
/* Restore the signals. */
(void) __sigaction (SIGINT, &intr, (struct
sigaction *) NULL);
(void) __sigaction (SIGQUIT, &quit, (struct
sigaction *) NULL);
(void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
INIT_LOCK ();
/* Exec the shell. */
(void) __execve (SHELL_PATH, (char *const *) new_argv, __environ);
_exit (127); /*exec执行失败则返回127*/
}
else if (pid < (pid_t) 0)
/* The fork failed. */
status = -1;
else /*父进程,waitpid*/
/* Parent side. */
{
/* Note the system() is a
cancellation point. But since we call
waitpid() which itself is a cancellation point we do not
have to do anything here. */
if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid)
status = -1; /*waitpid
失败返回1*/
}
#ifdef CLEANUP_HANDLER
CLEANUP_RESET;
#endif
save = errno;
DO_LOCK ();
if ((SUB_REF () == 0
&& (__sigaction (SIGINT, &intr, (struct
sigaction *) NULL)
| __sigaction (SIGQUIT, &quit, (struct
sigaction *) NULL)) != 0)
|| __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
{
#ifndef _LIBC
/* glibc cannot be used on systems without waitpid. */
if (errno == ENOSYS)
__set_errno (save);
else
#endif
status = -1;
}
DO_UNLOCK ();
return status;
}
总结:system函数的返回值:分2大类:
(1) 当参数为空时,调用do_system ("exit 0"),返回值为NULL /*网上都说是返回非0值,但我测的是NULL
!!!!*/
(2) 调用result = do_system (line);
当执行忽略SIGINT和SIGQUIT信号时,错误返回-1
fork子进程时出现错误 返回值为-1
当exec执行错误或命令无效时返回值为127
当waitpid错误时 返回值为-1
if(NULL == cmdstring) //如果cmdstring为空趁早闪退吧,尽管system()函数也能处理空指针
以下可以得到返回值错在什么位置,相关知识详见APUE(摘录的具体位置忘了,作者看到后请留言)
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被信号暂停执行,取得信号值
}
#include
int system(const char *command);
system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will be ignored.
system函数的返回值比较多,且存在相同的值却代表着不同的意思,针对以上问题对源码进行分析。
Libc-2.9 下sysdeps\posi\system.c源码:
点击(此处)折叠或打开
int system (const char *line)
{
return __libc_system (line);
}
int __libc_system (const char *line) /*system函数实际上调用的是do_system函数*/
{
if (line == NULL)
/* Check that we have a command processor available. It might
?not be available after a chroot(), for example. */
return do_system ("exit 0") == 0; /* 当line为NULL时,返回值为0,及执行bash
–c exit 0*/
if (SINGLE_THREAD_P)
return do_system (line);
/*GCC cleanup exception range can cover the
LIBC_CANCEL_ASYNC() and LIBC_CANCEL_RESET():http://sourceware.org/ml/libc-alpha/2011-08/msg00063.html */
int oldtype = LIBC_CANCEL_ASYNC ();
int result = do_system (line);
LIBC_CANCEL_RESET (oldtype);
return result;
}
weak_alias (__libc_system, system) /* weak_alias
别名 */
/*通过以上分析system函数实际上调用的是do_system函数, 以下对do_system函数进行分析,以下列出主要函数:*/
/* Execute LINE as a shell command, returning its status. */
do_system (const char *line)
{
int status, save;
pid_t pid;
struct sigaction sa;
#ifndef _LIBC_REENTRANT
struct sigaction intr, quit;
#endif
sigset_t omask;
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
__sigemptyset (&sa.sa_mask);
DO_LOCK (); /* mutex
lock*/
if (ADD_REF () == 0)
{
if (__sigaction (SIGINT, &sa, &intr) < 0) /*执行时
SIGINT被忽略*/
{
SUB_REF ();
goto out;
}
if (__sigaction (SIGQUIT, &sa, &quit) < 0) /*执行时
SIGQUIT被忽略*/
{
save = errno;
SUB_REF ();
goto out_restore_sigint;
}
}
DO_UNLOCK ();
/* We reuse the bitmap in the 'sa' structure. */
__sigaddset (&sa.sa_mask, SIGCHLD);
save = errno;
if (__sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0) /*执行时设置SIG_BLOCK标志位,SIGCHLD被阻塞,执行失败,则恢复之前的信号的bitmap*/
{
#ifndef _LIBC
if (errno == ENOSYS)
__set_errno (save);
else
#endif
{
DO_LOCK ();
if (SUB_REF () == 0)
{
save = errno;
(void) __sigaction (SIGQUIT, &quit, (struct
sigaction *) NULL);
out_restore_sigint:
(void) __sigaction (SIGINT, &intr, (struct
sigaction *) NULL);
__set_errno (save);
}
out:
DO_UNLOCK ();
return -1;
}
}
#ifdef CLEANUP_HANDLER
CLEANUP_HANDLER;
#endif
/*执行成功,调用fork,生成子进程执行command命令*/
#ifdef FORK
pid = FORK (); /*调用SYS_CALL生成子进程*/
#else
pid = __fork ();
#endif
if (pid == (pid_t) 0) //
{
/* Child side. */
const char *new_argv[4];
new_argv[0] = SHELL_NAME;
new_argv[1] = "-c";
new_argv[2] = line;
new_argv[3] = NULL;
/* Restore the signals. */
(void) __sigaction (SIGINT, &intr, (struct
sigaction *) NULL);
(void) __sigaction (SIGQUIT, &quit, (struct
sigaction *) NULL);
(void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
INIT_LOCK ();
/* Exec the shell. */
(void) __execve (SHELL_PATH, (char *const *) new_argv, __environ);
_exit (127); /*exec执行失败则返回127*/
}
else if (pid < (pid_t) 0)
/* The fork failed. */
status = -1;
else /*父进程,waitpid*/
/* Parent side. */
{
/* Note the system() is a
cancellation point. But since we call
waitpid() which itself is a cancellation point we do not
have to do anything here. */
if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid)
status = -1; /*waitpid
失败返回1*/
}
#ifdef CLEANUP_HANDLER
CLEANUP_RESET;
#endif
save = errno;
DO_LOCK ();
if ((SUB_REF () == 0
&& (__sigaction (SIGINT, &intr, (struct
sigaction *) NULL)
| __sigaction (SIGQUIT, &quit, (struct
sigaction *) NULL)) != 0)
|| __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
{
#ifndef _LIBC
/* glibc cannot be used on systems without waitpid. */
if (errno == ENOSYS)
__set_errno (save);
else
#endif
status = -1;
}
DO_UNLOCK ();
return status;
}
总结:system函数的返回值:分2大类:
(1) 当参数为空时,调用do_system ("exit 0"),返回值为NULL /*网上都说是返回非0值,但我测的是NULL
!!!!*/
(2) 调用result = do_system (line);
当执行忽略SIGINT和SIGQUIT信号时,错误返回-1
fork子进程时出现错误 返回值为-1
当exec执行错误或命令无效时返回值为127
当waitpid错误时 返回值为-1
if(NULL == cmdstring) //如果cmdstring为空趁早闪退吧,尽管system()函数也能处理空指针
以下可以得到返回值错在什么位置,相关知识详见APUE(摘录的具体位置忘了,作者看到后请留言)
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被信号暂停执行,取得信号值
}
相关文章推荐
- 解决Unable to find the wrapper "https"的二种方法
- HTTP协议
- java公众平台通用接口工具类HttpConnectUtil
- 黑马程序员————Java网络通讯编程详解
- Linux网络配置总结
- TCP/IP详解卷1 读书笔记:第六章 ICMP 网际报文控制协议
- 现代网络应用中的UI设计-CH1
- TCP/IP详解笔记
- HttpUrlConnection编程
- HttpClient客户端
- 博客10:Linux的网络管理
- 博客10:Linux的网络管理
- socket网络编程
- TCP/IP、Http、Socket的区别
- HTTPCLIENT MultipartEntity 上传中文乱码
- 转自牛客网-计算机网络基础相关
- http://jinnianshilongnian.iteye.com/blog/2018936
- win8搜索不到wifi怎么办?windows8搜索不到无线网络解决方法图解
- 网络原理,以及对VMware Workstation虚拟网络VMnet0、VMnet1、VMnet8的图解
- http://blog.sina.com.cn/s/blog_641926f30100trj1.html popen/pclose解析