管道通信

***************************************************

更多精彩,欢迎进入:http://shop115376623.taobao.com

***************************************************


什么是管道?

      管道是单向的、先进先出的,它把一个进程的输出和另一个进程的输入连接在一起。一个进程(写进程)在管道的

尾部写入数据,另一个进程(读进程)从管道的头部读出数据

管道的分类

 

  管道包括无名管道名管道两种,前者用于父进程和子进程间的通信,后者可用于运行于同一系统中的任意两个进程间的通信。

无名管道的创建

  无名管道由pipe( )函数创建:

   int pipe(int filedis[2]);

   当一个管道被创建时,它会创建两个文件描述符:filedis[0]用于读管道,filedis[1]用于写管道。

        管道通信示意图如图1所示:

                                                                

                                                                                               图1   管道通信示意图

 

管道关闭

 

    关闭管道只是将两个文件描述符关闭即可,可以使用普通的close函数逐个关闭。

无名管道读写

 

    管道用于不同进程间通信。通常先创建一个管道,再通过fork函数创建一个子进程,该子进程会继承父进程创建的管道。注意事项:必须在系统调用fork()前调用pipe(),否则子进程将不会继承文件描述符。否则,会创建两个管道,因为父子进程共享同一段代码段,都会各自调用pipe(),即建立两个管道,出现异常错误。无名管道读写过程如图2所示:

                                                                             

                                                                                                 图2 无名管道读写示意图

无名管道实例:

 

[cpp] view plaincopy
  1. /********************************************************** 
  2. *实验要求:   使用pipe创建无名管道并实现父子进程之间的通讯。 
  3. *功能描述:   在父进程中通过无名管道的写端写入数据,通过子进程从管道读端读出相*           应的数据。 
  4. *日    期:   2010-9-17 
  5. *作    者:   国嵌 
  6. **********************************************************/  
  7. #include <unistd.h>  
  8. #include <sys/types.h>  
  9. #include <errno.h>  
  10. #include <stdio.h>  
  11. #include <string.h>  
  12. #include <stdlib.h>  
  13.   
  14. /* 
  15.  * 程序入口 
  16.  * */  
  17. int main()  
  18. {  
  19.     int pipe_fd[2];  
  20.     pid_t pid;  
  21.     char buf_r[100];  
  22.     char* p_wbuf;  
  23.     int r_num;  
  24.       
  25.     memset(buf_r,0,sizeof(buf_r));  
  26.       
  27.     /*创建管道*/  
  28.     if(pipe(pipe_fd)<0)  
  29.     {  
  30.         printf("pipe create error\n");  
  31.         return -1;  
  32.     }  
  33.       
  34.     /*创建子进程*/  
  35.     if((pid=fork())==0)  //子进程执行序列  
  36.     {  
  37.         printf("\n");  
  38.         close(pipe_fd[1]);//子进程先关闭了管道的写端  
  39.         sleep(2); /*让父进程先运行,这样父进程先写子进程才有内容读*/  
  40.         if((r_num=read(pipe_fd[0],buf_r,100))>0)  
  41.         {  
  42.             printf("%d numbers read from the pipe is %s\n",r_num,buf_r);  
  43.         }     
  44.         close(pipe_fd[0]);  
  45.         exit(0);  
  46.     }  
  47.     else if(pid>0) //父进程执行序列  
  48.     {  
  49.         close(pipe_fd[0]); //父进程先关闭了管道的读端  
  50.         if(write(pipe_fd[1],"Hello",5)!=-1)  
  51.             printf("parent write1 Hello!\n");  
  52.         if(write(pipe_fd[1]," Pipe",5)!=-1)  
  53.             printf("parent write2 Pipe!\n");  
  54.         close(pipe_fd[1]);  
  55.         waitpid(pid,NULL,0); /*等待子进程结束*/  
  56.         exit(0);  
  57.     }  
  58.     return 0;  
  59. }  


命名管道

 

命名管道和无名管道基本相同,但也有不同点:无名管道只能有父进程使用;但是通过命名管道,不相关的进程也能交换数据。

命名管道的创建

#include <sys/types.h>

#include <sys/stat.h>

int mkfifo(const char *pathname,mode_t mode)

pathname:FIFO文件名

mode:属性(与文件操作相同)
一旦创建了一个FIFO,就可以用open打开它,一般的文件访问函数(close,read,write)都可以用于FIFO

当打开FIFO时,非阻塞标志(O_NONBLOCK)

将对以后的读写产生如下影响:

1 没有使用 O_NONBLOCK:访问要求无法满足时进程阻塞。如读取空的FIFO时,或者FIFO已满时。

2 使用O_NONBLOCK:访问要求无法满足时不阻塞,立即出错返回,error是ENXIO。

FIFO读进程:

[cpp] view plaincopy
  1. /********************************************************** 
  2. *实验要求:   使用mkfifo创建有名管道并实现两个进程之间的通讯。 
  3. *功能描述:   创建一个进程,并从已经建立好的有名管道中,读出事先写入的 
  4. *           数据。 
  5. *日    期:   2010-9-17 
  6. *作    者:   国嵌 
  7. **********************************************************/  
  8. #include <sys/types.h>  
  9. #include <sys/stat.h>  
  10. #include <errno.h>  
  11. #include <fcntl.h>  
  12. #include <stdio.h>  
  13. #include <stdlib.h>  
  14. #include <string.h>  
  15. #define FIFO "/tmp/myfifo"  
  16.   
  17. /* 
  18.  * 程序入口 
  19.  * */  
  20. int main(int argc,char** argv)  
  21. {  
  22.     char buf_r[100];  
  23.     int  fd;  
  24.     int  nread;  
  25.   
  26.     printf("Preparing for reading bytes...\n");  
  27.     memset(buf_r,0,sizeof(buf_r));  
  28.       
  29.     /* 打开管道 */  
  30.     fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);  
  31.     if(fd==-1)  
  32.     {  
  33.         perror("open");  
  34.         exit(1);      
  35.     }  
  36.     while(1)  
  37.     {  
  38.         memset(buf_r,0,sizeof(buf_r));  
  39.           
  40.         if((nread=read(fd,buf_r,100))==-1)  
  41.         {  
  42.             if(errno==EAGAIN)  
  43.                 printf("no data yet\n");  
  44.         }  
  45.         printf("read %s from FIFO\n",buf_r);  
  46.         sleep(1);  
  47.     }  
  48.     /*后面三句话是不会被运行到的,但不会影响程序运行的效果当程序在上面的死循环中执行时收到信号后会马上结束运行而没有执行后面的三句话。这些会在后面的信号处理中讲到,现在不理解没有关系,这个问题留给大家学习了信号处理之后来解决。*/  
  49.     close(fd); //关闭管道  
  50.     pause(); /*暂停,等待信号*/  
  51.     unlink(FIFO); //删除文件  
  52. }  


FIFO写进程:

[cpp] view plaincopy
  1. /********************************************************** 
  2. *实验要求:   使用mkfifo创建有名管道并实现两个进程之间的通讯。 
  3. *功能描述:   创建一个进程,并在其中创建一个有名管道,并向其写入数据。 
  4. *日    期:   2010-9-17 
  5. *作    者:   国嵌 
  6. **********************************************************/  
  7. #include <sys/types.h>  
  8. #include <sys/stat.h>  
  9. #include <errno.h>  
  10. #include <fcntl.h>  
  11. #include <stdio.h>  
  12. #include <stdlib.h>  
  13. #include <string.h>  
  14. #define FIFO_SERVER "/tmp/myfifo"  
  15.   
  16. /* 
  17.  * 程序入口 
  18.  * */  
  19. int main(int argc,char** argv)  
  20. {  
  21.     int fd;  
  22.     char w_buf[100];  
  23.     int nwrite;  
  24.       
  25.     /*创建有名管道*/  
  26.     if((mkfifo(FIFO_SERVER,O_CREAT|O_EXCL|O_RDWR)<0)&&(errno!=EEXIST))  
  27.     {  
  28.         printf("cannot create fifoserver\n");  
  29.     }  
  30.   
  31.     /*打开管道*/  
  32.     fd=open(FIFO_SERVER,O_WRONLY |O_NONBLOCK,0);  
  33.     if(fd==-1)  
  34.     {  
  35.         perror("open");  
  36.         exit(1);  
  37.     }  
  38.       
  39.     /*入参检测*/  
  40.     if(argc==1)  
  41.     {  
  42.         printf("Please send something\n");  
  43.         exit(-1);  
  44.     }  
  45.     strcpy(w_buf,argv[1]);  
  46.       
  47.     /* 向管道写入数据 */  
  48.     if((nwrite=write(fd,w_buf,100))==-1)  
  49.     {  
  50.         if(errno==EAGAIN)  
  51.             printf("The FIFO has not been read yet.Please try later\n");  
  52.     }  
  53.     else   
  54.     {  
  55.         printf("write %s to the FIFO\n",w_buf);  
  56.     }  
  57.     close(fd); //关闭管道  
  58.     return 0;  
  59. }  


运行读进程结果如下:

打开另外一个终端,运行写进程结果如下:

同时读进程结果发生变化如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459089.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 终端下 dstat 监控工具

dstat 是一个可以取代vmstat&#xff0c;iostat&#xff0c;netstat和ifstat这些命令的多功能产品。dstat克服了这些命令的局限并增加了一些另外的功能&#xff0c;增加了监控项&#xff0c;也变得更灵活了。dstat可以很方便监控系统运行状况并用于基准测试和排除故障。dstat可…

运用HTML5+CSS3和CSS滤镜做的精美的登录界面

原始出处http://chenjinfei.blog.51cto.com/2965201/774865<!DOCTYPE HTML> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetgb2312"> <meta http-equiv"description" content"运用C…

MyEclipse使用总结——MyEclipse文件查找技巧 ctrl+shift+R ctrl+H

一、查找文件 使用快捷键【ctrlshiftR】弹出弹出文件查找框&#xff0c;如下图所示&#xff1a; 二、查找包含某个字符串的文件 使用快捷键【ctrlH】在弹出对话框中选File Search选项&#xff0c;然后在第一个文本框中粘贴&#xff08;我一般用粘贴&#xff09;或自已手动录入&…

java实现控件绑定数据源_控件(三)——TreeView控件以XmlDataSource控件为数据源实现简单的绑定...

TreeView控件功能非常强大&#xff0c;今天&#xff0c;我们只是窥其一角。我们实现的例子是&#xff1a;TreeView控件与XmlDataSource控件绑定&#xff0c;然后在网页显示选中项。首先我们添加一个xml&#xff0c;取名为tv.xml。在其中写上如下代码&#xff1a;这时我们在defa…

手机屏幕原理和设计(触摸屏幕)

//本文参考了很多百度百科的知识  随着android手机的流行&#xff0c;手机触摸屏成为一个时尚。再购机的时候&#xff0c;就会有很多人去问手机的触屏是电阻式的还是电容式的呢&#xff1f;但是其实很多人应该是不知道个中的原委的。只是一个感觉电容式的一定要比电阻式的好。…

extjs5(05--主界面上加入顶部和底部区域)

这一节为主界面加一个顶部区域和底部区域。一个管理系统的界面可以粗分为顶部标题部分、中间数据展示和处理的部分、底部备注和状态部分。 在增加这二个区域之前&#xff0c;我们先在MainModel.js中加入一些数据。 1 Ext.define(app.view.main.MainModel, {2 extend: Ext.a…

java mongo 查询数组_MongoDB查询(数组、内嵌文档)

一、简介我们上一篇介绍了db.collection.find()可以实现根据条件查询和指定使用投影运算符返回的字段省略此参数返回匹配文档中的所有字段&#xff0c;我们今天介绍了对数组和内嵌文档的查询操作&#xff0c;尤其是对$elemMatch 同样可以用在find方法的第二个参数来限制返回数组…

手机触摸屏的分类和原理,供大家选择手机时用

转载自&#xff1a;http://www.51testing.com/?uid-144635-action-viewspace-itemid-216296 必大家很关心的一个问题就是手机的触摸屏寿命是多少吧&#xff01;还有就是到底是电阻式触摸屏&#xff08;诺基亚的&#xff09;好还是电容式触摸屏&#xff08;iPhone等&#xff09…

Actionbarsherlock Demo 浅析 :Overlay

让Actionbar处于覆盖模式&#xff0c;当Activity需要显示大量滚动的内容&#xff0c;尤其是包含图片内容的时候&#xff0c;Overlay模式非常有效。 requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);//将Actionbar设置为Overlay模式。 getSupportActionBar().setBackg…

浅析C#中构建多线程应用程序

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 引言 1.理解多线程 2. 线程异步与线程同步 3.创建多线程应用程序 3.1通过System.Threa…

58同城高性能移动Push推送平台架构演进之路

2019独角兽企业重金招聘Python工程师标准>>> 本文详细讲述58同城高性能移动Push推送平台架构演进的三个阶段&#xff0c;并介绍了什么是移动Push推送&#xff0c;为什么需要&#xff0c;原理和方案对比&#xff1b;移动Push推送第一阶段&#xff08;单平台&#xff…

java不规则算法_分布式id生成算法 snowflake 详解

背景在复杂分布式系统中&#xff0c;往往需要对大量的数据和消息进行唯一标识。如在支付流水号、订单号等&#xff0c;随者业务数据日渐增长&#xff0c;对数据分库分表后需要有一个唯一ID来标识一条数据或消息&#xff0c;数据库的自增ID显然不能满足需求&#xff0c;此时一个…

Android中下载、安装和卸载(原)

应用场景&#xff1a;在检查版本更新的时候经常需要从服务器端下载然后安装到手机中 使用工具&#xff1a; XUtils&#xff0c;这个开源的框架真的是需要花大把时间去阅读和理解的&#xff0c;十分有用的&#xff0c;on the way &#xff01; fighting&#xff01; 下载&#x…

python对文件进行读写操作

2019独角兽企业重金招聘Python工程师标准>>> python进行文件读写的函数是open或file file_handler open(filename,,mode&#xff09; Table mode 模式描述r以读方式打开文件&#xff0c;可读取文件信息。w以写方式打开文件&#xff0c;可向文件写入信息。如文件存在…

[转]VisualStudio如何组织解决方案的目录结构

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 解决方案与项目&#xff1a; 从VC6之后VC系列就使用解决方案&#xff08;Solution&…

java几种删除_几种删除Linux目录的方法

在Linux中有很多方法可以删除目录&#xff0c;在图形化界面可以利用文件管理器&#xff0c;或者通过终端删除。本文将介绍在文本界面使用命令删除目录。使用rmdir删除目录Rmdir命令间成“remove directory”&#xff0c;用于删除空目录的命令。例如&#xff0c;删除一个名为“M…

【SpringMVC】SpringMVC系列6之@CookieValue 映射请求Cookie 值

6、CookieValue 映射请求Cookie 值 6.1、示例 CookieValue 可让处理方法入参绑定某个 Cookie 值&#xff0c;示例如下&#xff1a;

杭电OJ-2104_hide handkerchief超简洁代码

#include<iostream> using namespace std; int n, m;; int zz(int a, int b) {return b0 ? a: zz(b, a%b); } int main() {while (cin >> n >> m&&n ! -1 && m ! -1)cout << (nb(n, m) 1 ? "YES" : "POOR Haha"…

c# Invoke和BeginInvoke

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 转自&#xff1a;http://blog.3snews.net/html/30/34530-27563.html在多线程编程中&am…

Oracle手边常用70则脚本知识汇总

Oracle手边常用70则脚本知识汇总 作者&#xff1a;白宁超 时间&#xff1a;2016年3月4日13:58:36 摘要: 日常使用oracle数据库过程中&#xff0c;常用脚本命令莫不是用户和密码、表空间、多表联合、执行语句等常规操作。另外表的导入导出也很常用&#xff0c;这些脚步命令之前都…