linux 有名管道
有名管道:
匿名管道,由于没有名字,只能用于亲缘关系的进程间通信。为了克服这个缺点,提出了有名管道(FIFO),也叫命名管道、FIFO文件
有名管道(FIFO)不同于匿名管道之处在于它提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中,并且其打开方式与打开一个普通文件是一样的,这样即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过 FIFO 相互通信,因此,通过 FIFO 不相关的进程也能够交换数据
一旦打开了 FIFO ,就能在它上面使用与操作匿名管道和其他文件的系统调用一样的 I/O 系统调用(如 read() write() 和 close() 。与管道一样, FIFO 也有一个写入端和读取端,并且从管道中读取数据的顺序与写入的顺序是一样的。 FIFO 的名称也由此而来: 先入先出
有名管道(FIFO)和匿名管道(pipe)有一些特点是相同的,不一样的地方在于:
1.FIFO 在文件系统中作为一个特殊文件存在,但 FIFO 中的内容却存放在内存中。
2.当使用 FIFO 的进程退出后, FIFO 文件将继续保存在文件系统中以便以后使用。
3.FIFO 有名字,不相关的进程可以通过打开有名管道进行通信。
通过命令创建有名管道
mkfifo 名字
通过函数创建有名管道
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo (const char* pathname, mode_t mode);
一旦使用 mkfifo 创建了一个 FIFO ,就可以使用 open 打开它, 常见的文件 I/O 函数都可以用于 fifo 如: close、read、write、unlink 等。
FIFO 严格遵循先进先出 (First in First out),对管道及 FIFO 的读总是从开始处返回数据,对他们的写则把数据添加到末尾。他们不支持诸如 lseek() 等文件定位操作。
prw:p表示管道
mkfifo()
1 /* 2 man 3 fifo 3 创建fifo文件 4 1.通过命令: mkfifo 名字 5 2.通过函数: int mkfifo(const char* pathname, mode_t mode); 6 7 #include <sys/types.h> 8 #include <sys/stat.h> 9 int mkfifo(const char* pathname, mode_t mode); 10 参数: 11 - pathname:管道名称的路径(绝对路径/相对路径(当前)) 12 - mode: 文件的权限 和 open的 mode是一样的 13 是一个八进制的数 14 返回值: 15 成功:返回 0 16 失败:返回 -1 并设置错误号 17 */ 18 #include <stdio.h> 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 #include <stdlib.h> 22 23 int main() 24 { 25 int ret = mkfifo("fifo1",0664); 26 if(ret == -1) 27 { 28 perror("mkfifo"); 29 exit(0); 30 } 31 return 0; 32 }
案例: write.c read.c
写入:
1 //向管道中写数据 2 /* 3 有名管道的注意事项: 4 1.一个为只读而打开一个管道的进程会阻塞,直到另外一个进程为只写打开管道 5 2.一个为只写而打开一个管道的进程会阻塞,直到另外一个进程为只读打开管道 6 读管道: 7 管道中有数据,read返回实际督导的字节数 8 管道中无数据: 9 管道写端被全部关闭, read返回0 (相当于读到文件末尾) 10 写端没有全部被关闭, read阻塞等待 11 写管道: 12 管道读端被全部关闭,进程异常终止(收到一个 SIGPIPE信号) 13 管道读端没有全部关闭: 14 管道已经满了,write会阻塞 15 管道没有满,write将数据写入,并返回实际写入的字节数 16 */ 17 #include <stdio.h> 18 #include <sys/types.h> 19 #include <sys/stat.h> 20 #include <stdlib.h> 21 #include <unistd.h> 22 #include <fcntl.h> 23 #include <string.h> 24 int main() 25 { 26 //1.判断文件是否存在 27 int ret = access("test",F_OK);//判断文件是否存在 28 if(ret == -1) 29 { 30 //2.创建管道文件 31 printf("管道不存在,创建管道\n"); 32 ret = mkfifo("test",0664); 33 if(ret == -1) 34 { 35 perror("mkfifo"); 36 exit(0); 37 } 38 } 39 //3.打开管道 以 只写 的方式打开管道(只读错误 可读写容易出错) 40 int fd = open("test",O_WRONLY); 41 if(fd == -1) 42 { 43 perror("open"); 44 exit(0); 45 } 46 //写数据 47 for(int i = 0; i< 100;i++) 48 { 49 char buf[1024]; 50 sprintf(buf,"hello,%d\n",i); 51 printf("write data : %s\n",buf); 52 write(fd,buf,strlen(buf)); 53 sleep(1); 54 } 55 close(fd); 56 return 0; 57 }
读取数据:
1 //从管道中读数据 2 #include <stdio.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <stdlib.h> 6 #include <unistd.h> 7 #include <fcntl.h> 8 #include <string.h> 9 int main() 10 { 11 //1.打开管道文件 12 int fd = open("test",O_RDONLY);//只读 13 if(fd == -1) 14 { 15 perror("open"); 16 exit(0); 17 } 18 //读取数据 19 while(1) 20 { 21 char buf[1024] = {0}; 22 int len = read(fd,buf,sizeof(buf)); 23 if(len == 0) 24 { 25 printf("写端断开连接了...\n"); 26 break; 27 } 28 printf("recv buf: %s\n",buf); 29 } 30 close(fd); 31 return 0; 32 }
运行时,需要两个终端分别运行 读取可执行程序和写入可执行程序,有一端关闭 则管道阻塞。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)