目录
原理
创建过程
特性
代码练习
客户端与服务端交互
小知识
原理
原理:两个进程各自的struct file 指向相同的inode和文件缓冲区(这里的inode和文件缓冲区也应用了引用计数)。
命名管道创建的是磁盘上的一种不刷新数据到缓冲区的常规文件,也就是管道文件,以p作为开头的。
创建过程
mkfifo 创建管道文件
1.pathname是文件名(可加路径,在指定路径下创建),mode是权限。
2.成功返回0,失败返回-1,然后
errno
变量会被设置为相应的错误码,以指示具体的错误原因。unlink 删除文件
1.它是rm的底层系统调用。
以上两个命令都可以在命令行中使用。
在命令后直接加选项和文件名即可。
特性
和匿名管道的四种情况相同
1.写端不关,写端不写 管道里没有数据,读端会被阻塞(造就同步机制)
2.读端不关,读端不读 写满了(64kb,65536字节)就不会再写了
3.读端不关,写端先关 读端返回值会为0,表示读到文件结尾
4.写端不关,读端先关 OS会自动杀掉写进程,通过发送13号信号
主要用来解决无血缘关系的进程间的文件级进程通信
代码练习
客户端与服务端交互
main.hpp
#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
using namespace std;
const string fifoname = "fifo";
mode_t mode = 0777;
#define ERR_EXIT(s)\
do{\
perror(s);\
exit(EXIT_FAILURE);\
}while(0)
client.cpp
#include "main.hpp"
int main()
{
int fifofd = open(fifoname.c_str(),O_WRONLY);
if(fifofd<0)
{
ERR_EXIT("open");
}
string tmp;
while(1)
{
cout<<"请写入:";
cin>>tmp;
ssize_t writeret = write(fifofd,tmp.c_str(),tmp.size());
if(writeret<0)
{
ERR_EXIT("write");
}
cout<<"写入中:please wait!"<<endl;
tmp.clear();
sleep(0.2);
}
close(fifofd);
return 0;
}
server.cpp
#include "main.hpp"
int main()
{
umask(0);
int fiforet = mkfifo(fifoname.c_str(),mode);
if(fiforet<0)
{
ERR_EXIT("mkfifo");
}
int fifofd = open(fifoname.c_str(),O_RDONLY);
if(fifofd<0)
{
ERR_EXIT("open");
}
char buff[1024] = {'\0'};
while(1)
{
cout<<"读取中,please wait!"<<endl;
ssize_t readret = read(fifofd,buff,sizeof(buff)-1);
if(readret<0)
{
ERR_EXIT("read");
}
else if(readret==0)
{
cout<<"关闭\n";
exit(0);
}
buff[readret] = '\0';
cout<<buff<<endl;
sleep(0.2);
}
close(fifofd);
unlink(fifoname.c_str());
return 0;
}
Makefile
.PHONY:all
all:server client
server:server.cpp
g++ -o $@ $^ -std=c++11
client:client.cpp
g++ -o $@ $^ -std=c++11
.PHONY:clean
clean:
rm -rf client server
unlink fifo
小知识
1.删除数据时一般不是将属性和数据清空,而是将空间“释放”,将属性和数据标记为无效。
2..类型用来表明对象的大小,因为取地址时取到的都是首地址,加上对象大小才得到整个对象空间。