1. 何为管道
我的理解就是管道是一个类似于队列的缓冲区,数据先进先出。一个进程发送数据,一个进程接受数据
2. 管道分类
2.1 无名管道
无名管道适用于有亲缘关系的进程,如父子进程。因为子进程的内存空间是直接拷贝的父进程的内存空间,所以父进程创建管道后得到的文件描述符也被拷贝了一份,而其他没有亲缘关系的进程则无法的到该文件描述符(没有文件名与之对应)。
创建无名管道的接口:
#include <unistd.h> int pipe(int pipefd[2])
例子:
#include<stdio.h> #include<unistd.h> /* 父进程生成数据, 子进程取出数据并打印 */ int main(void) { int fd[2]; int ret = 0; int data = 0; ret = pipe(fd); if (ret < 0) { perror("pipe error"); return -1; } ret = fork(); if (ret == 0) { // 子进程 while(1) { ret = read(fd[0], &data, sizeof(data)); if (ret < 0) { printf("read error"); return -1; } printf("data: %d\n", data); } } else { // 父进程 while(1) { data += 1; write(fd[1], &data, sizeof(data)); sleep(1); // 一秒钟产生一个数据 } } close(fd[0]); close(fd[1]); return 0; }
2.2 有名管道
有名管道在没有亲缘关系的进程之间也能够使用,顾名思义,有名管道就是给管道命一个名字,也就是创建了一个文件,该文件称为管道文件。与普通文件不同的是,管道文件的数据是先进先出的,每个数据只能取一次,取了就没了,并且不能够使用lseek函数改变偏移量。
需要注意:
- 管道建立好后,在打开管道文件的时候,管道的两端读写必须分别打开,有任何一方未打开,则在调用open的时候就阻塞。比如,一个进程以写的方式打开管道文件,但没有任何进程以读的方式打开,那么就会阻塞在open函数,直到某个进程取以读的方式打开管道文件
- 管道大小是有最大值的,可以使用宏PIPE_BUF(limits.h)查看。
- 管道默认是阻塞的,在没有数据可读的时候,读操作会阻塞。
例子:
read_pipe.c
#include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> #include<string.h> #define FIFO_NAME "./fifo_test" /* 读取管道内的数据并打印, 每两秒读取一次 */ int main(void) { int ret = 0; int fifo_fd; int data = 0; // 打开管道 fifo_fd = open(FIFO_NAME, O_RDONLY); if (fifo_fd < 0) { perror("open fifo error"); return -1; } printf("[read] open ok\n"); while(1) { // 读取数据 ret = read(fifo_fd, &data, sizeof(data)); if (ret < 0) { perror("read error"); return -1; } printf("data: %d\n", data); sleep(2); } close(fifo_fd); return 0; }
write_pipe.c
#include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> #include<string.h> #define FIFO_NAME "./fifo_test" /* 创建管道, 向管道内写入数据,每一秒写入一次 */ int main(void) { int ret = 0; int fifo_fd; //char *data = "hello World"; int data = 0; // 没有就创建 if (access(FIFO_NAME, F_OK) == -1) { ret = mkfifo(FIFO_NAME, 0777); if (ret < 0) { perror("mkfifo error\n"); return -1; } } // 打开管道 fifo_fd = open(FIFO_NAME, O_WRONLY); if (fifo_fd < 0) { perror("open fifo error"); return -1; } printf("[write] open ok\n"); while(1) { // 写入数据 data += 1; write(fifo_fd, &data, sizeof(data)); sleep(1); } close(fifo_fd); return 0; }