您的位置:首页 > 理论基础 > 计算机网络

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

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: