福州做网站的公,兰州网络推广推广不了,静态网站托管平台,asp.net做网站源代码目录
1.原理
2.创建命名管道
3.使用命名通道实现简单的通信
4.使用创建的命名管道 1.原理 匿名管道没有名称#xff0c;它们是通过句柄在父进程和子进程之间传递的。这意味着匿名管道只能用于具有父子关系的进程之间。 但如果程序之间没关系#xff0c;那么这时候就要用…目录
1.原理
2.创建命名管道
3.使用命名通道实现简单的通信
4.使用创建的命名管道 1.原理 匿名管道没有名称它们是通过句柄在父进程和子进程之间传递的。这意味着匿名管道只能用于具有父子关系的进程之间。 但如果程序之间没关系那么这时候就要用到有名管道了有名管道通过一个名称通常是一个文件系统中的路径来标识。这使得任何进程都可以通过该名称来访问管道而不必是创建管道的进程的子进程。有名管道支持不同进程间的通信甚至支持跨计算机网络的通信。有名管道的生命周期由创建它的进程控制但即使创建它的进程终止只要还有进程连接着管道管道就会继续存在。 命名管道在操作系统中表现为一种特殊类型的文件它存在于系统的命名空间中可以像打开文件那样被打开和读写。一旦创建命名管道就可以在不同的进程中被打开多次允许单向或双向的数据流传输。 2.创建命名管道 创建命名管道直接使用mkfifo命令就可以了 eg 创建一个命名管道 一号机上的while循环持续地将字符串hello boy写入到命名管道myfifo中每次写入后暂停一秒。二号机上的cat命令则从myfifo中读取数据并将其输出到标准输出。看一看效果我们发现在一号机写到myfifo中的数据会被同步到二号机中的myfifo 两个不相关的进程一号机和二号机上的进程之间建立通信。这两个进程不需要有任何父子关系或其他特殊关系只需要知道命名管道的文件路径即可。 myfifo的文件大小始终都没有变因为并没有被刷新到磁盘中。 3.使用命名通道实现简单的通信 提供一个关闭命名管道的函数unlink 提供一个namepipe的类它封装了命名管道的创建、打开、读写和删除的逻辑。以下是代码namedPipe.hpp #pragma once#include iostream
#include cstdio
#include cerrno
#include string
#include unistd.h
#include sys/types.h
#include sys/stat.h
#include fcntl.hconst std::string comm_path ./myfifo;
#define DefaultFd -1
#define Creater 1
#define User 2
#define Read O_RDONLY
#define Write O_WRONLY
#define BaseSize 4096class NamePiped
{
private:bool OpenNamedPipe(int mode){_fd open(_fifo_path.c_str(), mode);if (_fd 0)return false;return true;}public:NamePiped(const std::string path, int who): _fifo_path(path), _id(who), _fd(DefaultFd){if (_id Creater){int res mkfifo(_fifo_path.c_str(), 0666);if (res ! 0){perror(mkfifo);}std::cout creater create named pipe std::endl;}}bool OpenForRead(){return OpenNamedPipe(Read);}bool OpenForWrite(){return OpenNamedPipe(Write);}int ReadNamedPipe(std::string *out){char buffer[BaseSize];int n read(_fd, buffer, sizeof(buffer));if(n 0){buffer[n] 0;*out buffer;}return n;}int WriteNamedPipe(const std::string in){return write(_fd, in.c_str(), in.size());}~NamePiped(){if (_id Creater){int res unlink(_fifo_path.c_str());if (res ! 0){perror(unlink);}std::cout creater free named pipe std::endl;}if(_fd ! DefaultFd) close(_fd);}private:const std::string _fifo_path;int _id;int _fd;
}; 成员变量 _fifo_path存储命名管道的路径。_id标识该对象是命名管道的创建者Creater还是用户User。_fd文件描述符用于与命名管道进行通信。初始化为DefaultFd定义为-1。构造函数 接收命名管道的路径和创建者/用户标识。如果_id为Creater则调用mkfifo函数在指定路径下创建命名管道。如果创建失败会打印错误信息。OpenForRead和OpenForWrite方法 这两个方法分别用于打开命名管道进行读取和写入操作。内部调用OpenNamedPipe方法传入相应的读取或写入模式O_RDONLY或O_WRONLY。OpenNamedPipe方法使用open系统调用来打开命名管道并保存文件描述符到_fd成员变量中。ReadNamedPipe和WriteNamedPipe方法 ReadNamedPipe方法从命名管道中读取数据到提供的字符串指针中。WriteNamedPipe方法将提供的字符串写入命名管道。这两个方法都使用read和write系统调用来执行实际的读写操作。析构函数 在对象销毁时析构函数会被调用。如果_id为Creater则调用unlink函数来删除命名管道。这确保了命名管道在不再需要时从文件系统中被移除。无论_id的值如何都会检查_fd是否不是DefaultFd即文件描述符是否已打开如果是则调用close函数来关闭文件描述符。 接下来创建一个客户端向命名管道写入client.cc #include namedPipe.hpp// write
int main()
{NamePiped fifo(comm_path, User);if (fifo.OpenForWrite()){std::cout client open namd pipe done std::endl;while (true){std::cout Please Enter ;std::string message;std::getline(std::cin, message);fifo.WriteNamedPipe(message);}}return 0;
} 循环的写入信息。 创建一个客户端用来读取命名管道的信息server.cc #include namedPipe.hppint main()
{NamePiped fifo(comm_path, Creater);// 对于读端而言,如果我们打开文件但是写还没来我会阻塞在open调用中直到对方打开// 进程同步if (fifo.OpenForRead()){std::cout server open named pipe done std::endl;sleep(3);while (true){std::string message;int n fifo.ReadNamedPipe(message);if (n 0){std::cout Client Say message std::endl;}else if(n 0){std::cout Client quit, Server Too! std::endl;break;}else{std::cout fifo.ReadNamedPipe Error std::endl;break;}}}return 0;
} 如果ReadNamedPipe返回的值n大于0表示成功读取了n个字符到message中。 程序将输出Client Say 和读取到的消息内容。如果n等于0通常表示客户端已经关闭了连接或者发送了一个EOF文件结束符。 程序将输出Client quit, Server Too!并退出循环然后退出程序。如果n小于0表示读取过程中发生了错误。 程序将输出fifo.ReadNamedPipe Error并退出循环然后退出程序。 4.使用创建的命名管道 我们先运行了读端程序但是并没有提示我们的读端创建成功对于读端而言,如果我们打开文件但是写还没来我会阻塞在open调用中直到对方打开 打开写端读端才成功打开。 这就实现进程间的通信了