《unix高级环境编程》进程控制——system函数

时间:2023-01-08 14:52:48

system函数

system 函数能够执行函数中参数的命令,实现如下:

/* system 函数 */
#include <stdlib.h>
int system(const char *cmdstring);
首先我们看下该函数的具体实现:

/* system 函数的实现 */
#include "apue.h"
#include <sys/wait.h>

int system(const char *cmdstring)
{
pid_t pid;
int status;

if(NULL == cmdstring)
return -1;
if((pid = fork()) < 0)
status = -1;
else if(0 == pid)
{
execl("/bin/sh", "sh", "-c", "cmdstring", (char *)0);
_exit(127);
}
else
{
while(waitpid(pid,&status,0) < 0)
{
if(errno != EINTR)
{
status = -1;
break;
}
}
}
return status;
}
  从该函数的实现我们可以知道,在现有进程中调用 fork 函数创建新的子进程,在 fork 所返回的子进程中调用execl 函数执行参数字符命令,在 fork 所返回父进程中调用 waitpid 函数等待进程终止;因此有下面的三个返回值:

  1. 如果 fork 失败或者waitpid 返回值除 EINTR 之外的出错,则system 返回-1,而且errno 中设置了错误类型值;
  2. 如果 exec失败(表示不能执行 shell),其返回值如同 shell 执行 exit(127)一样;
  3. 否则所有三个函数(fork、exec、waitpid)都执行成功,并且system的返回值是 shell 的终止状态;
测试程序:

#include <sys/wait.h>
#include "apue.h"

void pr_exit(int status)
{
if(WIFEXITED(status))
printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
else if(WIFSIGNALED(status))
printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? "(core file generated)" : " ");
#else
" ");
#endif

else if(WIFSTOPPED(status))
printf("child stoped, signal number = %d\n", WSTOPSIG(status));
}

int main(void)
{
int status;

if((status = system("date")) < 0)
err_sys("system error");
pr_exit(status);

if((status = system("nosuchcommand")) < 0)
err_sys("system error");
pr_exit(status);

if((status = system("stat;who; exit 44")) < 0)
err_sys("system error");
pr_exit(status);

exit(0);
}
返回值:

Fri Nov  7 19:19:17 CST 2014
normal termination, exit status = 0
sh: nosuchcommand: command not found
normal termination, exit status = 127
stat: missing operand
Try `stat --help' for more information.
nifengweijifen tty7 2014-11-07 08:44
nifengweijifen pts/1 2014-11-07 08:57 (:0.0)
nifengweijifen pts/4 2014-11-07 14:44 (:0.0)
normal termination, exit status = 44
测试程序2:

#include <sys/wait.h>
#include "apue.h"

void pr_exit(int status)
{
if(WIFEXITED(status))
printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
else if(WIFSIGNALED(status))
printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? "(core file generated)" : " ");
#else
" ");
#endif

else if(WIFSTOPPED(status))
printf("child stoped, signal number = %d\n", WSTOPSIG(status));
}

int main(int argc, char *argv[])
{
int status;
if(argc != 2)
{
printf("usage: a.out <cmdstring>\n");
exit(1);
}
status = system(argv[1]);
pr_exit(status);

exit(0);
}
以上程序可以根据自己需要输入要执行的字符命令参数。假设编译成可执行文件system,例如输入./system date,输出如下:

Fri Nov  7 19:28:43 CST 2014
normal termination, exit status = 0

参考资料:

《UNIX 高级环境编程》