一个管道文件的通信半双工的,且不能用lseek()
函数操作,其他操作与普通文件一样。
匿名pipe
#include <unistd.h>
int pipe(int pipefd[2]);
- 功能:创建无名管道。
- 参数:
pipefd
: 为int
型数组的首地址,其存放了管道的文件描述符pipefd[0]
、pipefd[1]
。当一个管道建立时,它会创建两个文件描述符fd[0]
和fd[1]
。其中fd[0]
固定用于读管道,而fd[1]
固定用于写管道。一般文件 I/O的函数都可以用来操作管道(lseek()
除外)。 - 返回值:
成功:0
失败:-1
命名pipe
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
- 功能:
命名管道的创建。 - 参数:
pathname : 普通的路径名,也就是创建后 FIFO 的名字。
mode : 文件的权限,与打开普通文件的 open() 函数中的 mode 参数相同。(0644) - 返回值:
成功:0 状态码
失败:如果文件已经存在,则会出错且返回 -1。 - 注意:
管道默认大小65536字节
管道读写四种情况
- 写端文件描述符全部关闭 (管道写端引用计数为0) ,管道没数据,read会返回0,就像读到文件末尾一样,不设置
errno
。 - 写端没关闭,管道没数据,则
read
阻塞。若读端设置非阻塞,read
返回-1,errno
设置为EAGAIN - 读端都关闭,写端进程会收到信号
SIGPIPE
,进程异常终止。 - 读端没关闭,管道写满,写端阻塞。若写端设置非阻塞,
write
返回-1,errno
设置为EAGAIN
内存映射:mmap()函数
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
- 功能:
一个文件或者其它对象映射进内存 - 参数:
addr
: 文件映射到内存哪个位置, 通常设为NULL, 由系统指定
length
:映射到内存的文件长度
prot
: 映射区的保护方式, 最常用的 :
a) 读:PROT_READ
b) 写:PROT_WRITE
c) 读写:PROT_READ | PROT_WRITE
flags
: 映射区的特性, 可以是
a) MAP_SHARED(直写法): 写入映射区的数据会复制回文件, 且允许其他映射该文件的进程共享。
b) MAP_PRIVATE : 对映射区的写入操作会产生一个映射区的复制(copy - on - write), 对此区域所做的修改不会写回原文件。
fd
:由open返回的文件描述符, 代表要映射的文件。
offset
:以文件开始处的偏移量, 必须是4k(内存页面大小)的整数倍, 通常为0, 表示从文件头开始映射 - 返回值:
成功:返回创建的映射区首地址
失败:MAP_FAILED宏
#include <sys/mman.h>
int munmap(void *addr, size_t length);
- 功能:
释放内存映射区 - 参数:
addr:使用mmap函数创建的映射区的首地址
length:映射区的大小 - 返回值:
成功:0
失败:-1
注意事项
- 创建映射区的过程中,隐含着一次对映射文件的读操作。
- 当MAP_SHARED时,要求:映射区的权限应 <=文件打开的权限(出于对映射区的保护)。而MAP_PRIVATE则无所谓,因为mmap中的权限是对内存的限制。
- 映射区的释放与文件关闭无关。只要映射建立成功,文件可以立即关闭。
- 特别注意,当映射文件大小为0时,不能创建映射区。所以,用于映射的文件必须要有实际大小。mmap使用时常常会出现总线错误,通常是由于共享文件存储空间大小引起的。
- munmap传入的地址一定是mmap的返回地址。坚决杜绝指针++操作。
- mmap创建映射区出错概率非常高,一定要检查返回值,确保映射区建立成功再进行后续操作。