文章目录
一、管道的应用实例-父进程唤醒子进程,子进程执行某种任务
二、命名管道
1.创建一个命名管道
2.匿名管道与命名管道的区别
3.命名管道的打开规则
4.用命名管道实现server&client通信
一、匿名管道的应用实例-父进程唤醒子进程,子进程执行某种任务
后续将源码上传到gitee,上传后修改链接。
二、命名管道
- 管道应用的一个限制就是只能具有共同祖先的进程进行通信
- 如果想让不相关的进程交换数据,可以使用FIFO文件来做,它被称为命名管道
- 命名管道是一种特殊的文件
1.创建一个命名管道
创建命令:mkfifo filename
创建函数: int mkfifo(const char * filename,mode_t mode);
参数:管道的名字,创建的管道权限
2.匿名管道与命名管道的区别
- 匿名管道由pipe函数创建并打开
- 命名管道由mkfifo函数创建,打开用open
- FIFO(命名管道)与pipe(匿名管道)之间的区别在于,他们创建与打开的方式不同,这些工作完成后,他们有相同的语义。
3.命名管道的打开规则
- 如果是只读方式打开FIFO
- O_NONBLOCK disable:阻塞直到有相应进程为写而打开FIFO
- O_NONBLOCK enable:立刻返回成功
- 如果是只写方式打开FIFO
- O_NONBLOCK disable:阻塞直到有相应进程为读而打开FIFO
- O_NONBLOCK enable:立刻返回失败,错误码为ENXIO
4.用命名管道实现server&client通信
实例功能:
1创建管道
2 创建的命名管道可以让两个进程通信
3. 进程A 向管道中写入 进程B从管道中读取并打印到标准输出
需求分析:首先需要创建两个进程,client端和server端,还需要一个common文件来声明共同的定义和方法,所以创建三个文件client.cc,server.cc,common.hpp。接下来逐个文件分析
1.首先,创建管道,只需要创建一次即可,本次案例在server.cc中创建,client.cc中使用即可
common.hpp
#pragma once
#include<iostream>
#include<string>
#define NUM 1024
const std::string fifoname = "./fifo";
uint32_t mode = 0666;
server.cc
umask = 0; //这个设置不影响系统的umask,只影响此进程的
int n = mkfifo(fifoname.c_str(),mode);
至此管道已经创建
2.让服务端直接开启管道文件
int rfd = open(fifoname.c_str(),O_RDONLY);
//打开失败
if(rfd < 0)
{
std::cout<<errno<<endl;
return 2;
}
//打开成功
....
3.client端不需要创建文件,只用写方式打开文件就可以
// int open(const char * pathname ,int oflag, ...)
//成功则返回文件描述符,失败-1
int wfd = open(filename.c_str(),O_WRONLY);
if(wfd <0)
{
//写方式打开失败
return 1;
}
4.两端开始通信
server端:
char buffer[1024];
while(true)
{
buffer[0] = 0;
//read(int fd , void * buf, size_t count) fd是文件描述符,用于要定位读取的文件或者其他设备,buf为缓冲区地址,count是要读取的字节数,读成功返回实际读取的字节数,返回复数读取失败,返回0读取到文件末尾
//从rfd文件中读取x个字节到buffer中
ssize_t n = read(rfd,buffer,sizeof(buffer)-1);
if(n> 0)
{
buffer[n] = 0;
std::cout<<"client " <<buffer <<std::endl;
}
else if(n== 0)
{
std::cout<<"client quit, me too" <<std::endl;
break;
}
else
{
std::cout<<errno<<std::endl;
break;
}
}
client端:
char buffer[NUM];
while(true)
{
std::cout<<"please enter your message : ";
char * msg = fgets(buffer,sizeof(buffer)-1,stdin);
assert(msg);
(void)msg;
//处理发送消息的回车,最后一个字符删掉
buffer[strlen(buffer)-1] = o;
ssize_t n = write(wfd,buffer,strlen(buffer));
assert(n>= 0);
(void)n;
}
5.两端通信结束,关闭对应的文件描述符
close(wfd);文章来源:https://www.toymoban.com/news/detail-682710.html
close(rfd);文章来源地址https://www.toymoban.com/news/detail-682710.html
到了这里,关于Linux通信--构建进程通信的 方案之管道(下)|使用匿名管道实现功能解耦|命名管道实现serve&client通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!