说明

  • system是标准库中定义的函数接口,在window和Linux上都得到了实现。

函数介绍

  • 功 能: 执行一条脚本命令(windows平台的DOS命令或者linux平台的shell命令)。
  • 函数声明
#include <stdlib.h>

int system(const char *command);
  • 例子:
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
  system("ls");
  return 0;
}

实现原理

  • linux平台system函数源码
int system(const char * cmdstring)
{
  pid_t pid;
  int status;

  if(cmdstring == NULL){
      return (1);
  }

  if((pid = fork())<0){
        status = -1;
  } else if(pid == 0){
    execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
    -exit(127); //子进程正常执行则不会执行此语句
    }
    else{
        while(waitpid(pid, &status, 0) < 0){
          if(errno != EINTER){
            status = -1;
            break;
          }
        }
    }
    return status;
}
  • man中描述
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.
  • 创建一个进程,在该进程中通过sh -c 来执行传入的命令,并且阻塞直到命令执行完成,在执行过程中,SIGCHLD信号将会被阻塞,SIGINT和SIGQUIT信号将会被忽略。

优缺点

优点

  1. 使用非常简单方便。
  • 能够非常简单的实现执行第三方程序或者命令。

缺点

  1. 性能低
  • 创建和销毁进程都需要消耗系统资源,并且为了保证通用,system需要采用sh -c 的方式执行命令,需要创建一个shell环境,性能不高。
  • 测试发现通过system调用md5sum和调用相同md5sum库接口,运行时长有10倍的差距。
  1. 部分信号被忽略
  • SIGINT和SIGQUIT信号将会被忽略,如果程序中涉及到信号处理,进程可能由于信号被忽略,导致运行异常。

使用

不要图方便而使用

  • 在嵌入式开发中,由于采用C语言开发,C语言功能不强大,很多功能没有库等原因,在中小公司中时常看到system的滥用,例如:system(“rm”); system(“touch xxx”);等基本功能。
  • mkdir,rm, touch这些简单的命令,本质上是一个二进制程序,也是调用的系统接口实现的,
  • 我们不应该图使用简单就直接使用system去调用这些命令,会降低性能,可以直接调用系统接口。

获取运行结果

  • 如果第三方程序实现较为复杂,没有提供库,必须采用system的形式调用,我们也需要注意获取其运行结果。
  • 程序使用exit函数来设置进程的退出值时,虽然exit函数的参数类型为int型,但是父进程中只能取到其值的低8位.所以用exit返回值时,高于255的值是没有意义的。
  • system函数,返回值是int类型,由两部分组成的,低8位值表示所执行的脚本在执行过程中所接收到的信号值,其余的位表示的脚本exit退出时所设置的值。
  • 可以使用三个宏来获取命令运行结果。
  1. 判断子进程是否正常退出,是的话,以下宏返回非0
WIFEXITED(int status)
  1. 如果子进程正常退出,可通过以下宏获得子进程exit()返回的结束值,先要用WIFEXITED判断是否正常结束。
WEXITSTATUS(int status)
  1. 如果子进程是因为信号而中断结束则以下宏值为真。
WIFSIGNALED(int status)
  • 使用例子:
int get_system_return(const char *cmd)
{
    int status = system(cmd);
    if (WIFEXITED(status))
    {
        return WEXITSTATUS(status);
    }
    return -1;
}