1.进程池补充
父进程创建多个子进程时,会有继承特性,也就是说文件描述符表也会继承,那么管道文件创建时,读端和写端也会继承,如果在创建一个子进程,那么这个子进程就会继承父进程的文件描述符表,也还会把上一个进程的读端或者写端继承,这样就会出现问题,列如遇到写端关闭,读端也会关闭,但是因为其它子进程也有指向这个管道文件作为写端,那么就会阻塞等待而不是关闭,所以要把子进程的多余的写端关闭掉。
方法一:关闭文件时,倒过来关闭,最后一个创建的子进程把把多个读端或者写端关闭,越往前关闭的次数就会减少。
方法二:
在创建子进程时,就执行关闭写端或者读端,虽然父进程和子进程同时进行,且父进程子在vector里插入了新的管道文件,但是并不会影响,因为有写时拷贝,也就是说第一个子进程的vector里面是空的,但父进程vector是有元素的,第二个子进程就会继承,能看到一个元素,但创建第二个子进程时父进程也插入了第二个元素,但是第二个子进程只能看到第一个元素且关闭第一个元素,就可以把管道文件多余的读端或者写端关闭掉了。
2.命名管道的介绍
管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信
如果想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,FIFO被命名为命名管道。
命名管道是一种特殊类型文件
创建一个命名管道
mkfifo filename
程序创建命名管道
int mkfifo(const char* fifename,mode_t mode);
创建命名管道:
int main(int argc,char* argv[])
{
mkfifo("p2",0644);
return 0;
}
匿名管道与命名管道的区别
匿名管道由pipe函数创建并打开
命名管道由mkfifo函数创建,打开用open
FIFO与pipe之间唯一区别在它们创建打开的方式不同,一但这些工作完成之后,它们具有相同的意义。
这里俩个进程虽然没有父子关系,但是打开的是同一个路径,路径有唯一性,俩个进程打开同一个文件,不会在创建一个inode和文件缓冲区,浪费资源,所以就有了同一块资源,满足了管道文件的前提。
3.简单实现命名管道
server.cc文件
创建并打开命名管道,然后读取信息,要想运行这个代码,先打开管道文件。
#include <iostream>
#include <cstdio>
#include <string>
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "comm.hpp"int main()
{umask(0);int n=mkfifo(FIFO_FILE,0666);if(n!=0&&errno!=EEXIST){std::cout<<"mkdri fifo error"<<std::endl;return 1;}int fd=open(FIFO_FILE,O_RDONLY);if(fd<0){std::cout<<"open fifo error"<<std::endl;return 2;}char buffer[1024];while(true){int n=read(fd,buffer,sizeof(buffer)-1);if(n>0){buffer[n]=0;std::cout<<"client say#"<<buffer<<std::endl;}}close(fd);return 0;
}
client文件
打开并往创建好的命名管道写入信息。
#include <iostream>
#include <cstdio>
#include <string>
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "comm.hpp"int main()
{int fd=open(FIFO_FILE,O_WRONLY);if(fd<0){std::cout<<"open fifo error"<<std::endl;return 2;}while(true){std::cout<<"Please Enter#";std::string message;std::cin>>message;int n=write(fd,message.c_str(),message.size());if(n>0){}}close(fd);return 0;
}
coomm.hpp文件
#pragma once#define FIFO_FILE "fifo"
实现结果
在client写入会在server看到。