宏伟精讲·linux system()函数完全解密
system()能让我们在自己的程序中调用系统的脚本和已编译好的程序,是一个非常简单、便捷的接口。
但很多程序员都对这个函数又爱又恨,爱是因为用它可以省很多事,恨是因为网上都说它会给程序带来
莫名其妙的BUG。但这个是system()函数的原罪吗?(system():怪我咯?)害怕源于不了解,下面
让我们系统的了解一下system()的用法,和所谓的坑。
一、基本功能和测试
1.头文件包含
#include <stdlib.h>
2.函数原型
/*
*功能:在C程序中执行字符串指定的系统命令或程序
*返回值:
* 1:命令为NULL
* -1:创建子进程失败
* 0x7f00:命令无法执行(子进程返回127)*
* 其他值:命令的返回值或退出码。
*命令的返回值或退出码格式说明:
* Bits 15-8 = 进程返回值或退出码。
* Bit 7 = 是否产生了core dump。
* Bits 6-0 = 导致进程被杀死的信号值。
* 常用异常码解析宏:
* WIFEXITED(status) 正常退出返回非零值
* WEXITSTATUS(status) 取得返回值或退出码
* WIFSIGNALED(status) 被信号杀死返回非零
* WTERMSIG(status) 取得杀死它的信号值
* WIFSTOPPED(status) 被信号暂停返回非零
* WSTOPSIG(status) 取得暂停它的信号值
int system(const char *__command);
3.函数流程
|-cmd==NULL? --------------YES---->return 1
|-创建子进程--------------失败---->return -1
|-执行cmd-----------------失败---->return 0x7f00(32512)
|-等待cmd执行完毕--等待cmd失败---->return -1
|--------------------------------->return cmd返回值或退出码
4.测试代码
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
*演示system返回值使用,空命令处理和信号处理跟system()不一样。
int mysystem(const char * __command)
pid_t pid;
int retval=0;
if(NULL==__command){
return 1;
if((pid=fork())<0){//fork error
return -1;
else if(pid==0){
//use __command to replace current process
execl("/bin/sh", "sh", "-c", __command, (char *)0);
return 127;
else{
while(waitpid(pid,&retval,0)<0){
if(EINTR!=errno){
retval = -1;
break;
return retval;
int main(int argc,const char **argv)
int ret=0;
ret=mysystem(argv[1]);
printf("mysystem ret=%d\n",ret);
ret=system(argv[1]);
printf("system ret =%d\n",ret);
return 1;
}
5.测试结果
(1)cmd为空
(2)未知命令
(3)执行成功
返回1的是第二个./mysys打印,表示cmd为空。
返回256的是第一个./mysys打印,表示“./mysys”执行成功,并返回了1(256=0x100)
二、注意事项
1.阻塞进程
system会阻塞当前进程,但是当前进程的其他线程不会被阻塞。
可对上面的代码稍加改动,然后测试:
#include <pthread.h>
void *threadloop(void *arg)
while(1){
printf("this is thread\n");
usleep(100000);
int main(int argc,const char **argv)
int ret=0;
pthread_t tid;
pthread_create(&tid,NULL,threadloop,NULL);
ret=mysystem(argv[1]);
printf("mysystem ret=%d\n",ret);
ret=system(argv[1]);
printf("system ret =%d\n",ret);
pthread_join(tid,NULL);
return 1;
}
测试结果:system会阻塞当前进程,但是当前进程的其他线程不会被阻塞。
2.返回值多
system()返回值多而复杂,咋一看五花八门,所以必须妥善处理,下面是一个返回值处理的范本。
int main(int argc,const char **argv)
int ret=0;
const char *cmd=argv[1];
ret=system(cmd);
printf("system ret =%d\n",ret);
if(1==ret){
printf("程序命令为空\n");
else if(-1==ret){
printf("创建命令子进程失败\n");
else if(0x7f00==ret){
printf("命令错误,无法执行\n");
else{
if(WIFEXITED(ret)){
printf("程序正常结束,返回值:%d\n",WEXITSTATUS(ret));
else if(WIFSIGNALED(ret)){
printf("程序被信号杀死,信号值:%d\n",WTERMSIG(ret));