管道和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的更多相关文章

  1. linux有名管道fifo,进程间通信

    命名管道(FIFO)不同于无名管道之处在于它提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中,这样,即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通 ...

  2. 进程间通讯:有名管道FIFO

    接收端: #include <sys/stat.h> #include <sys/types.h> #include <stdio.h> #include < ...

  3. 有名管道FIFO进程间数据传输实例

    紧接着上面一个博客的简单介绍,下面进行一个没有血缘关系的进程间通信的实例,实现文件拷贝传输. 有两个进程,一个主要是fifow进程:读文件Makefile内容,写入管道;另一个进程fifor:读管道内 ...

  4. Linux 进程间通信 有名管道(fifo)

    有名管道特点: 1)无名管道只能用于具有亲缘关系的进程之间,这就限制了无名管道的使用范围 2)有名管道可以使互不相关的两个进程互相通信. 3)有名管道可以通过路径名来指出,并且在文件系统中可见,但内容 ...

  5. Linux进程间通信---管道和有名管道

    一.管道 管道:管道是一种半双工的通信方式,数据只能单方向流动,而且只能在具有亲缘关系的进程间使用,因为管道 传递数据的单向性,管道又称为半双工管道.进程的亲缘关系通常是指父子进程关系. 管道的特点决 ...

  6. linux进程间通信-有名管道(FIFO)

    有名管道(FIFO) 命名管道也被称为FIFO文件,是一种特殊的文件.由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一. (1)创建命名管道 用如下两个函数中的 ...

  7. linux 有名管道(FIFO)

    http://blog.csdn.net/firefoxbug/article/details/8137762 linux 有名管道(FIFO) 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时 ...

  8. 进程间通信IPC之--无名管道(pipe)和有名管道(fifo)(转)

     进程间通信IPC之--无名管道(pipe)和有名管道(fifo) 2012-01-17 22:41:20 分类: C/C++ 每个进程各自有不同的用户地址空间,任何一个进 程的全局变量在另一个进程中 ...

  9. Unix/Linux进程间通信(二):匿名管道、有名管道 pipe()、mkfifo()

    1. 管道概述及相关API应用 1.1 管道相关的关键概念 管道是Linux支持的最初Unix IPC形式之一,具有以下特点: 管道是半双工的,数据只能向一个方向流动:需要双方通信时,需要建立起两个管 ...

随机推荐

  1. 【linux】Linux 进程状态

    linux上进程有5种状态: 1. 运行(正在运行或在运行队列中等待) 2. 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号) 3. 不可中断(收到信号不唤醒和不可运行, 进程必须等待直到有 ...

  2. LwIP下一种可能耗尽内存的情况

    若App在连接断开后仍旧使用该tcp_pcb发送数据,LwIP会自动发送SYNC试图重建连接.若对方不响应(指没有任何响应)而App又在不断发送数据,将导致LwIP不停的发送新的SYNC(每试图发送一 ...

  3. sikuli 安装

    1     简介 官方介绍: Sikuli脚本自动化,你在屏幕上看到的任何东西.它使用图像识别,识别和控制GUI组件.这是有用的,当有一个GUI的内部或源代码的访问是不容易的. Sikuli(在墨西哥 ...

  4. Linux期中架构 全网备份案例

    server端脚本 #!/bin/bash #1 进行数据完整性验证 并生成结果 find /backup -type f -name "finger.txt"| xargs md ...

  5. 1111 Online Map (30 分)

    1111 Online Map (30 分) Input our current position and a destination, an online map can recommend sev ...

  6. ubuntu 常用命令集锦

    一.文件/文件夹管理 ls 列出当前目录文件(不包括隐含文件) ls -a 列出当前目录文件(包括隐含文件) ls -l 列出当前目录下文件的详细信息 cd .. 回当前目录的上一级目录 cd - 回 ...

  7. C#后台调用前台javascript的五种方法小结

    第一种,OnClientClick (vs2003不支持这个方法) <asp:Button ID="Button1" runat="server" Tex ...

  8. 在ubuntu中如何向U盘复制粘贴文件 Read-only file system

    1.  重新挂载被操作分区的读写权限,如U盘 $ sudo mount -o remount,rw /media/lenmom/00093FA700017B96 #U盘挂载目录,如果是系统中的其他盘, ...

  9. 为github帐号添加SSH keys(Linux和Windows)

    文章转自:https://blog.cofface.com/archives/406.html/2 一.Linux增加ssh keys方法: 使用git clone命令从github上同步github ...

  10. 使用nproxy代理本地服务到内网

    前端开发中:很多场景需要在局域网下的其他手机或设备查看网页, 问题来了, web服务部署在本机的某个端口上(8080),只能通过本机浏览器访问,  怎样能让局域网下的其他设备也访问呢?可能你会说 关闭 ...