导读 曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入。这里必须要搞懂system()函数,因为有时你不得不面对它。

先来看一下system()函数的简单介绍:
#include
int system(const char *command)

system()函数调用/bin/sh来执行参数指定的命令,/bin/sh 一般是一个软连接,指向某个具体的shell,比如bash,-c选项是告诉shell从字符串command中读取命令; 在该command执行期间,SIGCHLD是被阻塞的,好比在说:hi,内核,这会不要给我送SIGCHLD信号,等我忙完再说; 在该command执行期间,SIGINT和SIGQUIT是被忽略的,意思是进程收到这两个信号后没有任何动作。

再来看一下system()函数返回值:

为了更好的理解system()函数返回值,需要了解其执行过程,实际上system()函数执行了三步操作:

  1. fork一个子进程;
  2. 在子进程中调用exec函数去执行command;
  3. 在父进程中调用wait去等待子进程结束。 对于fork失败,system()函数返回-1。 如果exec执行成功,也即command顺利执行完毕,则返回command通过exit或return返回的值。 (注意,command顺利执行不代表执行成功,比如command:"rm debuglog.txt",不管文件存不存在该command都顺利执行了) 如果exec执行失败,也即command没有顺利执行,比如被信号中断,或者command命令根本不存在,system()函数返回127. 如果command为NULL,则system()函数返回非0值,一般为1.

看一下system()函数的源码

看完这些,我想肯定有人对system()函数返回值还是不清楚,看源码最清楚,下面给出一个system()函数的实现:

int system(const char * cmdstring)
{
pid_t pid;
int status;
if(cmdstring == NULL)
{
return (1); //如果cmdstring为空,返回非零值,一般为1
}
if((pid = fork())<0)
{
status = -1; //fork失败,返回-1
}
else if(pid == 0)
{
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
_exit(127); // exec执行失败返回127,注意exec只在失败时才返回现在的进程,成功的话现在的
进程就不存在啦~~
}
else //父进程
{
while(waitpid(pid, &status, 0) < 0)
{
if(errno != EINTR)
{
status = -1; //如果waitpid被信号中断,则返回-1
break;
}
}
}
return status; //如果waitpid成功,则返回子进程的返回状态
}

仔细看完这个system()函数的简单实现,那么该函数的返回值就清晰了吧,那么什么时候system()函数返回0呢?只在command命令返回0时。

看一下该怎么监控system()函数执行状态 这里给我出的做法:
int status;
if(NULL == cmdstring) //如果cmdstring为空趁早闪退吧,尽管system()函数也能处理空指针
{
return XXX;
}
status = system(cmdstring);
if(status < 0)
{
printf("cmd: %s\t error: %s", cmdstring, strerror(errno)); // 这里务必要把errno信息输出或
记入Log
return XXX;
} if(WIFEXITED(status))
{
printf("normal termination, exit status = %d\n", WEXITSTATUS(status)); //取得cmdstring执行结果 }
else if(WIFSIGNALED(status))
{
printf("abnormal termination,signal number =%d\n", WTERMSIG(status)); //如果cmdstring被信号中
断,取得信号值
}
else if(WIFSTOPPED(status))
{
printf("process stopped, signal number =%d\n", WSTOPSIG(status)); //如果cmdstring被信号暂停执
行,取得信号值
}

system()函数用起来很容易出错,返回值太多,而且返回值很容易跟command的返回值混淆。这里推荐使用popen()函数替代,关于popen()函数的简单使用可以自己查下资料。

popen()函数较于system()函数的优势在于使用简单,popen()函数只返回两个值: 成功返回子进程的status,使用WIFEXITED相关宏就可以取得command的返回结果; 失败返回-1,我们可以使用perro()函数或strerror()函数得到有用的错误信息。

这篇文章只涉及了system()函数的简单使用,还没有谈及SIGCHLD、SIGINT和SIGQUIT对system()函数的影响,事实上,之所以今天写这篇文章,是因为项目中因有人使用了system()函数而造成了很严重的事故。现像是system()函数执行时会产生一个错误:“No child processes”。此时调用my_system()来执行system函数的功能(my_system函数中是使用popen()函数来实现的), 测试了一天,没有再次出现程序突然死掉的问题(修改前连续循环调用system()函数测试,每10次就会至少导致程序挂掉一次.连续不停顿的调用)。

本文地址:http://www.linuxprobe.com/linux-system-constructors.html

关于linux下system()函数的总结的更多相关文章

  1. 对于linux下system()函数的深度理解(整理)

    原谅: http://blog.sina.com.cn/s/blog_8043547601017qk0.html 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同 ...

  2. 转:对于linux下system()函数的深度理解(整理)

    这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为 ...

  3. 【C/C++】Linux下system()函数引发的错误

    http://my.oschina.net/renhc/blog/54582 [C/C++]Linux下system()函数引发的错误 恋恋美食  恋恋美食 发布时间: 2012/04/21 11:3 ...

  4. (笔记)Linux下system()函数的深度理解(整理)

    注:从其它地方转的非常好的一篇文章,值得深究! 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数 ...

  5. [转载]关于linux下system()函数的总结

    1.曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入.这里必须要搞懂system()函数,因为有时你不得不面对它. 2.先来看一下system()函数的简 ...

  6. Linux下system函数

    http://www.jb51.net/article/40517.htm   浅析如何在c语言中调用Linux脚本 http://blog.csdn.net/koches/article/detai ...

  7. Linux下system()函数的实现

    #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types. ...

  8. linux下syscall函数,SYS_gettid,SYS_tgkill

    出处:http://blog.chinaunix.net/uid-28458801-id-4630215.html     linux下syscall函数,SYS_gettid,SYS_tgkill  ...

  9. Linux下c函数dlopen实现加载动态库so文件代码举例

    dlopen()是一个强大的库函数.该函数将打开一个新库,并把它装入内存.该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的.这种机制使得在系统中添加或者删除一个模块时,都不需要重新编译了. ...

随机推荐

  1. BZOJ 2743 【HEOI2012】 采花

    题目链接:采花 这道题一眼看去,一个很显然的想法就是莫队.但是数据范围是\(10^6\)级别的,莫队显然已经过不去了. 其实感觉这道题和以前写过的一道题HH的项链很像.只不过那道题要求的是区间出现次数 ...

  2. linux查看主板型号及内存硬件信息

      公司服务器内存不够用了. 想看看买啥型号的. 购买内存条注意点: ddr3 or4 频率 块钱. 内存槽及内存条: dmidecode |grep -A16 "Memory Device ...

  3. [LeetCode] Valid Anagram 验证变位词

    Given two strings s and t, write a function to determine if t is an anagram of s. For example, s = & ...

  4. [LeetCode] First Missing Positive 首个缺失的正数

    Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2,0]  ...

  5. KPI:Key Performance Indicator

    通信中KPI,是Key Performance Indicators的缩写,意思是关键性能指标.performance 还有绩效:业绩的意思,但显然不适用于这种场合. 通信中KPI的内容有:掉话率.接 ...

  6. 从2G到5G, 基站天线过去与未来

    在蜂窝移动通信系统中,天线是电路信号与空间辐射电磁波的转换器,是移动通信系统的末梢关键组成部分. 从2G到4G,移动基站天线经历了全向天线.定向单极化天线.定向双极化天线.电调单极化天线.电调双极化天 ...

  7. hihocoder-1453-Rikka with Tree

    #Hihocoder 1453 : Rikka with Tree 时间限制:10000ms 单点时限:1000ms 内存限制:256MB   source: https://hihocoder.co ...

  8. Android 使用代码主动去调用控件的点击事件(模拟人手去触摸控件)

    使用代码主动去调用控件的点击事件(模拟人手去触摸控件) //View 可以是LinearLayout,Button,TextView View.performClick();

  9. 《UNIX环境高级编程》笔记——1.UNIX基础知识

    这一章节侧重一些基本概念和书中用到的一些名词. 一.引言 所有的操作都提供服务,典型的服务包括:执行新程序.打开文件.读写文件.分配存储区以及获得当前时间等. 二.UNIX体系结构 其实linux常见 ...

  10. Android基础总结(五)

    HttpClient 发送get请求 创建一个客户端对象 HttpClient client = new DefaultHttpClient(); 创建一个get请求对象 HttpGet hg = n ...