system函数
在编写C程序时,使用system函数调用shell命令来帮助执行一些操作方便而简单,system函数的实质是调用fork()创建了一个子进程,然后调用execl执行/bin/sh程序来执行命令字符串。
函数定义:
int system(const char * string);
函数说明:
system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。
返回值:
如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值。如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。
需要注意的是system会阻塞原进程,也就是说原进程需要等待system执行的任务(子进程)结束并返回之后才能够继续执行,否则会阻塞在system处。
从system的实现源码可以很好理解为什么。下面是system函数的实现源码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 int system(const char * cmdstring) 2 { 3 pid_t pid; 4 int status; 5 6 if(cmdstring == NULL){ 7 8 return (1); 9 } 10 11 12 if((pid = fork())<0){ 13 14 status = -1; 15 } 16 else if(pid == 0){ 17 execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); 18 _exit(127); //如果execl调用失败,则会执行该语句,否则不会被执行到 19 20 } 21 else{ 22 while(waitpid(pid, &status, 0) < 0){ 23 if(errno != EINTER){ 24 status = -1; 25 break; 26 } 27 } 28 } 29 return status; 30 }
wait函数
waitpid(wait)会暂时停止目前进程的执行,直到有子进程结束的信号到来,结束状态保存在status结构中。如果执行成功,则返回值为结束子进程的进程识别码(pid),如果错误返回-1。如果在调用wait时子进程已经结束,则wait会立即返回子进程结束状态值。
pid_t wait (int * status); 等待任一子进程。
pid_t waitpid(pid_t pid,int * status,int options); 等待某一子进程。进程号由pid给出。
pid的值可以为以下几种情况
pid<-1 等待进程组识别码为pid绝对值的任何子进程。
pid=-1 等待任何子进程,相当于wait()。
pid=0 等待进程组识别码与目前进程相同的任何子进程。
pid>0 等待任何子进程识别码为pid的子进程。
参数option可以为0 或下面的OR 组合
WNOHANG 如果没有任何已经结束的子进程则马上返回,不予以等待。
WUNTRACED 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会。
子进程的结束状态返回后存于status,底下有几个宏可判别结束情况
WIFEXITED(status)如果子进程正常结束则为非0值。
WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。
WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真
WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。
WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。
WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。
示例:
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main() { int status, i; int fpid; if((fpid = fork()) < 0) { perror("fork"); }else if(fpid == 0) {//child printf("This is the child process, pid is %d\n",getpid()); _exit(5); }else{ printf("This is the parent process, pid is %d, the child pid is %d\n",getpid(),fpid); pid_t pid = wait(&status); i = WEXITSTATUS(status); printf("the child is end, pid is %d, the exit is %d\n",pid,i); } return 0; }
运行结果:
This is the parent process, pid is 3645, the child pid is 3646
This is the child process, pid is 3646
the child is end, pid is 3646, the exit is 5