【读书笔记】管道和FIFO
管道
提供一个单路(单向)数据流,可以为两个不同进程提供进程间的通信手段
#include <unistd.h> int pipe(int fd[2]);
返回两个文件描述符,fd[0](读) 和 fd[1](写)
管道间的通信通常是使用 read 和 write 函数完成的
管道的典型用法:
首先,由父进程创建一个管道,然后调用fork派生一个自身的副本
接着,父进程关闭管道的读端,子进程关闭管道的写段
这样就在父子进程间提供了一个单向数据流
双管道:
当需要一个双向数据流的时候,我们必须创建两个管道,每个方向一个
int pipe1[2], pipe2[2]; pid_t childpid; Pipe(pipe1); Pipe(pipe2); if( (childpid = Fork()) ==0 ) { Close(pipe1[1]); Close(pipe2[0]); /*代码*/ exit(0); } Close(pipe1[0]); Close(pipe2[1]); /*代码*/ Waitpid(childpid, NULL, 0); exit(0);
FIFO
指代先进先出(first in, first out),是一个单向数据流
不同于管道的是,每个FIFO有一个路径名与之关联,从而允许无亲缘关系的进程访问同一个FIFO,因而也称"有名管道"。(我更愿意把它看做一个文件)
#include <sys/types.h> #include <sys/stat.h> int mkfifo(const char* pathname, mode_t mode);
pathname是一个路径名,也是该FIFO的名字
mode指文件的权限位
常值 | 说明 |
S_IRUSR S_IWUSR |
用户(属主)读 用户(属主)写 |
S_IRGRP S_IWGRP |
(属)组成员读 (属)组成员写 |
S_IROTH S_IWOTH |
其他成员读 其他成员写 |
常值 FIFO_MODE 在 unpipc.h 中定义:
#define FIFE_MODE ( S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )
与管道不同的是:
创建并打开一个管道只需用 pipe,创建并打开一个FIFO则需要调用 mkfifo 后再调用 open
管道在所有进程都关闭它后自动消失,FIFO的名字则只有通过调用 unlink 才从文件系统中删除
#define FIFO1 "/tmp/fifo.1" #define FIFO2 "/tmp/fifo.2" int readfd, writefd; pid_t childpid; if( (mkfifo(FIFO1, FILE_MODE) < 0) && (errno != EEXIST) ) err_sys("can't create %s", FIFO1); if( (mkfifo(FIFO2, FILE_MODE) < 0) && (errno != EEXIST) ) { unlink(FIFO1); err_sys("can't create %s", FIFO2); } if( (childpid = Fork()) ==0 ) { readfd = Open(FIFO1, O_RDONLY, 0); writefd = Open(FIFO2, O_WRONLY, 0); /*代码*/ //为什么这里不需要Close(readfd) Close(writefd) exit(0); } writefd = Open(FIFO1, O_WRONLY, 0); readfd = Open(FIFO2, O_RDONLY, 0); /*代码*/ Waitpid(childpid, NULL, 0); Close(readfd); Close(writefd); Unlink(FIFO1); Unlink(FIFO2); exit(0);