system函数和fork-exec机制

34 篇文章 1 订阅
10 篇文章 0 订阅

system函数

使用man system查看帮助如下:

NAME
       system -execute a shell command
 
SYNOPSIS
       #include<stdlib.h>
 
       intsystem(const char *command);
 
DESCRIPTION
       system()  executes a command specified in command by calling
       /bin/sh -ccommand, and returns after the command  has  been
      completed.   During execution ofthe command, SIGCHLD will be
       blocked, andSIGINT and SIGQUIT will be ignored.
 
RETURN VALUE
       The value returned is -1 on error (e.g.  fork(2) failed), and
       the  return status  of  the command otherwise.  This latter
       return statusis in the format specified in wait(2).   Thus,
       the exit code of thecommand will be WEXITSTATUS(status). In
       case /bin/shcould not be executed, the exit status will  be
       that of acommand that does exit(127).
 
       If the valueof command is NULL, system() returns non-zero if
       the shell isavailable, and zero if not.
 
       system() doesnot affect the wait status of any other  chil-
       dren.

说明:

以/bin/sh -c command的方式执行命令,如果命令之间用“; ”隔开,则可以执行多条指令。

system是一个同步函数,即执行完之后才会返回,内部实现也类似与fork-exec机制(执行期间会阻塞SIGCHLD信号,同时忽略SIGINT、SIGQUIT)。

如何判断system是否执行成功:

1、   fork成功:-1 != status

2、   system命令是否正常终止:WIFEXITED(status)非0 ,非正常终止=0

3、   根据返回值判断:WEXITSTATUS(status)== 0  //获取system的返回值(低八位,可以理解为unsignedbyte);如果shell命令无法执行,则返回127,命令检测到有错误,则返回1-126

注意:

当shell脚本不存在、没有执行权限等场景下时,以上前2个条件仍会成立,此时WEXITSTATUS(status)为127,126等数值。

所以,我们在shell脚本中不能将127,126等数值定义为返回值,否则无法区分中是shell的返回值,还是调用shell脚本异常的原因值。shell脚本中的返回值最好多1开始递增。

fork-exec机制

此机制用于执行一个新的进程。System函数的内部实现采用的也是fork-exec机制,下面是fork-exec的一个示例:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
 
int main(int argc, char *argv[])
{
         pid_t pid =0;
         pid =  fork();
         if (pid <0)
         {
                  printf("forkerror!\n");
                  exit(-1);
         }
         else if (0 ==pid)
         {
                  //childprocess
                  char* const szArgs[] = {"sleep", "10", NULL};
// bookmark:1
                  if(-1== execvp("/bin/sleep", szArgs))
                  {
                            printf("execvperror!\n");
                            _exit(-1);
                  }
         }
         else
         {
                  //parentprocess
                  charszCmd[64]={0};
                  snprintf(szCmd,sizeof(szCmd), "kill -9 %d", pid);
// bookmark:2
                  //system(szCmd);    //to cause unormal terminate, you canannotate it  
                  intstatus= 0;
                 
                  pid= wait(&status);
                  if(WIFEXITED(status)) // normal terminate
                  {
                            if(0 == WEXITSTATUS(status))
                            {
                                     printf("processexecute success, exit code=%d", status);
                            }
                            else
                            {
                                     printf("processexecute failed, exit code = %d, WEXITSTATUS(status) = %d",status,WEXITSTATUS(status));
                            }
                  }
                  else
                  {
                            printf("processterminated unormally, pid = %d, status = %d, WEXITSTATUS(status) = %d\n",pid, status, WEXITSTATUS(status));
                  }
         }
         return 0;
}

运行看看,一探究竟:

1)       当把bookmark:1下面的 sleep改为ssleep时(即命令不正确),输出结果为

execvp error!

process execute failed, exit code = 64256, WEXITSTATUS(status)= 255

表明execvp返回-1,捕获的WEXITSTATUS(status)=255(-1), 但这种情况算正常终止,WIFEXITED(status) 非0.

2)       当把 bookmark:2 下面的system语句注释掉,输出结果为:

process terminated unormally, pid = 17584, status = 9,WEXITSTATUS(status) = 0

表明程序非正常终止,WIFEXITED(status) == 0.

总结:

从程序运行的结果看,可以得出几条结论:当exec shell命令不存在或没有执行权限时,execvp执行的进程仍算正常终止,而当execvp运行期间被终止时,算异常终止。

说明:

子进程的结束状态返回后存于status,底下有几个宏(位于头文件sys/wait.h)可判别结束情况:
WIFEXITED(status)如果子进程正常结束则为非0值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status)取得引发子进程暂停的信号代码,

参考链接:

http://blog.chinaunix.net/uid-10554711-id-2948333.html

http://blog.csdn.net/cheyo/article/details/6595955

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值