system execl

1. system();
int system(const char *command);
在Windows下,用来调用常用的Dos命令
在Linux下,system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略

//源码
int system(const char * cmdstring)
{
    pid_t pid;
    int status;

    if(cmdstring == NULL)
    {      
        return (1);
    }


    if((pid = fork()) < 0)
    {
        status = -1;
    }
    else if(pid == 0)
    {
        execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
        -exit(127); //子进程正常执行则不会执行此语句
    }
    else
    {
        while(waitpid(pid, &status, 0) < 0)
        {
            if(errno != EINTER)
            {
                status = -1;
                break;
            }
        }
    }
    return status;
}

system()在调用/bin/sh时失败则返回127,其他失败原因返回-1
如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功

if(WIFEXITED(status))
{
    printf("normal termination, exit status=%d
", WEXITSTATUS(status)); //取得cmdstring执行结果
}
else if(WIFSIGNALED(status))
{
    printf("abnormal termination,signal number=%d
", WTERMSIG(status)); //如果cmdstring被信号中断,取得信号值
}
else if(WIFSTOPPED(status))
{
    printf("process stopped, signal number=%d
", WSTOPSIG(status)); //如果cmdstring被信号暂停执行,取得信号值
}

2 返回值
system函数返回结果并非command命令的结果返回,而是返回shell的终止状态,而非执行命令字符串的终止状态

//命令错误
ret = system("lad /home");
ret = 32512
//命令正确,执行错误
ret = system("ls /ttt");
ret = 512 > 255     //高8位有值
//命令正确,执行正确
ret = system("ls /home");
ret = 0

exit退出时,父进程中只取其低8位。高于255的值是没有意义

3. SIGCHLD信号
执行system函数,还会受到SIGCHLD信号处理的影响,他需要的方式就是SIG_DFL,不可以使用其他信号处理。如果当前进程有semop在睡眠,会收到EINTR信号而中断

sighandler_t old_handler; 
old_handler = signal(SIGCHLD, SIG_DFL); 
ret = system(cmd_line); 
signal(SIGCHLD, old_handler); 

4. execl();
int execl(const char *path, const char *arg, …);
execl()其中后缀”l”代表list也就是参数列表的意思,第一参数path字符指针所,指向要执行的文件路径, 接下来的参数代表执行该文件时传递的参数列表:argv[0],argv[1]… 最后一个参数须用空指针NULL作结束。

// 执行/bin目录下的ls, 第一参数为程序名ls, 第二个参数为”-al”, 第三个参数为”/etc/”
execl(“/bin/ls”,”ls”,”-al”,”/etc/”,NULL);

execl与system的一个区别:
使用execl时最好在之前先调用fork,在子进程中执行execl,否则execl会返回。而system则不用,因为从它的实现源码来看,实际上已经调用了fork

原文地址:https://www.cnblogs.com/zhangxuechao/p/11709937.html