Linux 进程间通信(二) 管道
Linux 进程间通信-管道
进程是一个独立的资源分配单位,不同进程之间的资源是相互独立的,没有关联,不能在一个进程中直接访问另一个进程中的资源。但是,进程不是孤立的,不同的进程之间需要信息的交换以及状态的传递,因此需要进程间数据传递、同步与异步的机制。
此篇博文记录管道。
管道pipe
管道是进程间通信的主要手段之一。一个管道实际上就是个只存在于内存中的文件,对这个文件的操作要通过两个已经打开文件进行,它们分别代表管道的两端。管道是一种特殊的文件,它不属于某一种文件系统,而是一种独立的文件系统,有其自己的数据结构。根据管道的适用范围将其分为:无名管道和命名管道。
管道分类
● 无名管道
主要用于父进程与子进程之间,或者两个兄弟进程之间。在linux系统中可以通过系统调用建立起一个单向的通信管道,且这种关系只能由父进程来建立。因此,每个管道都是单向的,当需要双向通信时就需要建立起两个管道。管道两端的进程均将该管道看做一个文件,一个进程负责往管道中写内容,而另一个从管道中读取。这种传输遵循“先入先出”(FIFO)的规则。
● 命名管道
命名管道是为了解决无名管道只能用于近亲进程之间通信的缺陷而设计的。命名管道是建立在实际的磁盘介质或文件系统(而不是只存在于内存中)上有自己名字的文件,任何进程可以在任何时间通过文件名或路径名与该文件建立联系。为了实现命名管道,引入了一种新的文件类型——FIFO文件(遵循先进先出的原则)。实现一个命名管道实际上就是实现一个FIFO文件。命名管道一旦建立,之后它的读、写以及关闭操作都与普通管道完全相同。虽然FIFO文件的inode节点在磁盘上,但是仅是一个节点而已,文件的数据还是存在于内存缓冲页面中,和普通管道相同。
管道的读写
写入管道的数据按到达次序排列。如果管道满,则对管道的写被阻塞,直到管道的数据被读操作读取。对于写操作,如果一次write调用写的数据量小于管道容量,则写必须一次完成,即如果管道所剩余的容量不够,write被阻塞直到管道的剩余容量可以一次写完为止。如果write调用写的数据量大于管道容量,则写操作分多次完成。如果用fcntl设置管道写端口为非阻塞方式,则管道满不会阻塞写,而只是对写返回0。
读操作按数据到达的顺序读取数据。已经被读取的数据在管道内不再存在,这意味着数据在管道中不能重复利用。如果管道为空,且管道的写端口是打开状态,则读操作被阻塞直到有数据写入为止。一次read调用,如果管道中的数据量不够read指定的数量,则按实际的数量读取,并对read返回实际数量值。如果读端口使用fcntl设置了非阻塞方式,则当管道为空时,read调用返回0。
如果管道的读端口关闭,那么在该管道上的发出写操作调用的进程将接收到一个SIGPIPE信号。关闭写端口是给读端口一个文件结束符的唯一方法。对于写端口关闭后,在该管道上的read调用将返回0。
无名管道
用于父进程与子进程之间,或者两个兄弟进程之间。
函数说明
/* 管道 */ #include <unistd.h> /* 建立管道 */
int pipe(int filedes[]); /*
filedes[0]为管道里的读取端
filedes[1]为管道里的写入端 返回值: 成功返回-1,错误返回-1,错误存于errno中 错误代码:
EMFILE 进程已用完文件描述词最大量
ENFILE 系统已无文件描述符可用
EFAULT 参数filedes数组地址不合法
*/ /* 阻塞设置 */
fcntl(filedes[], F_SETFL, O_NONBLOCK);
fcntl(filedes[], F_SETFL, O_NONBLOCK); /* 读写 */
read(fd, buf, sizeof(buf));
write(fd, buf, sizeof(buf));
实例
#include <unistd.h>
#include <stdio.h> int main()
{
int p[];
char buf[];
char buf0[];
pid_t pid; strcpy(buf,"Hello World!"); pipe(p); if((pid = fork()) > ){
printf("This is father process.\n\n");
write(p[], buf, strlen(buf));
close(p[]);
close(p[]);
}
else{
printf("This is child process.\n");
read(p[], buf0, sizeof(buf0));
printf("%s\n", buf0);
close(p[]);
close(p[]);
} return ;
}
命名管道
能用于近亲进程之间通信。
函数说明
/* 命名管道 */ #include <sys/types.h>
#include <sys/stat.h> /* 建立管道 */
int mkfifo(const char * pathname, mode_t mode);
/*
pathname 路径,创建管道的位置
mode 打开函数open中的Mode
*/ /* 打开管道 */
int open(const char *pathname,int oflag,... /* mode_t mode */);
/*
mode 可选:O_RDONLY | O_WRONLY | O_NONBLOC
*/ /* 读写 */
int read(int fd, void *buf, int nbyte)
int write(int fd, void *buf, int nbyte) /* 关闭 */
close(int handle)
实例
/* fifo_write.c */
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h> int main()
{
const char* pathname = "m_fifo";
int pipe_fd = -;
int bytes;
char buf[]; strcpy(buf, "hello world!"); mkfifo(pathname, ); pipe_fd = open(pathname, O_WRONLY); printf("Process %d result %d\n", getpid(), pipe_fd); write(pipe_fd, buf, strlen(buf)); printf("Process %d finished!\n", getpid()); return ;
}
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> int main()
{
const char* pathname = "m_fifo";
char buf[];
int pipe_fd; pipe_fd = open(pathname, O_RDONLY); printf("Process %d result %d\n", getpid(), pipe_fd); read(pipe_fd, buf, sizeof(buf)); close(pipe_fd); printf("Process %d finished,\n read content: %s \n", getpid(), buf); return ;
}
参考
http://blog.csdn.net/myarrow/article/details/9037135
http://blog.sina.com.cn/s/blog_4e9440910100yihb.html
http://blog.sina.com.cn/s/blog_67b7d7e401018dvz.html
http://blog.csdn.net/guxch/article/details/6828452
本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。欢迎转载,请注明出处:
转载自:cococo点点 http://www.cnblogs.com/coder2012
Linux 进程间通信(二) 管道的更多相关文章
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道 ...
- Linux进程间通信之管道
1,进程间通信 (IPC ) Inter-Process Communication 比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息. 2,linux下IPC机制的分类:管道.信号.共 ...
- Linux - 进程间通信 - 匿名管道
一.概念:进程间通信( IPC,InterProcess Communication) 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进城之间要交换数据必须通过内 ...
- Linux 进程间通信之管道(pipe),(fifo)
无名管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信: 定义函数: int pipe(int f ...
- Linux进程间通信(一) - 管道
管道(pipe) 普通的Linux shell都允许重定向,而重定向使用的就是管道. 例如:ps | grep vsftpd .管道是单向的.先进先出的.无结构的.固定大小的字节流,它把一个进程的标准 ...
- Linux -- 进程间通信之管道
管道是 Linux 里的一种文件类型,同时也是 Linux 系统下进程间通信的一种方式 创建一个管道文件有两种方式: Shell 下命令 mkfifo + filename,即创建一个有名管道 ...
- linux进程间通信-有名管道(FIFO)
有名管道(FIFO) 命名管道也被称为FIFO文件,是一种特殊的文件.由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一. (1)创建命名管道 用如下两个函数中的 ...
- Linux进程间通信-命名管道
前面我们讲了进程间通信的一种方式,匿名管道.我们知道,匿名管道只能用于父子关系的进程之间.那么没有这种关系的进程之间该如何进行数据传递呢? 1.什么是命名管道 匿名管道是在缓存中开辟的输出和输入文件流 ...
- Linux进程间通信-匿名管道
前面我们讲了进程间通信的一种方式,共享内存.下面看一看另一种机制,匿名管道.1.什么是管道管道是一个进程的数据流到另一个进程的通道,即一个进程的数据输出作为另一个进程的数据输入,管道起到了桥梁的作用. ...
随机推荐
- VC++绘图时,利用双缓冲解决屏幕闪烁 转载
最近做中国象棋,绘制界面时遇到些问题,绘图过程中屏幕闪烁,估计都会想到利用双缓冲来解决问题,但查了下网上双缓冲的资料,发现基本是MFC的,转化为VC++后,大概代码如下: void DrawBmp(H ...
- Ubuntu-12.04-server 配置修改静态 IP地址
前几天在装Ubuntu 12.04 Server版系统的服务器时IP地址写错了,导致服务器不能上网,今天重新修改了一下IP地址,这里做一个总结. 1.配置静态IP地址 sudo vi /etc/net ...
- java打包遇到问题java.io.IOException: invalid header field
问题:java打包时报以下错误 $ jar -cvmf main.txt test.jar Shufile1.class java.io.IOException: invalid header fie ...
- java break语句的三种用法
1.用于switch语句当中,用于终止语句 2.用于跳出循环,此为不带标签的break语句,相当与goto的作用 e.g while(i<j&&h<k){ if(h< ...
- The string "--" is not permitted within comments
ibatis中SAXParseException异常:The string "--" is not permitted within comments 这个异常是说sqlmap里面 ...
- SQLServer语句 汇总
SQL Server语句 序号 功能 语句 1 创建数据库(创建之前判断该数据库是否存在) if exists (select * from sysdatabases where name='data ...
- dede channelartlist 中引用channel 并且设置当前选择类的样式,currentstyle暂时没有效果.特发求助!!!!
在dede中需要达到当前选择了该类,样式不同的话.如果是channelartlist 的话. 可以使用下面的情况: {dede:channelartlist typeid='6' row='3' cu ...
- Xshell连接虚拟机
一般连接虚拟机失败 原因1:ip地址错误 当输入 ifconfig 只有lo没有eth0,或者有eth0,但eth0中确没有inet addr这一行 输入命令:dhclient eth0 就可以了
- RAID配置
一.madam -a 检测设备名称 -n 指定硬盘数量 -l 指定raid级别 -C 创建 -f 模拟硬盘故障 -r 移除硬盘 -a ...
- 【Java学习笔记】Map借口的子接口----HashMap
存储在HashMap集合中的元素,必须覆盖hashCode和equals方法(与HashSet类似) import java.util.HashMap; import java.util.Iter ...