在C/C++中我们有时需要用到system系统调用来完成一些操作系统“更加擅长”的工作,本篇对system调用原理,调用方法,返回值封装宏,system简单源代码等内容进行了描述。


1. 应用例子
#include <stdlib.h>
int system(const char *command);
返回值:
通常:shell命令执行成功返回0,失败返回非0.
1. 若参数string为空指针(NULL),则返回非零值
2. 若system()在调用/bin/sh时失败则返回127
返回127的例子:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{



}
输入结果为:
[wipan@bjlinc1229 ~/src]$ ./system
sh: ll: command not found
Returned code: 127
3. 若fork不成功返回-1.
4. 若system()调用成功则最后会返回执行shell命令后的返回值(此值也可能是127,若shell命令执行的最后有返回值,则需注意其返回值的判断方法)
例子:
while ( !HDDready )

  
   if (status == 0)

        

    

   else 

    


2. system的调用过程原理

原理:当system接受的命令为NULL时直接返回,否则fork出一个子进程,因为fork在两个进程:父进程和子进程中都返回,这里要检查返回的pid,fork在子进程中返回0,在父进程中返回子进程的pid,父进程使用waitpid等待子进程结束,子进程则是调用execl来启动一个程序代替自己,execl("/bin/sh", "sh", "-c", cmdstring, (char*)0)是调用shell,这个shell的路径是/bin/sh,后面的字符串都是参数,然后子进程就变成了一个shell进程,这个shell的参数是cmdstring,就是system接受的参数。在windows中的shell是command,想必大家很熟悉shell接受命令之后做的事了。


3. 判断system返回是否成功更加详细的方法(实践中我们用上一种即可)

3.1   背景

   


3.2   判断返回值的宏

如果参数status的值不是NULL,wait就会把子进程退出时的状态取出并存入其中,这是一个整数值(int),指出了子进程是正常退出还是被非正常结束的,或被哪一个信号结束的等信息。由于这些信息被存放在一个整数的不同二进制位中,所以用常规的方法读取会非常麻烦,人们就设计了一套专门的宏(macro)来完成这项工作,下面我们来学习一下其中最常用的两个:

1) 
2) 
例子如下:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
main()
{
     
     
     
      if(pc<0) 
            
      else if(pc==0){    
            
             exit(3);  
     
      else{             
            
             if(WIFEXITED(status)){   
                   
                   
             }else                   
                   
     
}
结果如下:
$ cc wait2.c -o wait2
$ ./wait2
This is child process with pid of 1538.
the child process 1538 exit normally.
the return code is 3.

3.3  
#inlucde <wait.h>
 ...
    sprintf(szCommand, "compress -fc %s > %s.Z", szFilePath, szFilePath);
    iStatus = system(szCommand);
    if (WIFEXITED(iStatus) && WEXITSTATUS(iStatus) == 0)
    {
       strcat(pstMsgHeader->acFileName, ".Z";
    }
    else
    {
       printf("Compress file <%s> fail with exit status %d.",
          szFilePath, WEXITSTATUS(iStatus)) ;
       return -1;
    }4. system源码
 system()函数功能强大,很多人用却对它的原理知之甚少。看下简单的linux版system函数的源码:
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <errno.h>
 #include <unistd.h>
 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;
 }