详解linux进程间通信-管道 popen函数 dup2函数
前言:进程之间交换信息的唯一方法是经由f o r k或e x e c传送打开文件,或通过文件系统。本章将说明进程之间相互通信的其他技术—I P C(InterProcess Communication)。今天将介绍半双工的管道。
一、匿名管道
1、匿名管道介绍:
管道有两种限制;
(1) 它们是半双工的。数据只能在一个方向上流动。
(2)它们只能在具有公共祖先的进程之间使用。通常,一个管道由一个进程创建,然后该进程调用f o r k,此后父、子进程之间就可应用该管道。
管道是由调用p i p e函数而创建的:
#include <unistd.h>
int pipe(intf i l e d e s [ 2 ]) ;
返回:若成功则为0,若出错则为 - 1
经由参数f i l e d e s返回两个文件描述符: f i l e d e s [ 0 ]为读而打开, f i l e d e s [ 1 ]为写而打开。 f i l e d e s [ 1 ]
的输出是f i l e d e s [ 0 ]的输入。
程序1- 1创建了一个从父进程到子进程的管道,并且父进程经由该管道向子进程传送数据。
#include "my.h" int main()
{
int pfd[],ret;
ret = pipe(pfd);//创建管道
if(ret<)
{
perror("pipe error!");
exit(-);
}
pid_t pid = fork();
if(pid<)
{
perror("fork error!");
exit(-);
}
else if(pid>)//父进程
{
close(pfd[]);
int num;
puts("please input your num:");
scanf("%d",&num);
write(pfd[],&num,sizeof(num));
//wait(NULL);
}
else //子进程
{
close(pfd[]);
int num;
read(pfd[],&num,sizeof(num));
printf("num:%d\n",num);
}
return ;
}
注:头文件my.h见这篇博客:http://www.cnblogs.com/liudw-0215/p/8946879.html
运行示例,如下图:

接下来介绍几个跟管道有关的函数。
2、dup和d u p 2函数
下面两个函数都可用来复制一个现存的文件描述符:
#include <unistd.h>
int dup(intf i l e d es) ;
int dup2(int f i l e d e s, int f i l e d e s 2) ;
两函数的返回:若成功为新的文件描述符,若出错为- 1
由d u p返回的新文件描述符一定是当前可用文件描述符中的最小数值。用 d u p 2则可以用f i l e d e s 2
参数指定新描述符的数值。如果 f i l e d e s 2已经打开,则先将其关闭。如若f i l e d e s等于f i l e d e s 2,则
d u p 2返回f i l e d e s 2,而不关闭它。
优化程序1-1,程序1-2如下:
#include "my.h" int main()
{
int pfd[],ret;
ret = pipe(pfd);
if(ret<)
{
perror("pipe error!");
exit(-);
}
pid_t pid = fork();
if(pid<)
{
perror("fork error!");
exit(-);
}
else if(pid>)
{
close(pfd[]);
int num;
puts("please input your num:");
scanf("%d",&num);
write(pfd[],&num,sizeof(num));
wait(NULL);
}
else
{
close(pfd[]);
dup2(pfd[],STDIN_FILENO);//pfd[0]复制到标准输入
int num;
read(STDIN_FILENO,&num,sizeof(num));
printf("num:%d\n",num);
}
return ;
}
3、popen和p c l o s e函数 因为常见的操作是创建一个连接到另一个进程的管道,然后读其输出或向其发送输入,所
以标准I / O库为实现这些操作提供了两个函数 p o p e n和p c l o s e。这两个函数实现的操作是:创建
一个管道, f o r k一个子进程,关闭管道的不使用端, e x e c一个s h e l l以执行命令,等待命令终止。
#include <stdio.h>
FILE *popen(const char * c m d s t r i n g, const char * t y p e) ;
返回:若成功则为文件指针,若出错则为 N U L L
int pclose(FILE * f p) ;
返回: c m d s t r i n g的终止状态,若出错则为 - 1
函数popen 先执行f o r k,然后调用e x e c以执行c m d s t r i n g,并且返回一个标准 I / O文件指针。
如果t y p e是"r",则文件指针连接到c m d s t r i n g的标准输出。
如果t y p e 是"w",则文件指针连接到c m d s t r i n g 的标准输入。
程序1-3将用popen函数实现下图功能:

#include "my.h" int main()
{
int c;
while((c = getchar()) != EOF)
{
if(isupper(c)) //是否有大写
c = tolower(c); //转为小写
if(putchar(c) == EOF)
puts("put error!");
if(c == '\n')
fflush(stdout); //刷新标准输出
}
exit();
} ---isupper.c---
#include "my.h"
#define MAXLINE 4096 int main()
{
char line[MAXLINE];
FILE *fpin; if((fpin = popen("./upper","r")) == NULL)
perror("popen error!"); for(;;){
fputs("prompt > ",stdout);
fflush(stdout);
if(fgets(line,MAXLINE,fpin) == NULL)
break;
if(fputs(line,stdout) == EOF)
perror("puts error!");
}
if(pclose(fpin) == -)
perror("pclose error!"); putchar('\n');
return ; } ---popen.c---
运行演示如下图:

二、有名管道(命名管道)
1、简介
命名管道有时被称为FIFO。管道只能由相关进程使用,它们共同的祖先进程创建了管道。
但是,通过F I F O,不相关的进程也能交换数据。
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char * p a t h n a m e, mode_tm o d e) ;
返回:若成功则为0,若出错则为 - 1
m k f i f o函数中m o de参数的规格说明与o p e n函数中的m o d e相同。
一旦已经用 m k f i f o创建了一个 F I F O,就可用 o p e n打开它。确实,一般的文件 I / O函数
(c l o s e、 r e a d、 w r i t e、 u n l i n k等)都可用于F I F O。
程序2-1演示有名管道通信,一个写端、一个读端:
#include "my.h"
typedef struct{
char name[];
int age;
double height;
}Person;
int main()
{
mkfifo("pipe",);//创建管道 名字为pipe
int fd = open("pipe",O_WRONLY);
if(fd < )
{
perror("open error!");
exit(-);
}
Person p;
puts("please input your name,age,height:");
scanf("%s%d%lf",p.name,&p.age,&p.height);
write(fd,&p,sizeof(p));
close(fd);
return ;
}
---fwrite.c---
#include "my.h"
typedef struct{
char name[];
int age;
double height;
}Person;
int main()
{
int fd = open("pipe",O_RDONLY);
if(fd < )
{
perror("open error!");
exit(-);
}
Person p;
read(fd,&p,sizeof(p));
printf("name:%-5sage:%-5dheight:%-5lf\n ",p.name,p.age,p.height);
close(fd);
unlink("pipe");//删除管道文件
return ;
}
--- fread.c ---
运行演示:先编译fwrite.c生成w可执行用户,./w执行,再编译fread.c然后执行,写端输入数据,读端输出数据:


总结:主要介绍了进程间通信的管道,主要分为匿名管道和有名管道,还介绍了popen等函数
详解linux进程间通信-管道 popen函数 dup2函数的更多相关文章
- 详解linux进程间通信-信号
前言:之前说看<C++ Primer >暂时搁浅一下,迷上公司大神写的代码,想要明白,主要是socket.进程间通信! 知道进程间通信:信号.信号量.管道.消息队列.共享内存(共享存储), ...
- 详解linux进程间通信-消息队列
前言:前面讨论了信号.管道的进程间通信方式,接下来将讨论消息队列. 一.系统V IPC 三种系统V IPC:消息队列.信号量以及共享内存(共享存储器)之间有很多相似之处. 每个内核中的 I P C结构 ...
- linux dmesg命令参数及用法详解(linux显示开机信息命令)
linux dmesg命令参数及用法详解(linux显示开机信息命令) http://blog.csdn.net/zhongyhc/article/details/8909905 功能说明:显示开机信 ...
- Linux进程上下文切换过程context_switch详解--Linux进程的管理与调度(二十一)
1 前景回顾 1.1 Linux的调度器组成 2个调度器 可以用两种方法来激活调度 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制, 以固定的频率运行, 不时的检测 ...
- linux下sort命令使用详解---linux将文本文件内容加以排序命令
转载自:http://www.cnblogs.com/hitwtx/archive/2011/12/03/2274592.html linux下sort命令使用详解---linux将文本文件内容加以排 ...
- Linux下ps命令详解 Linux下ps命令的详细使用方法
http://www.jb51.net/LINUXjishu/56578.html Linux下的ps命令比较常用 Linux下ps命令详解Linux上进程有5种状态:1. 运行(正在运行或在运行队列 ...
- 详解Linux交互式shell脚本中创建对话框实例教程_linux服务器
本教程我们通过实现来讲讲Linux交互式shell脚本中创建各种各样对话框,对话框在Linux中可以友好的提示操作者,感兴趣的朋友可以参考学习一下. 当你在终端环境下安装新的软件时,你可以经常看到信息 ...
- linux useradd(adduser)命令参数及用法详解(linux创建新用户命令)
linux useradd(adduser)命令参数及用法详解(linux创建新用户命令) useradd可用来建立用户帐号.帐号建好之后,再用passwd设定帐号的密码.而可用userdel删除帐号 ...
- 详解linux运维工程师入门级必备技能
详解linux运维工程师入门级必备技能 | 浏览:659 | 更新:2013-12-24 23:23 | 标签:linux it自动化运维就是要很方便的运用各种工具进行管理维护,有效的实施服务器保护 ...
随机推荐
- python-map的用法
map()函数 map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 1.当seq只 ...
- 写一个vue组件
写一个vue组件 我下面写的是以.vue结尾的单文件组件的写法,是基于webpack构建的项目.如果还不知道怎么用webpack构建一个vue的工程的,可以移步到vue-cli. 一个完整的vue组件 ...
- 阿里云API网关(10)服务网关业务流程
一.开放api 二.调用api 三.开发指南 四.其他 1.调试 2.测试 3.mock 4.发布 5.checklist
- OAuth2.0学习(1-11)新浪开放平台微博认证-使用OAuth2.0调用微博的开放API
使用OAuth2.0调用API 使用OAuth2.0调用API接口有两种方式: 1. 直接使用参数,传递参数名为 access_token URL 1 https://api.weibo.com/2/ ...
- RxJava系列3(转换操作符)
RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...
- 【第二十一篇】手C# MVC 微信授权登录 OAuth2.0授权登录
首先一定要熟读,最起码过一遍微信开发者文档 微信开发者文档 文档写的很清楚 授权登录四步走 在正文开始前,我得讲清楚一个事情 敲黑板,划重点:微信一共有两个 access_token 一个是7200就 ...
- 项目管理器 ProjectManager Beta 10 发布
本次更新内容: 可以设置主界面是否显示表格线 去除了开发日志界面的表格线,看起来好像好看一些 修复主界面时间显示的问题 自定义问候语 修复习惯统计记录时间显示错误的问题 修复创建项目时间错误问题 增加 ...
- SpringMVC(十二):SpringMVC 处理输出模型数据之@ModelAttribute
Spring MVC提供了以下几种途径输出模型数据:1)ModelAndView:处理方法返回值类型为ModelAndView时,方法体即可通过该对象添加模型数据:2)Map及Model:处理方法入参 ...
- WPF利用附加属性修改ShowGridLines效果
1.思路主要代码 wpf的gridline原本效果是虚线类型的.有时候需要设计成表格形式的,因此有了用附加属性来自动绘制边框线的想法. 思路:绘制Line并添加到grid的children里,但效果并 ...
- vue报错 Do not use built-in or reserved HTML elements as component id:header
组件,不能和html标签重复 header组件,h5新标签重复 Do not use built-in or reserved HTML elements as component id:header ...