有名管道FIFO
管道和FIFO的特征之一是它们的数据是一个字节流。这是UNIX的原生I/O模型。进程往其中写入的是字节流,系统不对它作解释。
FIFO不存数据,只是通过它找到内核文件。
一.建立有名管道
1.命令mknod :
mknod name p/s/m //创建管道文件/信号量/共享内存
2.命令mkfifo 创建管道
mkfifo -m 664 k2 //创建一个访问权限为664的管道文件k2
3作为函数:mkfifo
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
【注意】
mkfifo已隐含指定O_CREAT|O_EXCL。即它要么创建一个新的FIFO,要么返回一个EEXIST错误。如果只是希望打开而不创建文件,那就应调用open而不是mkfifo。
要打开一个已存在的FIFO或创建一个新的FIFO,应先调用mkfifo,检查它是否返回EEXIST错误,若返回则改为调用open。
另:open函数
open(const char *path, O_RDONLY);//1
open(const char *path, O_RDONLY | O_NONBLOCK);//2
open(const char *path, O_WRONLY);//3
open(const char *path, O_WRONLY | O_NONBLOCK);//4
1、就是程序不能以O_RDWR(读写)模式打开FIFO文件进行读写操作,而其行为也未明确定义,因为如一个管道以读/写方式打开,进程就会读回自己的输出,同时我们通常使用FIFO只是为了单向的数据传递。
2、就是传递给open的是FIFO的路径名,而不是文件名。
3.第二个参数中的选项O_NONBLOCK,选项O_NONBLOCK表示非阻塞,加上这个选项后,表示open调用是非阻塞的,如果没有这个选项,则表示open调用是阻塞的。
以只读方式和只写方式打开文件时要注意:
读端打开,如果写端已打开则打开操作成功返回,如果写端没打开,则读端阻塞。如果是非阻塞函数,则成功返回,(读到文件结束标志)
写端打开,如果读端已打开则打开操作成功返回,如果读端没打开,则写端阻塞。如果是非阻塞函数,则返回ENXIO错误(产生信号SIGPIPE)
从FIFO中读取数据:
1. 读端的阻塞标志只对本进程第一个读操作施加作用,如果本进程内有多个读操作序列,则在第一个读操作被唤醒并完成读操作后,其它将要执行的读操作将不再阻塞,即使在执行读操作时,FIFO中没有数据也一样(此时,读操作返回0)。
2. 对于设置了阻塞标志的读操作说,造成阻塞的原因有两种:当前FIFO内有数据,但有其它进程在读这些数据;另外就是FIFO内没有数据。解阻塞的原因则是FIFO中有新的数据写入,不论写入数据量的大小,也不论读操作请求多少数据量。就是说读操作同时只可以有一个进程进行。
3. 如果有进程写打开FIFO,且当前FIFO内没有数据,则对于设置了阻塞标志的读操作来说,将一直阻塞。对于没有设置阻塞标志读操作来说则返回-1,当前errno值为EAGAIN,提醒以后再试。
向FIFO中写入数据:
1.对于设置了阻塞标志的写操作:
- 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果此时管道空闲缓冲区不足以容纳要写入的字节数,则进入睡眠,直到当缓冲区中能够容纳要写入的字节数时,才开始进行一次性写操作。
- 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。FIFO缓冲区一有空闲区域,写进程就会试图向管道写入数据,写操作在写完所有请求写的数据后返回。(这时读端可能间歇性得到数据)
2.对于没有设置阻塞标志的写操作:
- 当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。如果当前FIFO空闲缓冲区能够容纳请求写入的字节数,写完后成功返回;如果当前FIFO空闲缓冲区不能够容纳请求写入的字节数,则返回EAGAIN错误,提醒以后再写;
- 当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。在写满所有FIFO空闲缓冲区后,写操作返回。
FIFO内核实现时可以支持双向通信。(pipe单向通信,因为父子进程共享同一个file 结构体)
先关闭只读方式打开的文件,再以只写方式打开文件。这样就可以实现双向通信了。但最好使用一对FIFO
验证代码:
先写后读:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define MSG "hello"
int main()
{
int fd;
fd = open("./fio",O_WRONLY);
printf("w:send msg:%s\n",MSG);
write(fd,MSG,sizeof(MSG));
sleep();
close(fd);
fd = open("./fio",O_RDONLY);
char buf[];
memset(buf,,sizeof(buf));
read(fd,buf,sizeof(buf));
printf("w,recv:%s\n",buf); }
先读后写:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main()
{
int fd;
fd = open("./fio",O_RDONLY);
char buf[];
memset(buf,,sizeof(buf));
read(fd,buf,sizeof(buf));
printf("r:recv msg:%s\n",buf); sleep();
close(fd);
fd = open("./fio",O_WRONLY);
printf("r:send:%s\n","fighting");
write(fd,"fighting",); }
安全问题:
个FIFO文件,有多个进程同时向同一个FIFO文件写数据,而只有一个读FIFO进程在同一个FIFO文件中读取数据时,会发生数据块的相互交错。
根据上面的知识我们知道:
如果所有的写请求都是发往一个阻塞的FIFO的,并且每个写记请求的数据长度小于等于PIPE_BUF字节,系统就可以确保数据决不会交错在一起。
模型:
1-1
n-1
n-1-n
fgets,它读取以换行符“\n”结尾的字符串.
小结:
管道文件。它占用i节点块和数据块,在目录文件中记载了文件和i节点对应关系的管道是有名管道,没有记载的是无名管道。
管道文件一旦读出,就从管道中删除,所以它具有不可再现性。
有名管道FIFO的更多相关文章
- linux有名管道fifo,进程间通信
命名管道(FIFO)不同于无名管道之处在于它提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中,这样,即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通 ...
- 进程间通讯:有名管道FIFO
接收端: #include <sys/stat.h> #include <sys/types.h> #include <stdio.h> #include < ...
- 有名管道FIFO进程间数据传输实例
紧接着上面一个博客的简单介绍,下面进行一个没有血缘关系的进程间通信的实例,实现文件拷贝传输. 有两个进程,一个主要是fifow进程:读文件Makefile内容,写入管道;另一个进程fifor:读管道内 ...
- Linux 进程间通信 有名管道(fifo)
有名管道特点: 1)无名管道只能用于具有亲缘关系的进程之间,这就限制了无名管道的使用范围 2)有名管道可以使互不相关的两个进程互相通信. 3)有名管道可以通过路径名来指出,并且在文件系统中可见,但内容 ...
- Linux进程间通信---管道和有名管道
一.管道 管道:管道是一种半双工的通信方式,数据只能单方向流动,而且只能在具有亲缘关系的进程间使用,因为管道 传递数据的单向性,管道又称为半双工管道.进程的亲缘关系通常是指父子进程关系. 管道的特点决 ...
- linux进程间通信-有名管道(FIFO)
有名管道(FIFO) 命名管道也被称为FIFO文件,是一种特殊的文件.由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一. (1)创建命名管道 用如下两个函数中的 ...
- linux 有名管道(FIFO)
http://blog.csdn.net/firefoxbug/article/details/8137762 linux 有名管道(FIFO) 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时 ...
- 进程间通信IPC之--无名管道(pipe)和有名管道(fifo)(转)
进程间通信IPC之--无名管道(pipe)和有名管道(fifo) 2012-01-17 22:41:20 分类: C/C++ 每个进程各自有不同的用户地址空间,任何一个进 程的全局变量在另一个进程中 ...
- Unix/Linux进程间通信(二):匿名管道、有名管道 pipe()、mkfifo()
1. 管道概述及相关API应用 1.1 管道相关的关键概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管 ...
随机推荐
- 【python】网络编程-TCP协议套接字
服务器端: #!/usr/bin/env python from socket import * from time import ctime HOST = '' PORT = 21567 BUFSI ...
- SQL Server存储过程 对数组参数的循环处理
方法一 分割 例:通过SQL Server存储过程传送数组参数删除多条记录 eg. ID 值为'1,2,3' 以下存储过程就是删除表中id号为1,2,3的记录: CREATE PROCEDURE De ...
- Spring的IOC原理 通俗解释
1. IoC理论的背景我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最终实现系统的业务逻辑. 图1:软件系统中耦合的对象 如果我们打开机械 ...
- android 关于 webview 控制其它view的显示 以及更改view数据失败的问题总结
总结: 1.webview 无法直接更改view的属性,可以通过 handler实现,因为跨线程 2.webview可以通过js api读取 view的属性值 代码: private Handler ...
- 廖雪峰Java1-2程序基础-8字符和字符串
1.字符类型char char是基本的数据类型 char:保存一个字符,如英文字符.中文字符. Java使用unicode表示字符,可以将char赋值给int类型,查看字符对应的unicode编码. ...
- MySQL 误删用户
误删除root用户&误删除所有用户 #----------------------------------------------------------------------------- ...
- 1076 Forwards on Weibo (30 分)
1076 Forwards on Weibo (30 分) Weibo is known as the Chinese version of Twitter. One user on Weibo ma ...
- Impala源码分析
问题导读:1.Scheduler任务中Distributed Plan.Scan Range是什么?2.Scheduler基本接口有哪些?3.QuerySchedule这个类如何理解?4.Simple ...
- Web API源码剖析之HttpServer
Web API源码剖析之HttpServer 上一节我们讲述全局配置.本节将讲述全局配置的DefaultServer,它是一个HttpServer类型. 主要作用就是接受每一次请求,然后分发给消息处理 ...
- Spark分析之Master
override def preStart() { logInfo("Starting Spark master at " + masterUrl) webUi.bind() // ...