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

导读 曾经的曾经,被system()函数折磨过,之因此这样,是由于对system()函数了解不够深刻。这里必需要搞懂system()函数,由于有时你不得不面对它。

linux-crond-1

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

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

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

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

  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.

SYSTEMD

看一下system()函数的源码

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

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时。bash

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

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

相关文章
相关标签/搜索