1、system函数:
使用函数system,在程序中执行一个shell命令字符串很方便。它是一个和操作系统紧密相关的函数,用户可以使用它在自己的程序中调用系统提供的各种命令,执行系统的命令行,其实也是调用程序创建一个进程来实现的。实际上,system函数的实现正是通过调用fork、exec、waitpid函数来完成的。system函数原型:
1 #include <stdlib.h> 2 3 int system(const char* cmdstring); 4 5 /*源码,该源码没有对信号进行处理*/ 6 #include <sys/types.h> 7 #include <sys/wait.h> 8 #include <errno.h> 9 #include <unistd.h> 10 int system(const char * cmdstring) 11 { 12 pid_t pid; 13 int status; 14 15 if(cmdstring == NULL){ 16 return (1); 17 } 18 19 if((pid = fork())<0){ 20 status = -1; 21 } 22 else if(pid = 0){ 23 execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); 24 _exit(127); //子进程正常执行则不会执行此语句 25 } 26 else{ 27 while(waitpid(pid, &status, 0) < 0){ 28 if(errno != EINTER){ 29 status = -1; 30 break; 31 } 32 } 33 } 34 return status; 35 }
2、system函数的返回值:
由于system是通过fork、exec、waitpid函数实现的,则system对返回值的处理分为三个阶段:
阶段1 fork失败,返回-1;
阶段2 调用/bin/sh拉起shell脚本,只要能够调用到/bin/sh,并且执行shell过程中没有被其他信号异常中断,都算正常结束。
(比如:不管shell脚本中返回什么原因值,是0还是非0,都算正常执行结束。
即使shell脚本不存在或没有执行权限,也都算正常执行结束。
如果shell脚本执行过程中被强制kill掉等情况则算异常结束。)
如何判断阶段2中shell脚本是否正常结束?如何判断阶段2中,shell脚本是否正常执行结束呢?系统提供了宏:WIFEXITED(status)。如果WIFEXITED(status)为真,则说明正常结束。
阶段3 如果shell脚本正常执行结束,将shell返回值填到status的低8~15比特位中;
如何取得阶段3中的shell返回值?你可以直接通过右移8bit来实现,但安全的做法是使用系统提供的宏:WEXITSTATUS(status)。
总结:
判断一个system函数调用shell脚本是否正常结束的方法应该是如下3个条件同时成立
(1)-1 != status 创建子进程成功
(2)WIFEXITED(status)为真 子进程正常退出
(3)0 == WEXITSTATUS(status) shell命令执行成功
例:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/wait.h> 4 int main(int argc, char **argv) 5 { 6 int status = 0; 7 status = system("exit 44"); 8 if (status == -1) { 9 printf("fork failed\n"); 10 return 0; 11 } 12 if (WIFEXITED(status)) { 13 printf("normal exit status = %d\n",WEXITSTATUS(status)); 14 } 15 return 0; 16 }