管道

管道是unix ipc的最古老形式,是一种在内存中的特殊文件,只能在具有公共祖先的进程之间使用(即父子进程,兄弟进程)。

管道由pipe函数创建

#include <unistd.h>

int pipe(int fd[])

fd[1]写,fd[0]读。

单个进程的管道几乎没有任何用处,通常,调用pipe的进程接着调用fork,这样就创建了父子进程间的管道。

#include <unistd.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h> int main()
{
int fd[];
char buf[];
pid_t pid;
pipe(fd);
pid = fork();
if(pid>)
{//父进程
printf("Father thread\n");
char s[]="Hello\n";
write(fd[],s,sizeof(s));
close(fd[]);
close(fd[]);
}
else if(pid==)
{
printf("Child Thread\n");
read(fd[],buf,sizeof(buf));
printf("%s\n",buf);
close(fd[]);
close(fd[]);
}
waitpid(pid,NULL,);//等待子进程结束
return ;
}

输出结果:

Father thread
Child Thread
Hello

当管道的一端关闭时:

  当读一个写端关闭的管道时,则认为已经读到了数据的末尾,读函数返回的读出字节数为0;

  当写一个读端关闭的管道时,向管道中写入数据的进程将收到内核传来的SIFPIPE信号,应用程序可以处理该信号,也可以忽略(默认动作则            是应用程序终止)。

从管道中读取数据:

当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,如果请求的字节数目不大于PIPE_BUF,则返回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);或者返回请求的字节数(此时,管道中数据量不小于请求的数据量)。注:PIPE_BUF在include/linux/limits.h中定义。

向管道中写入数据:

向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。

管道因为没有名字所以只能用于具有亲缘关系的进程,而有名管道(FIFO)则克服了这个限制。

FIFO

创建函数如下

 #include <sys/types.h>
#include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode);

第一个参数是一个普通的路径名,即为FIFO的名字。第二个参数设置权限,跟创建普通文件一样。

FIFO的读写也像普通文件一样,不过需要读写端都打开,具体规则如下:

当打开(open)时:

若没有设置O_NONBLOCK,只读open要阻塞到其它进程为写而打开FIFO。类似地,只写open要阻塞到其它进程为读而打开FIFO。

如果设置了O_NONBLOCK,则只读open立即返回,若没有其它进程为写而打开FIFO,则返回-1。

用FIFO模拟生产者消费者问题:

fifo2.cpp:

#include<iostream>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> #define FIFO "/tmp/myfifo"
#define BUF_SIZE PIPE_BUF
#define SEND_MAX (1024*1024*10)
using namespace std; int main()
{
int pid,fifo_fd;
int send_num;
char *buf[BUF_SIZE+];
if(- == access(FIFO,F_OK))
{
int res = mkfifo(FIFO,);
if(res != )
{
fprintf(stderr,"can't create fifo in %s",FIFO);
exit(EXIT_FAILURE);
}
} fifo_fd = open(FIFO,O_WRONLY);
printf("process %d open fifo %d\r\n",getpid(),fifo_fd);
if(fifo_fd == -)
exit(EXIT_FAILURE);
int res;
while(send_num<SEND_MAX)
{
res = write(fifo_fd,buf,BUF_SIZE);
if(res == -)
{
cout<<"write fifo error"<<endl;
exit(EXIT_FAILURE);
}
send_num += res;
}
return ;
}

fifo3.cpp

#include<iostream>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> #define FIFO "/tmp/myfifo"
#define BUF_SIZE PIPE_BUF
#define SEND_MAX (1024*1024*10)
using namespace std; int main()
{
int fifo_fd;
int res;
char buffer[BUF_SIZE+];
int read_num = ; fifo_fd = open(FIFO,O_RDONLY);
printf("process %d open FIFO %d\r\n",getpid(),fifo_fd);
if(fifo_fd == -)
exit(EXIT_FAILURE);
do{
res = read(fifo_fd,buffer,BUF_SIZE);
read_num += res;
}while(res>);
close(fifo_fd);
return ;
}

结果如下:

可见读进程运行0.013s就读取了10m的数据,FIFO的效率还是很高的。

linux IPC总结——管道的更多相关文章

  1. Linux IPC之管道通信

    2017-04-07 管道通信在linux中使用较为频繁的进程通信机制.基于unix一切皆文件的传统,管道也是一种文件.所以可以使用一般的VFS接口对管道进行读写操作,如read.write.具体管道 ...

  2. Linux IPC实践(1) -- 概述

    进程的同步与互斥 进程同步: 多个进程需要相互配合共同完成一项任务. 进程互斥: 由于各进程要求共享资源,而且有些资源需要互斥使用,因此各进程间竞争使用这些资源,进程的这种关系为进程的互斥;系统中某些 ...

  3. Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)

    整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道 ...

  4. linux ipc/its

    linux进程间双向消息队列 server.c #include <stdio.h> #include <stdlib.h> #include <string.h> ...

  5. Linux下的管道命令有这些:

    Linux下的管道命令有这些: 选取命令:cat grep 排序命令:sort wc uniq 双向重定向:tee 字符转换命令: tr, col, join, paste, expand 切割命令: ...

  6. linux进程的管道通信

    linux进程的管道通信 要求 编程实现进程的管道通信,掌握管道通信的同步和互斥机制. 相关函数 pipe管道 指用于连接一个读进程和一个写进程以实现他们之间通信的一个共享文件,又名pipe文件.向管 ...

  7. Linux IPC之共享内存C 事例

    Linux IPC之共享内存 标签: linuxrandomnull工作 2011-08-25 11:52 4123人阅读 评论(0) 收藏 举报  分类: Linux(3)  读书札记(3)  版权 ...

  8. 【Linux】【专项突破】Linux重定向与管道

    [专项突破]Linux重定向与管道 This article is written by Xrilang(Chinese Name:萌狼蓝天) If you want find me ,You can ...

  9. 【Linux 应用编程】进程管理 - 进程间通信IPC之管道 pipe 和 FIFO

    IPC(InterProcess Communication,进程间通信)是进程中的重要概念.Linux 进程之间常用的通信方式有: 文件:简单,低效,需要代码控制同步 管道:使用简单,默认阻塞 匿名 ...

随机推荐

  1. rpm命令详解

    http://www.rpm.org/max-rpm/s1-rpm-install-additional-options.html#S2-RPM-INSTALL-REPLACEFILES-OPTION ...

  2. 判断JS对象是否拥有某属性的方法举例

    判断JS对象是否拥有某属性 JS是否拥有某属性的判断方法,这里提供两种方式,供大家参考. 1.in 运算符 var obj = {name:'jack'}; alert('name' in obj); ...

  3. ajax GET和POST请求web api 的几种方式

    GET请求 1.无参数get请求 一般get请求有两种写法,一种是 $.get()   一种是$.ajax({type:"get"}), 我个人比较喜欢用后者. 下面例子主要是ge ...

  4. 【转】Ext JS xtype

      原文:Ext 中xtype一览 基本组件: xtype Class 描述 button Ext.Button 按钮 splitbutton Ext.SplitButton 带下拉菜单的按钮 cyc ...

  5. hbuilder工具快捷键 http://www.qq210.com/shoutu/android

    http://www.qq210.com/shoutu/android 创建HTML结构: h 8 (敲h激活代码块列表,按8选择第8个项目,即HTML代码块,或者敲h t Enter)中途换行: ' ...

  6. echo、print、print_r、printf、sprintf、var_dump的区别比较

    一.echoecho() 实际上不是一个函数,是php语句,因此您无需对其使用括号.不过,如果您希望向 echo() 传递一个以上的参数,那么使用括号会发生解析错误.而且echo是返回void的,并不 ...

  7. MySql 在大数量的统计中具体的使用技巧

    一.CASE WHEN THEN ELSE END 使用用法. 在用sql语句统计某字段的某种状态的出现的次数,可以考虑用到 CASE WHEN THEN ELSE END 使用用法.当数据量过于庞大 ...

  8. “T”必须是具有公共的无参数构造函数的非抽象类型,才能用作泛型类型或方法

    最近在项目中,使用EF编程时,在使用泛型类型的过程中,写了一上午,结果生成时,编译不通过,报出如下错误: “T”必须是具有公共的无参数构造函数的非抽象类型,才能用作泛型类型或方法.如图: 找了好久,终 ...

  9. 从 IT 的角度思考 BIM(一):面向对象

    还记得那个笑话吗:要把大象放进冰箱,总共分几步?这不仅仅是一个笑话,还是一个值得我们好好分析的笑话. 如果要放进冰箱的是一个苹果,那么也就不可笑了,但换成大象,就引起了我们的兴趣和注意,为什么? 我们 ...

  10. TCP/IP入门学习(1)---分层概述

    本文旨在记述一些学习中的笔记 OSI分层:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层 详细点: 1.应用层:为应用程序提供服务并规定程序中通信相关细节. 2.表示层:将应用处理的信息转 ...