有名管道FIFO

管道和FIFO的特征之一是它们的数据是一个字节流。这是UNIX的原生I/O模型。进程往其中写入的是字节流,系统不对它做解释。linux

FIFO不存数据,只是经过它找到内核文件。安全

一.创建有名管道函数

1.命令mknod   :spa

mknod  name  p/s/m    //建立管道文件/信号量/共享内存code

2.命令mkfifo 建立管道blog

mkfifo -m 664 k2     //建立一个访问权限为664的管道文件k2 进程

3做为函数:mkfifoip

#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

一、就是程序不能以O_RDWR(读写)模式打开FIFO文件进行读写操做,而其行为也未明肯定义,由于如一个管道以读/写方式打开,进程就会读回本身的输出,同时咱们一般使用FIFO只是为了单向的数据传递。

二、就是传递给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(5); close(fd); fd = open("./fio",O_RDONLY); char buf[1024]; memset(buf,0,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[1024]; memset(buf,0,sizeof(buf)); read(fd,buf,sizeof(buf)); printf("r:recv msg:%s\n",buf); sleep(5); close(fd); fd = open("./fio",O_WRONLY); printf("r:send:%s\n","fighting"); write(fd,"fighting",9); }

安全问题:

个FIFO文件,有多个进程同时向同一个FIFO文件写数据,而只有一个读FIFO进程在同一个FIFO文件中读取数据时,会发生数据块的相互交错。

根据上面的知识咱们知道:

若是全部的写请求都是发往一个阻塞的FIFO的,而且每一个写记请求的数据长度小于等于PIPE_BUF字节,系统就能够确保数据决不会交错在一块儿。

模型:

1-1

n-1

n-1-n

 fgets,它读取以换行符“\n”结尾的字符串.

小结:

管道文件。它占用i节点块和数据块,在目录文件中记载了文件和i节点对应关系的管道是有名管道,没有记载的是无名管道。

管道文件一旦读出,就从管道中删除,因此它具备不可再现性。

相关文章
相关标签/搜索