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

导读 曾经的曾经,被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技术教程书籍,为开源技术爱好者努力做得更多更好:http://www.linuxprobe.com/

时间: 2024-12-29 07:55:04

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

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

对于linux下system()函数的深度理解(整理) (2013-02-07 08:58:54) 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为是其他的代码影响到这个,或是内核驱动文件系统什么的异常导致,昨天有出现了这个问题,就随手百了一下度,问题出现了,很多人都说system()函数要慎用要少用要能不用则不用,system()函数不稳定?

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

http://my.oschina.net/renhc/blog/54582 [C/C++]Linux下system()函数引发的错误 恋恋美食  恋恋美食 发布时间: 2012/04/21 11:33 阅读: 11393 收藏: 21 点赞: 8 评论: 4 今天,一个运行了近一年的程序突然挂掉了,问题定位到是system()函数出的问题,关于该函数的简单使用在我上篇文章做过介绍: http://my.oschina.net/renhc/blog/53580 先看一下问题 简单封装了一下sys

Linux下system()函数引发的错误

先看一下问题 简单封装了一下system()函数: 1 int pox_system(const char *cmd_line) 2 { 3     return system(cmd_line); 4 } 函数调用: 1 int ret = 0; 2 ret = pox_system("gzip -c /var/opt/I00005.xml > /var/opt/I00005.z"); 3 if(0 != ret) 4 { 5     Log("zip file fa

Linux下system函数

http://www.jb51.net/article/40517.htm   浅析如何在c语言中调用Linux脚本 http://blog.csdn.net/koches/article/details/7552034 C语言system()函数 http://blog.csdn.net/lazy_tiger/article/details/1771705 System函数与脚本的后台执行 Linux下system函数

Linux下Kill函数用法

http://www.cnblogs.com/winnxm/archive/2010/01/22/1654502.html [ KILL ]功能描述: 用于向任何进程组或进程发送信号. 1 #include <sys/types.h> 2 3 #include <signal.h> 4 5 int kill(pid_t pid, int sig); 6 7 参数: pid:可能选择有以下四种 1. pid大于零时,pid是信号欲送往的进程的标识. 2. pid等于零时,信号将送往所

Linux下select函数的使用

Linux下select函数的使用 转载:http://www.cnblogs.com/hjslovewcl/archive/2011/03/16/2314330.html 一.Select 函数详细介绍 Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect. accept.recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发 生,

[Android Memory] Linux下malloc函数和OOM Killer

http://www.linuxidc.com/Linux/2010-09/28364.htm Linux下malloc函数主要用来在用户空间从heap申请内存,申请成功返回指向所分配内存的指针,申请失败返回NULL.默认情况下,Linux内核使用“乐观的”分配内存策略,首先粗略估计系统可使用的内存数,然后分配内存,但是在使用的时候才真正把这块分配的内存给你.这样一来,即使用malloc申请内存没有返回NULL,你也不一定能完全使用这块内存,特别是在一次或连续多次申请很多内存的时候. 如果一直连

windows下system函数的使用

system函数 是可以调用一些DOS命令,比如system("cls");//清屏,等于在DOS上使用cls命令写可执行文件路径,可以运行它···· 下面列出常用的DOS命令,都可以用system函数调用: ASSOC 显示或修改文件扩展名关联.AT 计划在计算机上运行的命令和程序.ATTRIB 显示或更改文件属性.BREAK 设置或清除扩展式 CTRL+C 检查.CACLS 显示或修改文件的访问控制列表(ACLs).CALL 从另一个批处理程序调用这一个.CD 显示当前目录的名称或

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

dlopen()是一个强大的库函数.该函数将打开一个新库,并把它装入内存.该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的.这种机制使得在系统中添加或者删除一个模块时,都不需要重新编译了.可以在自己的程序中使用 dlopen().dlopen() 在 dlfcn.h 中定义,并在 dl 库中实现.它需要两个参数:一个文件名和一个标志.文件名就是一个动态库so文件,标志指明是否立刻计算库的依赖性.如果设置为 RTLD_NOW 的话,则立刻计算:如果设置的是 RTLD_LAZY,则在需要