在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;
}