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

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

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

3、再来看一下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.
4、看一下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时。

5、看一下该怎么监控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次就会至少导致程序挂掉一次.连续不停顿的调用)。

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

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

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

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

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

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

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

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

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

  5. 关于linux下system()函数的总结

    导读 曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入.这里必须要搞懂system()函数,因为有时你不得不面对它. 先来看一下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下VMware虚拟机根目录空间扩充

    [转载]实战Linux下VMware虚拟机根目录空间扩充 (2011-07-31 21:34:34) 转载▼ 标签: 转载   原文地址:实战Linux下VMware虚拟机根目录空间扩充作者:shar ...

  9. linux select函数:Linux下select函数的使用详解【转】

    本文转载自;http://www.bkjia.com/article/28216.html Linux下select函数的使用 Linux下select函数的使用 一.Select 函数详细介绍 Se ...

随机推荐

  1. Ubuntu: 无法使用su命令

    Ubuntu 无法使用su命令解决方案 在Ubuntu上编译Qt环境时发现无法使用su命令切换到root用户,通过网上查找发现解决方案如下: xt@xt-ubuntu:~$ su密码: su:认证失败 ...

  2. iOS应用网络安全之HTTPS

    移动互联网开发中iOS应用的网络安全问题往往被大部分开发者忽略,iOS9和OS X 10.11开始Apple也默认提高了安全配置和要求.本文以iOS平台App开发中对后台数据接口的安全通信进行解析和加 ...

  3. Windows10提示“没有权限使用网络资源”的解决方案

    1.点击“开始→运行”,在“运行”对话框中输入“GPEDIT.MSC”,打开组策略编辑器 2.依次选择“计算机配置→Windows设置→安全设置→本地策略→用户权利分配” 3.双击“拒绝从网络访问这台 ...

  4. 【转载】关于C++中cin的几点说明性总结

    转载地址:http://www.07net01.com/program/289153.html 学C++的时候,这几个输入函数弄的有点迷糊:这里做个小结: 1.cin 2.cin.get() 3.ci ...

  5. 使用Shell脚本查找程序对应的进程ID,并杀死进程

    #!/bin/sh NAME='shell.php' echo $NAME ID=`ps -ef | grep "$NAME" | grep -v "$0" | ...

  6. 基于netty的异步http请求

    package com.pt.utils; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; im ...

  7. 红米1S.线刷

    ZC:遇到问题:“Missmatching image and device”,解决网址:“[2.23][史上最全]MiFlash线刷错误的那些事儿_收藏备用_小米手机4_MIUI论坛.html”(h ...

  8. MFC 去掉CWnd的边框

    使用继承CWnd的控件,总是有边框,使用 ModifyStyle(WS_BORDER,0);  不能去掉边框,包括SetWindowLong设置去掉WS_BORDER, 也不行. 最后找到了方法就是M ...

  9. java:BufferedReader接受输入进来的2个数字,并将它们相加

    java:BufferedReader接受输入进来的2个数字,并将它们相加 //接受输入进来的2个数字,并将它们相加 BufferedReader buf = null; buf = new Buff ...

  10. Mybatis_总结_06_用_插件开发

    一.前言 Mybatis采用责任链模式,通过动态代理组织多个插件(拦截器),通过这些插件可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的 ...