进程间并发通信-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

相关文章

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

Linux系统管理与进程任务管理方式

《Linux系统管理与进程任务管理方式》本文系统讲解Linux管理核心技能,涵盖引导流程、服务控制(Systemd与GRUB2)、进程管理(前台/后台运行、工具使用)、计划任务(at/cron)及常用... 目录引言一、linux系统引导过程与服务控制1.1 系统引导的五个关键阶段1.2 GRUB2的进化优

Spring Security 前后端分离场景下的会话并发管理

《SpringSecurity前后端分离场景下的会话并发管理》本文介绍了在前后端分离架构下实现SpringSecurity会话并发管理的问题,传统Web开发中只需简单配置sessionManage... 目录背景分析传统 web 开发中的 sessionManagement 入口ConcurrentSess

Go中select多路复用的实现示例

《Go中select多路复用的实现示例》Go的select用于多通道通信,实现多路复用,支持随机选择、超时控制及非阻塞操作,建议合理使用以避免协程泄漏和死循环,感兴趣的可以了解一下... 目录一、什么是select基本语法:二、select 使用示例示例1:监听多个通道输入三、select的特性四、使用se

MySQL中处理数据的并发一致性的实现示例

《MySQL中处理数据的并发一致性的实现示例》在MySQL中处理数据的并发一致性是确保多个用户或应用程序同时访问和修改数据库时,不会导致数据冲突、数据丢失或数据不一致,MySQL通过事务和锁机制来管理... 目录一、事务(Transactions)1. 事务控制语句二、锁(Locks)1. 锁类型2. 锁粒

深入解析Java NIO在高并发场景下的性能优化实践指南

《深入解析JavaNIO在高并发场景下的性能优化实践指南》随着互联网业务不断演进,对高并发、低延时网络服务的需求日益增长,本文将深入解析JavaNIO在高并发场景下的性能优化方法,希望对大家有所帮助... 目录简介一、技术背景与应用场景二、核心原理深入分析2.1 Selector多路复用2.2 Buffer

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

Go语言并发之通知退出机制的实现

《Go语言并发之通知退出机制的实现》本文主要介绍了Go语言并发之通知退出机制的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、通知退出机制1.1 进程/main函数退出1.2 通过channel退出1.3 通过cont

java如何实现高并发场景下三级缓存的数据一致性

《java如何实现高并发场景下三级缓存的数据一致性》这篇文章主要为大家详细介绍了java如何实现高并发场景下三级缓存的数据一致性,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 下面代码是一个使用Java和Redisson实现的三级缓存服务,主要功能包括:1.缓存结构:本地缓存:使

一文解密Python进行监控进程的黑科技

《一文解密Python进行监控进程的黑科技》在计算机系统管理和应用性能优化中,监控进程的CPU、内存和IO使用率是非常重要的任务,下面我们就来讲讲如何Python写一个简单使用的监控进程的工具吧... 目录准备工作监控CPU使用率监控内存使用率监控IO使用率小工具代码整合在计算机系统管理和应用性能优化中,监