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掉等情况
附:
三、返回值
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是最方便的。