有名管道FIFO
无名管道只能用于具有亲缘关系的进程之间,这大大的限制了管道的使用,有名管道的出现突破了这种限制,它可以使互不相关的两个进程实现彼此通信。该管道可以通过路径名来指出,并且在文件系统中是可见的。在建立管道之后,两个进程就可以把它当作普通文件一样进行读写操作。
值得注意的是,FIFO的读总是从开始处返回数据,写则是添加到末尾,不支持lseek()等文件定位操作
有名管道可以使用mkfifo()创建,该函数类似open(),可以指定管道的路径和打开模式
在创建管道成功以后,就可以使用open()、read()和write()这些函数了。与普通文件的开发设置一样,对于为读而打开的管道可以在open()中设置O_RDONLY,对于为写而打开的管道可在open()中设置O_WRONLY,不同的是阻塞问题。在管道的读写中会出现阻塞的可能,这里的非阻塞标志可以在open()中设定为O_NONBLOCK。下面分别对阻塞打开和非阻塞打开的读写进行分析:
对于读进程:
- 若该管道是阻塞打开,且当前FIFO中没有数据,则对读进程而言将一直阻塞到有数据写入
- 若该管道是非阻塞打开,则不论FIFO内是否有数据,读进程都会立即执行读操作。如果没有数据则立即返回0
对于写进程:
- 若该管道是阻塞打开,则写操作一直阻塞到数据可以写入
- 若该管道是非阻塞打开而不能写入全部数据,则部分写入或调用失败
mkfifo()
1 2 3
| #include <sys/types.h> #include <sys/state.h> int mkfifo (const char *filename, mode_t mode);
|
mode:
O_RDONLY : 读管道
O_WRONLY : 写管道
O_RDWR : 读写管道
O_NONBLOCK : 非阻塞
O_CREAT : 如果不存在则创建,并用第三个参数设置权限
O_EXCL : 如果使用O_CREAT时文件存在,返回错误消息
出错时的errno如下:
erron |
描述 |
EACCESS |
参数filename所指定的目录无可执行权限 |
EEXIST |
参数filename所指定的文件已存在 |
ENAMETOOLONG |
参数filename的路径名称太长 |
ENOENT |
参数filename包含的目录不存在 |
ENOSPC |
文件系统的剩余空间不足 |
ENOTDIR |
参数filename路径中的目录存在但却非真正的目录 |
EROFS |
参数filename指定文件存在于只读文件系统内 |
写管道:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <limits.h> #define MYFIFO "./myfifo" #define MAX_BUFFER_SIZE PIPE_BUF
int main(int argc, char *argv[]) { int fd; char buf[MAX_BUFFER_SIZE] = {0}; int nwrite;
if (argc <= 1) { printf ("Usage: ./fifo_write string\n"); exit(1); }
sscanf(argv[1], "%s", buf);
fd = open (MYFIFO, O_WRONLY); if (fd == -1) { printf ("Open fifo file error\n"); exit(1); }
if ((nwrite = write (fd, buf, MAX_BUFFER_SIZE)) > 0) { printf ("Write '%s' to FIFO\n", buf); }
close(fd); exit(0); }
|
读管道:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <limits.h> #define MYFIFO "./myfifo" #define MAX_BUFFER_SIZE PIPE_BUF
int main() { int fd; char buf[MAX_BUFFER_SIZE] = {0}; int nwrite;
if (access(MYFIFO, F_OK) == -1) { if ((mkfifo (MYFIFO, 0666) < 0) && (errno != EEXIST)) { printf ("Cannot creat fifo file\n"); exit(1); } }
fd = open (MYFIFO, O_RDONLY); if (fd == -1) { printf ("Open fifo file error\n"); exit(1); }
while (1) { memset(buf, 0, sizeof (buf)); if ((nwrite = read (fd, buf, MAX_BUFFER_SIZE)) > 0) { printf ("Read '%s' from FIFO\n", buf); } }
close(fd); exit(0); }
|