产品升级,新增网卡,原先的产品是arm平台,新网卡是mips平台,需要开发网卡的配置程序,该程序原计划是以守护进程的形式后台执行,不过测试过程中发现系统不是特别稳定,导致程序时不时奔溃下,一时半会儿无法解决,只能先给该程序加个壳,以系统调用的方式来执行,如果出现问题的话重复调用就可以了。

以前在程序里调用系统命令的话,使用的是system()函数,不过system函数无法获取命令的输出,查了下资料,发现有个popen调用,和system类似,也能够执行系统命令,区别在于它能够获取命令的输出或者给系统命令传递参数,类似与管道的作用。

popen接口定义:

#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);popen函数会创建一个管道,并且创建一个子进程来执行shell,shell会创建一个子进程来执行command,
根据type的值不同,分成两种情况:如果type是r: command执行的标准输出,就会写入管道,从而被调用popen的进程读到,通过对popen返
回的FILE类型指针执行read或fgets操作,就可以读取到command的标准输出。如果type是w:调用popen的进程可以通过对FILE类型指针执行write、fputs等操作,负责往管道里面写
入,写入的内容经过管道传递给执行command的进程,作为命令的的输入。popen函数成功时,会返回stdio库封装的FILE类型的指针,失败时会返回NULL,并且设置errno,
常见的失败有fork失败、pipe失败,或者分配内存失败。I/O结束后,可以调用pclose函数来关闭管道,并且等待子进程的退出。pclose函数成功时会返回
子进程shell的终止状态。popen函数和system函数类似,如果command对应命令无法执行,就如同
执行了exit(127)一样,如果发生其它错误,pclose函数则返回-1.可以从errno中获取到失败的原因。

命令执行后需要获取命令的返回值,可以通过如下几个宏来获取:

1. 进程正常退出
WIFEXITED(status) : 如果子进程正常退出,则返回true,否则返回false
WEXITSTATUS(status):如果子进程正常退出,则本宏用来获取进程的退出状态2. 进程收到信号,导致退出
WIFSIGNALED(status) : 如果进程是被信号杀死的,则返回true,否则返回false
WTREMSIG(status):如果进程是被信号杀死的,则返回杀死进程信号的值
WCOREDUMP(status) : 如果子进程产生了core dump,则返回true,否则返回false

测试用例:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include<sys/wait.h>
#include<signal.h>#define MAX_LINE_SIZE 8192/* 打印shell返回结果 */
void print_wait_exit(int status)
{/* shell正常退出,即便命令执行异常,shell也有可能是正常退出的 */if(WIFEXITED(status))                                {printf("normal termination, exit status = %d\n", WEXITSTATUS(status));}/* shell异常退出 */else if(WIFSIGNALED(status)){printf("abnormal terminatio, signal number = %d\n", WTERMSIG(status));}
}int main(int argc, char *argv[])
{FILE *fp = NULL;char command[MAX_LINE_SIZE], buffer[MAX_LINE_SIZE];if(argc != 2){fprintf(stderr, "Usage : %s filename \n", argv[0]);exit(1);}snprintf(command, sizeof(command), "%s", argv[1]);fp = popen(command, "r");if (fp == NULL){fprintf(stderr, "popen failed (%s)", strerror(errno));exit(2);        }while (fgets(buffer, MAX_LINE_SIZE,fp) != NULL){fprintf(stdout, "%s",buffer);}int ret = pclose(fp);if (ret == 127){fprintf(stderr, "bad command :%s \n",command);exit(3);}else if (ret == -1){fprintf(stderr, "failed to get child status :%s \n",strerror(errno));exit(4);}else{print_wait_exit(ret);}exit(0);
}

运行截图:

参考资料:

1. 《Linux环境编程 从应用到内核》高峰,李彬著

c语言调用shell命令一 popen使用以及获取命令返回值相关推荐

  1. Shell函数(函数定义、函数变量、函数调用、函数传参、函数返回值、获取函数返回值)

    分享知识 传递快乐 1.函数定义 linux shell 可以用户定义函数,然后在shell脚本中可以随便调用.Shell 函数定义的语法格式如下: [function] funname [()]{函 ...

  2. linux获取命令的返回值,Shell $?:获取函数返回值或者上一个命令的退出状态

    $?是一个特殊变量,用来获取上一个命令的退出状态,或者上一个函数的返回值. 所谓退出状态,就是上一个命令执行后的返回结果.退出状态是一个数字,一般情况下,大部分命令执行成功会返回0,失败返回1,这和C ...

  3. linux里返回状态命令行,Shell $?获取函数返回值或者上一个命令的退出状态

    $? 是一个特殊变量,用来获取上一个命令的退出状态,或者上一个函数的返回值. 所谓退出状态,就是上一个命令执行后的返回结果.退出状态是一个数字,一般情况下,大部分命令执行成功会返回 0,失败返回 1, ...

  4. shell中一些特殊命令|: 管道命令。;;在前一个命令结束时,而忽略其返回值,继续执行下一個命令。

    shell传递参数 $0 对应的是当前 Shell 脚本程序的名称,$#对应的是总共有几个参数,$*对应的是所有位置的参数值,$?对应的是显示上一次命令的执行返回值,而$1.$2.$3--则分别对应着 ...

  5. C++调用python并获取其返回值

    C++调用python并获取其返回值 先上实例代码: C++代码: //初始化py环境 // Py_Initialize();PyRun_SimpleString("import sys&q ...

  6. c语言调用shell脚本或命令

    1.system(执行shell 命令) 相关函数 fork,execve,waitpid,popen 表头文件 #include<stdlib.h> 定义函数 int system(co ...

  7. linux下如何用c语言调用shell命令-转

    C程序调用shell脚本共有三种法子 :system().popen().exec系列函数 system()不用你自己去产生进程,它已经封装了,直接加入自己的命令exec 需要你自己 fork 进程, ...

  8. [shell]C语言调用shell脚本接口

    1) system(shell命令或shell脚本路径); 执行过程:system()会调用fork()产生子进程,由子进程来调用/bin/sh -c string来执行参数string字符串所代表的 ...

  9. 随手记——Linux中C语言调用shell指令的三种方式

    在学习资料满天飞的大环境下,知识变得非常零散,体系化的知识并不多,这就导致很多人每天都努力学习到感动自己,最终却收效甚微,甚至放弃学习.我的使命就是过滤掉大量的无效信息,将知识体系化,以短平快的方式直 ...

最新文章

  1. android用户引导页,android欢迎界面引导页
  2. Error in match.names(clabs, names(xi)) : names do not match previous names
  3. Visual Studio 11 Beta 带来新的Metro 应用开发体验
  4. Introspection
  5. JZOJ__Day 2:【NOIP普及模拟】分数
  6. 【职场】税前110万
  7. 主播靠颜值还是???!!!!!
  8. 7135制作自动量程电压切换_基于数字电压表的直流电位差计自动检定装置的讨论...
  9. php form表单属性,HTML5 表单属性
  10. 阶段5 3.微服务项目【学成在线】_day02 CMS前端开发_23-CMS前端页面查询开发-分页查询实现...
  11. PAIP.获取RSS全文输出.txt
  12. 几款经典css框架下载
  13. F2FS源码分析-3.1 [F2FS 文件创建和删除部分] 一般文件的创建
  14. Ckeditor富文本编辑器
  15. Java基础之集合篇(内容超详细,带你轻松搞懂List、Set和Map的使用)
  16. ubuntu-20.04.3-详细安装教程(图文)附下载地址
  17. 携程,京东,4399静态页面总结
  18. Linux系统编程——execl函数族
  19. 有一页式系统,其页表存放在内存中. (1)如果对内存的一次存取需要1.5微秒,问实现一次页面访问的存取时间是多少? (2)如果系统增加有快表,平均命中率为85%,.....
  20. 私有部署、重构企业软件,第四范式发布大模型“式说”

热门文章

  1. Centos 7 安装LAMP环境
  2. 黑马 程序员——Java基础---流程控制
  3. (学)DEV在设计界面部分组件显示红叉并报错的问题
  4. java.函数参数太多,Java方法参数太多怎么办—Part 2—引入参数对象,javapart
  5. Matlab结构第三版,MATLAB程序设计(原书第3版)
  6. 【STM32】外部中断实验代码详解
  7. 【控制】傅里叶系列(二)傅里叶变换的推导
  8. curl 使用 ~/.netrc
  9. 子组件获取父组件的值,将这个值作为状态值保存
  10. 作为JavaScript开发人员,这些必备的VS Code插件你都用过吗?