https://blog.csdn.net/derkampf/article/details/60762854 一.介绍 在前面的无名管道博文中,我们看到了创建两个管道可以实现进程间的全双工通信,那么同样也可以创建两个FIFO(有名管道)来实现不同进程间的全双工通信。 1.为什么引入有名管道? 我们通常所说的管道为无名管道或者匿名管道,管道没有名字,因此,只能在有亲缘关系的进程间(父子进程)实现通信,有名管道的出现突破了该限制,它是一个设备文件,它提供一个路径名与FIFO关联,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问这个路径也可以实现通信。 2.创建有名管道 mknod/mkfifo shell中的创建方式 mknod 名字 pipemkfifo 名字
函数创建方式 (1)int mknod(const char *path, mode_t mode, dev_t dev);参数mode的选择Name DescriptionS_IFIFO FIFO-specialS_IFCHR Character-special (non-portable)S_IFDIR Directory (non-portable)S_IFBLK Block-special (non-portable)S_IFREG Regular (non-portable)If mode is not S_IFIFO or dev is not 0, the behavior of mknod() is unspecified.举例:mknod("/tmp/fifo", S_IFIFO | 0666, 0)(2)int mkfifo(const char *pathname, mode_t mode);mkfifo() makes a FIFO special file with name pathname. mode specifies the FIFO's permissions.所以只需要填写管道的权限就型举例mkfifo("/tmp/fifo", 0666);
3.使用有名管道 与无名管道的使用方法基本相同,只是需要先调用open函数将其打开。因为有名管道终究是在硬盘上的文件,而无名管道只是存在内存上的特殊文件。 注意open()的阻塞情况 1.以只写方式打开,阻塞直到有读方式打开管道 open(“/tmp/fifo”, O_WRONLY); 2.以只读方式打开,阻塞直到有写方式打开管道 open(“/tmp/fifo”, O_RDONLY); 3.同时读写方式打开,一定不阻塞。 open(“/tmp/fifo”, O_RDWR); 二.代码演示 1.server.c #include"utili.h"int main(){ char sendbuf[MAX_MSG_LEN]; char recvbuf[MAX_MSG_LEN]; int res = mkfifo(FIFO_WRITE, 0666); if(res == -1) { perror("mkfifo WRITE"); exit(EXIT_FAILURE); } //以只写方式打开,会阻塞到有读方式打开管道 int wfd = open(FIFO_WRITE, O_WRONLY); if(wfd == -1) { perror("open WRITE"); exit(EXIT_FAILURE); } //以只读方式打开,会阻塞到有写方式打开管道 int rfd = open(FIFO_READ, O_RDONLY); if(rfd == -1) { perror("open READ"); exit(EXIT_FAILURE); } while(1) { printf("Ser:>"); scanf("%s", sendbuf); if(strcmp(sendbuf, "quit") == 0) { close(wfd); unlink(FIFO_WRITE); close(rfd); exit(EXIT_SUCCESS); } write(wfd, sendbuf, strlen(sendbuf)+1); read(rfd, recvbuf, MAX_MSG_LEN); printf("Cli:>%s\n", recvbuf); }}
2.client.c #include"utili.h"int main(){ char recvbuf[MAX_MSG_LEN]; char sendbuf[MAX_MSG_LEN]; int wfd, rfd; int res = mkfifo(FIFO_READ, 0666); if(res == -1) { perror("mkfifo READ"); exit(EXIT_FAILURE); } //server的写对应client读 rfd = open(FIFO_WRITE, O_RDONLY); if(rfd == -1) { perror("open READ"); exit(EXIT_FAILURE); } wfd = open(FIFO_READ, O_WRONLY); if(wfd == -1) { perror("open WRITE"); exit(EXIT_FAILURE); } while(1) { read(rfd, recvbuf, MAX_MSG_LEN); printf("Ser:>%s\n", recvbuf); printf("Cli:>"); scanf("%s", sendbuf); if(strcmp(sendbuf, "quit") == 0) { close(rfd); unlink(FIFO_READ); close(wfd); exit(EXIT_SUCCESS); } write(wfd, sendbuf, strlen(sendbuf)+1); }}
3.公共头文件 utili.h #ifndef _UTILI_H_#define _UTILI_H_#include<stdio.h>#include<unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include<stdlib.h>#include<string.h>#define FIFO_READ "readfifo"#define FIFO_WRITE "writefifo"#define MAX_MSG_LEN 256#endif
|