命名管道 FIFO (First In First Out)
命令行: mknod
mknod [-m mode] NAME TYPE [ MAJOR MINOR]
mknod name b | c major minor //块设备,字符设备文件
mknod name p //管道文件
mknod name s //信号量
mknod name m //共享内存
命令行:mkfifo (first input first output)
mkfifo [-m mode] name //创建命名管道
mode 即文件访问权限, 如 mkfifo –m 644 k2
命令行测试管道通信
mknod pnod p
tty1: cat pnod
tty2: echo Message > pnod
注:管道无内容时,读阻塞;管道写入内容,没有读出之前,写阻塞
管道创建函数
<sys/types.h>
<sys/stat.h>
int mkfifo (const char *pathname, mode_t mode)
和命令行一样:
向管道中写入数据后,没有被读出,则阻塞
从管道中读出数据时,如果没数据,则阻塞
思路:
命名管道文件使用,和读写文件操作类似, 步骤如下:
1: 创建管道文件 mkfifo()
2: 打开管道
进程a:只读打开管道文件 open 或 fopen
进程b:只写打开管道文件
3: 读写管道
进程a:读管道 read, fread
进程b:写管道 write, fwrite
4: 关闭管道 close, fclose
管道模型
1-1 模型
两个进程间双向通信
需要两个管道
n-1 模型
非交互式服务:多个客户端向服务端发送消息
1 个管道,客户端向服务端单向通信
n-1-n 模型
交互式服务:
1:多个客户端 共用管道向服务端发送消息
2:服务端通过专用管道向客户端发送消息
例子:两个进程间通信,要启动两次程序,只有单向通信。
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
void testPipe()
{
char cMode;
fprintf(stderr,"select the mode:w/r:");
cMode=getchar();
char szFile[128]={"pnod"};
int fd;
int len;
char szBuf[1024];
struct stat info;
//不存在名为pnod的文件
if(!stat(szFile,&info))
{
//创建名为pnod的管道文件
if(!mkfifo(szFile,0664))
{
perror("fail mkfifo!");
return ;
}
}
//存在该文件,但不是管道文件
else if(!S_ISFIFO(info.st_mode))
{
perror("this is not a pipe file");
return ;
}
//接受方
if(cMode==‘r‘)
{
//打开文件,返回文件描述符
fd=open(szFile,O_RDONLY);
if(fd<0)
{
perror("fail open!");
return ;
}
while(1)
{
memset(szBuf,0,sizeof(szBuf));
len=read(fd,szBuf,sizeof(szBuf));
if(len<0)
{
perror("fail to read file!");
return ;
}
else if(len==0)
{
printf("FIFO closed!\n");
return ;
}
else
{
printf("receive:%s",szBuf);
}
}
close(fd);
}
//发送方
else if(cMode==‘w‘)
{
fd=open(szFile,O_WRONLY);
if(fd<0)
{
perror("fail open!");
return ;
}
while(1)
{
fprintf(stderr,"Send:");
memset(szBuf,0,sizeof(szBuf));
read(0,szBuf,sizeof(szBuf));
write(fd,szBuf,strlen(szBuf));
}
close(fd);
}
else
{
return ;
}
}
int main()
{
testPipe();
return 0;
}
原文地址:https://www.cnblogs.com/gd-luojialin/p/9216013.html