system

一、头文件与原型

#include "stdlib.h"    

#include "sys/wait.h"    

#include "sys/types.h"

int system(const char *command);

二、执行流程

阶段1:创建子进程等准备工作(fork)。如果失败,返回-1。

阶段2:调用/bin/sh拉起shell脚本(应用程序)(execl("/bin/sh", "sh","-c"command,(char *)0),

       如果拉起失败或者shell未正常执行结束(比如命令是非法的、不存在的),原因值被写入到status的低8~15比特位中。

阶段3:如果shell脚本(应用程序)正常执行结束(waitpid),将shell返回值(或者command通过exit或者return返回的值)填到status的低8~15比特位中。

阶段3的正常执行:执行shell脚本(或应用程序)过程中没有被其他信号异常中断,都算正常结束。

阶段3的异常执行:shell脚本(或应用程序)执行过程中被强制kill掉等情况

附:

system和popen_子进程

三、返回值

1.system函数的返回值:

-1:出现错误 

0:调用成功但是没有出现子进程 

>0:成功退出的子进程的id

2.判断返回值的函数

还需要再判断,操作成功或者操作失败。

常用宏:

WIFEXITED(status) :子进程正常退出会返回非零值

WEXITSTATUS(status) :子进程exit()或者return返回的值(status的低8~15数据),一般先用WIFEXITED 来判断是否正常结束再使用此宏。

不常用宏:

WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真

WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。

WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。

WSTOPSIG(status)取得引发子进程暂停的信号代码

四、注意事项

调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略

五、例程

#include "stdio.h"

#include "stdlib.h"    

#include "sys/wait.h"    

#include "sys/types.h"

int main(int argc, char **argv)

{

    int ret= 0;

    ret= system(command);  

    if(ret == -1){

        printf("system run error\n");

        return -1;

    }else{

        if(WIFEXITED(ret)){

            if(WEXITSTATUS(ret) == 0){

                printf("child process run succeed\n");

                return 0;

            }else{

                printf("child process run error, exit code: %d\n", WEXITSTATUS(ret));

                return -1;

            }

        }else{

            printf("exit status = %d\n", WEXITSTATUS(ret));

            return -1;

        }

    }

popen

syste与popen

相同点

    system和popen都是执行了类似的运行流程,大致是fork->execl->return

区别

1. system在执行期间调用进程会一直等待shell命令执行完成(waitpid等待子进程结束)才返回

  popen无须等待shell命令执行完成就返回了

2. popen可以控制程序的输入或者输出,而system的功能明显要弱一点,比如无法将ls的结果用到程序中。

  如果不需要使用到程序的I/O数据流,那么system是最方便的。