标准I/O函数库提供了popen函数,它启动另外一个进程去执行一个shell命令行。

这里我们称调用popen的进程为父进程,由popen启动的进程称为子进程。

popen函数还创建一个管道用于父子进程间通信。父进程要么从管道读信息,要么向管道写信息,至于是读还是写取决于父进程调用popen时传递的参数。下在给出popen、pclose的定义:

01 #include <stdio.h>
02 /*
03 函数功能:popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令。
04         参数type可使用“r”代表读取,“w”代表写入。
05         依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。
06         随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中
07 返回值:若成功则返回文件指针,否则返回NULL,错误原因存于errno中
08 */
09 FILE * popen( const char * command,const char * type);
10  
11 /*
12 函数功能:pclose()用来关闭由popen所建立的管道及文件指针。参数stream为先前由popen()所返回的文件指针
13 返回值:若成功返回shell的终止状态(也即子进程的终止状态),若出错返回-1,错误原因存于errno中
14 */
15 int pclose(FILE * stream);

下面通过例子看下popen的使用:

假如我们想取得当前目录下的文件个数,在shell下我们可以使用:

1 ls wc -l

我们可以在程序中这样写:

01 /*取得当前目录下的文件个数*/
02 #include <stdio.h>
03 #include <stdlib.h>
04 #include <errno.h>
05 #include <sys/wait.h>
06  
07 #define MAXLINE 1024
08  
09 int main()
10 {
11     char result_buf[MAXLINE], command[MAXLINE];
12     int rc = 0; // 用于接收命令返回值
13     FILE *fp;
14  
15     /*将要执行的命令写入buf*/
16     snprintf(command, sizeof(command), "ls ./ | wc -l");
17  
18     /*执行预先设定的命令,并读出该命令的标准输出*/
19     fp = popen(command, "r");
20     if(NULL == fp)
21     {
22         perror("popen执行失败!");
23         exit(1);
24     }
25     while(fgets(result_buf, sizeof(result_buf), fp) != NULL)
26     {
27         /*为了下面输出好看些,把命令返回的换行符去掉*/
28         if('\n' == result_buf[strlen(result_buf)-1])
29         {
30             result_buf[strlen(result_buf)-1] = '\0';
31         }
32         printf("命令【%s】 输出【%s】\r\n", command, result_buf);
33     }
34  
35     /*等待命令执行完毕并关闭管道及文件指针*/
36     rc = pclose(fp);
37     if(-1 == rc)
38     {
39         perror("关闭文件指针失败");
40         exit(1);
41     }
42     else
43     {
44         printf("命令【%s】子进程结束状态【%d】命令返回值【%d】\r\n", command, rc, WEXITSTATUS(rc));
45     }
46  
47     return 0;
48 }

编译并执行:

$ gcc popen.c

$ ./a.out

命令【ls ./ | wc -l】 输出【2】

命令【ls ./ | wc -l】子进程结束状态【0】命令返回值【0】

上面popen只捕获了command的标准输出,如果command执行失败,子进程会把错误信息打印到标准错误输出,父进程就无法获取。比如,command命令为“ls nofile.txt” ,事实上我们根本没有nofile.txt这个文件,这时shell会输出“ls: nofile.txt: No such file or directory”。这个输出是在标准错误输出上的。通过上面的程序并无法获取。

注:如果你把上面程序中的command设成“ls nofile.txt”,编译执行程序你会看到如下结果:

$ gcc popen.c

$ ./a.out

ls: nofile.txt: No such file or directory

命令【ls nofile.txt】子进程结束状态【256】命令返回值【1】

需要注意的是第一行输出并不是父进程的输出,而是子进程的标准错误输出。

有时子进程的错误信息是很有用的,那么父进程怎么才能获取子进程的错误信息呢?

这里我们可以重定向子进程的错误输出,让错误输出重定向到标准输出(2>&1),这样父进程就可以捕获子进程的错误信息了。例如command为“ls nofile.txt 2>&1”,输出如下:

命令【ls nofile.txt 2>&1】 输出【ls: nofile.txt: No such file or directory】

命令【ls nofile.txt 2>&1】子进程结束状态【256】命令返回值【1】

附:子进程的终止状态判断涉及到的宏,设进程终止状态为status.

WIFEXITED(status)如果子进程正常结束则为非0值。

WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。

WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真。

WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。

WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。

WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。

转载于:https://www.cnblogs.com/yangli-ios/p/4195791.html

【IPC通信】基于管道的popen和pclose函数相关推荐

  1. 基于管道的popen和pclose函数

    基于管道的popen和pclose函数 标准I/O函数库提供了popen函数,它启动另外一个进程去执行一个shell命令行. 这里我们称调用popen的进程为父进程,由popen启动的进程称为子进程. ...

  2. linux c之通过popen和pclose函数创建管道执行shell 运行命令使用总结

    1.函数介绍 popen 和 pclose 函数 操作是创建一个管道链接到另一个进程,然后读其输出或向其输入端发送数据.标准 I/O 库提供了两个函数 popen 和 pclose 函数,这两个函数实 ...

  3. 微软不会放弃Electron:Electron 快速入门及IPC 通信

    最近,有媒体推文说"微软要放弃Electron了",很多不明真相的群众被带偏了节奏:我刚学了Electron就要过时了吗?求真相!那么我们还要不要学Electron呢? 实际上:只 ...

  4. android IPC通信(下)-AIDL

    android IPC通信(上)-sharedUserId&&Messenger android IPC通信(中)-ContentProvider&&Socket 这篇 ...

  5. golang之跨语言ipc通信

    1 golang之跨语言ipc通信 文章目录 1 golang之跨语言ipc通信 1.1 unix domain Socket(unix域套接字)介绍 1.2 IPC SOCKET通信 1.2.1 函 ...

  6. 传统的Linux中IPC通信原理

    在了解 Binder 跨进程通信原理之前, 我们先了解一下 Linux 传统的进程间通信的概念和基本原理, 这样有助于我们更好的理解 Binder 的通信原理. 这个部分基本都是理论, 基础不是很好的 ...

  7. async function_Electron IPC 通信如何使用 async/await 调用?

    前言碎语 此想法是在使用 electron 进程间通信(IPC)过程中,无法忍受其 API 的使用不友好性而产生. 为了提高代码可读性.可维护性,而不得已造轮子了. 生命在于折腾,其乐无穷. Elec ...

  8. 4月25日 python学习总结 互斥锁 IPC通信 和 生产者消费者模型

    一.守护进程 import random import time from multiprocessing import Processdef task():print('name: egon')ti ...

  9. web前端培训分享Electron之IPC 通信

    本文由小千给大家分享Electron之IPC 通信. 1.index.html <!DOCTYPE html><html><head><meta charse ...

  10. web前端技术分享Electron之IPC 通信

    本文由小千给大家分享Electron之IPC 通信. 1.index.html <!DOCTYPE html><html><head><meta charse ...

最新文章

  1. 在Ubuntu 16.04.6 LTS上安装python3.7和pip3后出现Command '('lsb_release', '-a')' 出错问题的解决方法
  2. 分布式存储(ceph)技能图谱(持续更新)
  3. linux磁盘满处理
  4. java高级特性2,Java高级特性 2
  5. windows api 枚举进程pid
  6. Java中抽象类、接口、父类直接的区别与联系
  7. 转:PHP 获取今日、昨日、上周、本月的起始时间戳和结束时间戳的方法
  8. Android开发之自定义view进行旋转动画
  9. 在Web应用中使用localforage存储离线数据
  10. oracle秘钥到期,Oracle – 更新加入 – 非密钥保留表
  11. 云要闻 | 腾讯在华南建云计算基地;致敬Larry Roberts;华云数据在无锡拿了一个奖!...
  12. BlockChain:区块链入门课程 -- 区块链之类型 、应用程序、技术挑战和潜力
  13. 快速理解设计模式六大原则
  14. ssm框架图片上传与显示_SSM在线考试系统
  15. [easyui] - 在easyui的table中展示提示框
  16. 手机设置邮箱无法验证服务器失败,用手机邮箱设置怎么总显示无法验证帐户信息...
  17. 怎么用c语言写汤姆猫小游戏,Android实现汤姆猫小游戏
  18. 服务器没有显示器能接笔记本吗,笔记本能连显示器吗_笔记本能不能接显示器...
  19. JAVA计算等额本金还款列表
  20. 微信小程序 控制台报错net::ERR_UNSAFE_PORT

热门文章

  1. ValueError: This sheet is too large! Your sheet size
  2. Graphviz神经网络的绘图
  3. GCN的形象讲解1,2
  4. 下载faceScrub人脸数据库(单线程版本)
  5. python实现七种方法去除列表中的重复元素
  6. c++ array容器 传参_C/C++常用技巧及初学者易错点汇总学习
  7. 永磁同步电机转子磁链_永磁同步电机转子初始位置检测、增量式光电编码器对位调零思路解析...
  8. 机器学习 什么是Cross Entropy 交叉熵
  9. FISCO BCOS源码(6)编译源码 获取FISCO BCOS可执行程序
  10. 解决button多次重复点击