进程间并发通信-IO多路复用

2024-06-03 17:52

本文主要是介绍进程间并发通信-IO多路复用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 select

1.1 源码示例

/*************************************************************************> File Name: write.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 14时50分23秒************************************************************************/#include<stdio.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>int main(void)
{int fd=0;char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_WRONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 接收终端输入并写入管道文件描述符-向管道写数据 */while(1){fgets(tmpbuff,sizeof(tmpbuff),stdin);write(fd,tmpbuff,strlen(tmpbuff));}/* 4 关闭管道 */close(fd);return 0;
}
/*************************************************************************> File Name: read.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 14时34分49秒************************************************************************/#include<stdio.h>#include <signal.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>/* According to POSIX.1-2001, POSIX.1-2008 */
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>int main(void)
{int fd=0;fd_set rdfds;fd_set tmpfds;int ret=0;char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_RDONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 文件描述符集的操作 - 4个宏 - FD_ZERO(initialize)-FD_SET(create)-FD_CLR(delete)-FD_ISSET(retrieve) *//* 3.1 初始化文件描述符集合 */FD_ZERO(&rdfds);//清除文件描述符集合 - 初始化文件描述符集合/* 3.2 增加文件描述符至文件描述符集合 */FD_SET(fd,&rdfds);//添加文件描述符至文件描述符集FD_SET(0,&rdfds);/* 4 管道读(写) - 终端和管道-谁来数据就读谁 */while(1){/* 4.1 初始化监听文件描述符集合 */tmpfds=rdfds;/* 4.2 监听文件描述符集合 -> 监听多个文件描述符,直到有一个或者多个文件描述符准备进行某类IO操作 *//*注意: 一旦监听到某个文件描述符准备进行IO操作,那么这个文件描述符监听前后状态就发生了变化 ( 非ready状态->ready状态 ),* 所以要想一直对某个文件描述符进行监听,每次调用select之前都要重置该文件描述符状态为监听之前的状态(即非ready状态)*/ret=select(fd+1,&tmpfds,NULL,NULL,NULL);if(-1==ret){perror("fail to select");return -1;}/* 4.3 查询文件描述符集合中某个文件描述符状态是否发生改变 */if(FD_ISSET(fd,&tmpfds)){memset(tmpbuff,0,sizeof(tmpbuff));read(fd,tmpbuff,sizeof(tmpbuff));printf("fifo: %s\n",tmpbuff);}if(FD_ISSET(0,&tmpfds)){memset(tmpbuff,0,sizeof(tmpbuff));fgets(tmpbuff,sizeof(tmpbuff),stdin);printf("stdin: %s\n",tmpbuff);}}/* 5 关闭文件描述符 */close(fd);return 0;
}

1.2 运行结果

1.3 分析总结

2 poll

1.1 源码示例

/*************************************************************************> File Name: write.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 16时30分10秒************************************************************************/#include<stdio.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>int main(void)
{int fd=0;char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_WRONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 接收终端输入并写入管道文件描述符-向管道写数据 */while(1){fgets(tmpbuff,sizeof(tmpbuff),stdin);write(fd,tmpbuff,strlen(tmpbuff));}/* 4 关闭管道 */close(fd);return 0;
}
/*************************************************************************> File Name: read.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 16时30分10秒************************************************************************/#include<stdio.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>#include <poll.h>int main(void)
{int fd=0;struct pollfd fds[2];int fready=0;char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_RDONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 初始化文件描述符状态结构体数组*/fds[0].fd=fd;//添加文件描述符至数组fds[0].events=POLLIN;//修改文件描述符状态为 准备读fds[1].fd=0;fds[1].events=POLLIN;/* 4 管道读(写) - 终端和管道-谁来数据就读谁 */while(1){/* 4.1 监听文件描述符状态结构体数组 */fready=poll(fds,2,-1);//文件描述符数组(数组)-文件描述符个数(数组长度)-超时时间(-1 一直等)if(-1==fready){perror("fail to poll");return -1;}/* 4.2 查询文件描述符状态 - 通过位掩码方式查询 - 置位 */if(fds[0].revents&POLLIN){memset(tmpbuff,0,sizeof(tmpbuff));read(fd,tmpbuff,sizeof(tmpbuff));printf("fifo: %s\n",tmpbuff);}if(fds[1].revents&POLLIN){memset(tmpbuff,0,sizeof(tmpbuff));fgets(tmpbuff,sizeof(tmpbuff),stdin);printf("stdin: %s\n",tmpbuff);}}/* 5 关闭管道 */close(fd);
}

1.2 运行结果

1.3 分析总结

3 epoll

1.1 源码示例

/*************************************************************************> File Name: write.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 17时22分26秒************************************************************************/#include<stdio.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>int main(void)
{int fd=0;char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_WRONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 接收终端输入并写入管道文件描述符-向管道写数据 */while(1){fgets(tmpbuff,sizeof(tmpbuff),stdin);write(fd,tmpbuff,strlen(tmpbuff));}/* 4 关闭管道 */close(fd);return 0;
}
/*************************************************************************> File Name: read.c> Author: yas> Mail: rage_yas@hotmail.com> Created Time: 2024年06月02日 星期日 17时22分26秒************************************************************************/#include<stdio.h>#include <sys/types.h>
#include <sys/stat.h> #include <fcntl.h>#include <unistd.h>#include <string.h>#include <sys/epoll.h>int main(void)
{int fd=0;int epfd=0;struct epoll_event env;int fready=0;int i=0;struct epoll_event retenv[2];char tmpbuff[4096]={0};/* 1 创建有名管道 */mkfifo("/tmp/myfifo",0664);/* 2 打开有名管道 */fd=open("/tmp/myfifo",O_RDONLY);if(-1==fd){perror("fail to open");return -1;}/* 3 创建内核事件表 - 并返回表头 */epfd=epoll_create(2);//预期添加到事件表的文件描述符数量if(-1==epfd){perror("fail to epoll_create");return -1;}/* 4 初始化内核epoll事件结构体 - 数据类型 -初始化事件结构体 */env.events=EPOLLIN;//修改文件描述符状态为 准备读 - 事件状态 - 非ready态env.data.fd=fd;//文件描述符 - 这里指有名管道/* 5 操作内核epoll事件表 - EPOLL_CTL_ADD(增-fd)-EPOLL_CTL_DEL(删-fd)-EPOLL_CTL_MOD(改-fd事件) */epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&env);//建立文件描述符fd及其对应的事件env,并将文件描述符fd添加到epoll事件表epfd中env.events=EPOLLIN;env.data.fd=0;epoll_ctl(epfd,EPOLL_CTL_ADD,0,&env);//终端也将发生同样的事件(EPOLLIN),所以将终端(此指stdin)也加入至该内核事件表/* 6 管道读(写) - 终端和管道-谁来数据就读谁 */while(1){/* 6.1 监听内核epoll事件表,并返回ready态的文件描述符数量 */fready=epoll_wait(epfd,retenv,2,-1);//这里通过结构体数组retenv作为出参,将ready态的文件描述符带出-ready态if(-1==fready){perror("fail to epoll_wait");return -1;}/* 6.2 遍历所有ready态的文件描述符 */for(i=0;i<fready;i++){/* 通过ready态文件描述符进一步确认是哪个文件描述符状态被置位 -* 检测(类似于IO输入检测-key检测的思想-位掩码)-查询*/if(retenv[i].data.fd==0){memset(tmpbuff,0,sizeof(tmpbuff));fgets(tmpbuff,sizeof(tmpbuff),stdin);printf("stdin: %s\n",tmpbuff);}else if(retenv[i].data.fd==fd){memset(tmpbuff,0,sizeof(tmpbuff));read(fd,tmpbuff,sizeof(tmpbuff));printf("fifo: %s\n",tmpbuff);}}}/* 6 关闭管道*/close(fd);
}

1.2 运行结果

1.3 分析总结

这篇关于进程间并发通信-IO多路复用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027694

相关文章

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

Windows的CMD窗口如何查看并杀死nginx进程

《Windows的CMD窗口如何查看并杀死nginx进程》:本文主要介绍Windows的CMD窗口如何查看并杀死nginx进程问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录Windows的CMD窗口查看并杀死nginx进程开启nginx查看nginx进程停止nginx服务

Java进程CPU使用率过高排查步骤详细讲解

《Java进程CPU使用率过高排查步骤详细讲解》:本文主要介绍Java进程CPU使用率过高排查的相关资料,针对Java进程CPU使用率高的问题,我们可以遵循以下步骤进行排查和优化,文中通过代码介绍... 目录前言一、初步定位问题1.1 确认进程状态1.2 确定Java进程ID1.3 快速生成线程堆栈二、分析

如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socket read timed out的问题

《如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socketreadtimedout的问题》:本文主要介绍解决Druid线程... 目录异常信息触发场景找到版本发布更新的说明从版本更新信息可以看到该默认逻辑已经去除总结异常信息触发场景复

RabbitMQ工作模式中的RPC通信模式详解

《RabbitMQ工作模式中的RPC通信模式详解》在RabbitMQ中,RPC模式通过消息队列实现远程调用功能,这篇文章给大家介绍RabbitMQ工作模式之RPC通信模式,感兴趣的朋友一起看看吧... 目录RPC通信模式概述工作流程代码案例引入依赖常量类编写客户端代码编写服务端代码RPC通信模式概述在R

在Spring Boot中实现HTTPS加密通信及常见问题排查

《在SpringBoot中实现HTTPS加密通信及常见问题排查》HTTPS是HTTP的安全版本,通过SSL/TLS协议为通讯提供加密、身份验证和数据完整性保护,下面通过本文给大家介绍在SpringB... 目录一、HTTPS核心原理1.加密流程概述2.加密技术组合二、证书体系详解1、证书类型对比2. 证书获

python多线程并发测试过程

《python多线程并发测试过程》:本文主要介绍python多线程并发测试过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、并发与并行?二、同步与异步的概念?三、线程与进程的区别?需求1:多线程执行不同任务需求2:多线程执行相同任务总结一、并发与并行?1、

Python模拟串口通信的示例详解

《Python模拟串口通信的示例详解》pySerial是Python中用于操作串口的第三方模块,它支持Windows、Linux、OSX、BSD等多个平台,下面我们就来看看Python如何使用pySe... 目录1.win 下载虚www.chinasem.cn拟串口2、确定串口号3、配置串口4、串口通信示例5

Python多进程、多线程、协程典型示例解析(最新推荐)

《Python多进程、多线程、协程典型示例解析(最新推荐)》:本文主要介绍Python多进程、多线程、协程典型示例解析(最新推荐),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定... 目录一、multiprocessing(多进程)1. 模块简介2. 案例详解:并行计算平方和3. 实现逻