1、基本概念
命名管道是一种特殊的文件类型,其存在于磁盘上,但是大小永远是0。
不同于匿名管道的是:
- 可在同一台计算机的不同进程之间或在跨越网络的不同计算机的不同进程之间实现通信
- 支持可靠的、单向或双向的数据通信
- 命名管道只是让两个无关的进程之间建立起联系,一旦关系建立起来,与命名管道的文件不再有关
- 命名管道FIFO(first input first output)总是遵循先进先出的原则,即第一个进来的数据会第一个被读走
- 命名管道可以一个读端,多个写端;也可以多个写端,一个读端
服务器建立命名管道时给它指定一个名字,任何进程都可以通过该名字打开管道的另一端,根据给定的权限和服务器进程通信。
2、创建
1)命令行
通过执行以下命令即可创建命名管道:
mkfifo fifo_file_name
fifo_file_name 是要创建的命名管道文件名称。
如上图所示,可以看到命名管道fifo1,其大小为0
2)函数
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char* filename, mode_t mode)
返回:
成功:0
失败:-1
参数:
filename:创建的命名管道名称
mode:命名管道的读写模式,与open函数中的mode相同
O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
这三个常量,必须指定一个且只能指定一个
命名管道创建完成后就可以使用,其使用方法与管道一样,区别在于:命名管道使用之前需要使用open()打开。
这是因为:命名管道是设备文件,它是存储在硬盘上的,而管道是存在内存中的特殊文件。
但是需要注意的是
- 命名管道调用open()打开有可能会阻塞,但是如果以读写方式(O_RDWR)打开则一定不会阻塞;
- 以只读(O_RDONLY)方式打开时,调用open()的函数会被阻塞直到有数据可读;
- 如果以只写方式(O_WRONLY)打开时同样也会被阻塞,直到有以读方式打开该管道
3、示例
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<unistd.h>
int main()
{
int fd;
int len;
char buf[1024];
if(mkfifo("fifo1", 0666) < 0 && errno!=EEXIST)
perror("Create FIFO Failed");
if((fd = open("fifo1", O_RDONLY)) < 0)
{
perror("Open FIFO Failed");
exit(1);
}
while((len = read(fd, buf, 1024)) > 0)
{
printf("Read message: %s", buf);
}
close(fd);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<time.h>
#include<unistd.h>
int main()
{
int fd;
int n, i;
char buf[1024];
time_t tp;
printf("I am %d process.\n", getpid());
if((fd = open("fifo1", O_WRONLY)) < 0)
{
perror("Open FIFO Failed");
exit(1);
}
for(i=0; i<20; ++i)
{
time(&tp);
n=sprintf(buf,"Process %d's time is %s",getpid(),ctime(&tp));
printf("Send message: %s", buf);
if(write(fd, buf, n+1) < 0)
{
perror("Write FIFO Failed");
close(fd);
exit(1);
}
sleep(1);
}
close(fd);
return 0;
}
程序运行结果:
上述例子可以扩展成 客户进程—服务器进程 通信的实例,write_fifo的作用类似于客户端,可以打开多个客户端向一个服务器发送请求信息,read_fifo类似于服务器,它适时监控着FIFO的读端,当有数据时,读出并进行处理:
参考:
1.《UNIX环境高级编程》
2.《UNIX网络编程》
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)