管道和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.对于设置了阻塞标志的写操做:
2.对于没有设置阻塞标志的写操做:
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节点对应关系的管道是有名管道,没有记载的是无名管道。
管道文件一旦读出,就从管道中删除,因此它具备不可再现性。