system系统函数的功能是在c语言调用运行bash脚本的,只要是在bash可以运行的脚本,放在system函数中都可以运行.
其中命令行下的脚本是运行在当前bash环境下的.而对于脚本(.sh文件)或者system调用,是需要重新启动一个进程bash.我电脑ubuntu14.04默认启动的是/bin/sh,链接到的是dash,这个轻量级的bash.到底是bash还是dash,可以通过下面的命令查看.
dash和bash
dash和bash都是遵循posix标准的系统应用,dash相比于bash有更快的运行速度.关于详细介绍可以参看下面几篇介绍.
大概介绍:https://www.cyberciti.biz/faq/debian-ubuntu-linux-binbash-vs-bindash-vs-binshshell/
详细介绍:https://wiki.ubuntu.com/DashAsBinSh
性能对比:https://wiki.debian.org/DebianEeePC/Dash
基于性能的考虑,/bin/sh是调用dash,所以在运行($sh *.sh)命令的时候,是调用dash,作为其运行环境.而对于system函数也是调用/bin/sh.也就是在dash的环境下运行命令.
system(cmdstring)
system函数
概述
system函数通过/bin/sh-c执行命令行命令,在执行过程中,system函数会阻塞SIGCHLD信号(等待子进程返回,否则返回值会出现错误),会忽略SIGINT和SIGQUIT信号.
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函数主要就是通过在子进程中执行/bin/sh -c cmdstring实现,主要涉及的是三个函数,fork,execl和waitpid
1.fork();创建一个子进程,如果创建失败,返回值为-1;
2.execl(“/bin/sh”,”sh”,”-c”,cmdstring,(char*)0);执行失败返回127.
3.如果三个函数都执行成功,那么函数的返回值为0;
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
int main(int argc,char*argv[]){
int status = mysystem("ls -l");
printf("status = %d\n",status);
return 0;
}
int mysystem(const char *cmdstring){
int status;
int pid = fork();
if(pid==-1){
return -1;
}
if(pid==0){
//system("ps");
int e_status;
if((e_status = execl("/bin/sh","sh","-c",cmdstring,(char*)0))<0){
printf("hello world %d\n",e_status);
exit(127);
}
//Even though execl excute successly,this can not be excuted.
//printf("hello world %d",e_status);
}
printf("the pid of child %d\n",pid);
waitpid(pid,&status,0);
return status;
}
system函数默认是忽略SIGINT(ctrl+c),SIGQUIT(ctrl+)信号的,上述的实现并没有涉及忽略这两个信号.因为不怎么熟悉如何忽略信号,之后再来补上,贴一篇比较完整的博客:http://blog.youkuaiyun.com/dlutbrucezhang/article/details/8914772
可以通过下面的代码测试这两个信号是被忽略的.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main(int argc,char *argv[]){
while(1){
system("ps");
}
return 0;
}
发现,陷入死循环,ctrl+c和ctrl+\都无法停止.说明两个信号都被忽略了.ctrl+z挂起,可以正常停止.