IO多路复用简介和代码实例(select函数)

2024-06-13 21:36

本文主要是介绍IO多路复用简介和代码实例(select函数),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

接上篇

阻塞IO、非阻塞IO、IO多路复用和信号驱动IO简介-CSDN博客文章浏览阅读95次。阻塞IO、非阻塞IO、IO多路复用和信号驱动IO简介https://blog.csdn.net/CSDN_DU666666/article/details/139598410?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22139598410%22%2C%22source%22%3A%22CSDN_DU666666%22%7D

基本思想:

        构造一个关于文件描述符的表,将所以要监视的文件描述符都放在这个表里

        将这个表传给一个函数 (select poll epoll),这个函数默认也是阻塞的

        当监视的文件描述中有一个或多个文件描述符准备就绪的时候

        函数会立即返回,并告诉调用者哪些文件描述符已经就绪了

        我们已经知道哪些文件描述符就绪了,再去执行对应的io操作,就不会阻塞了

select函数

功能:实现多路IO复用
头文件:#include <sys/select.h>
函数原型:int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
参数:nfds:		要监视的最大文件描述符+1readfds:	要监视的读文件描述符集合 不关心可以传NULLwritefds:	要监视的写文件描述符集合 不关心可以传NULLexceptfds:	要监视的异常文件描述符集合 不关心可以传NULLtimeout:	超时时间 如果设置成NULL 会一直阻塞 直到有文件描述符就绪
返回值:成功 就绪的文件描述符的个数超时 0失败 -1 重置错误码 注意事项:1.select只能监视小于FD_SETSIZE(1024)的文件描述符2.select返回时会将没有就绪的文件描述符在集合中擦除所以循环中使用select时 每次需要重置集合3.我们一般只关心读文件文件描述符集合 其他两个置NULL即可void FD_CLR(int fd, fd_set *set);	//将文件描述符在集合中删除int  FD_ISSET(int fd, fd_set *set);	//判断文件描述符是否还在集合中// 返回0 表示不在了 非0 表示在void FD_SET(int fd, fd_set *set);	//向集合中添加一个文件描述符void FD_ZERO(fd_set *set);			//清空集合

service.c

首先创建三个管道文件

指令:mkfifo fifo1  

          mkfifo fifo2

          mkfifo fifo3

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>int main(int argc, const char *argv[]){int fd1 = open("fifo1", O_RDONLY);int fd2 = open("fifo2", O_RDONLY);int fd3 = open("fifo3", O_RDONLY);char buff[128] = {0};//创建文件描述符集合fd_set readfds;//母本FD_ZERO(&readfds);fd_set readfds_temp;//副本 用来给select每次擦除用FD_ZERO(&readfds_temp);int max_fd = 0;//用来记录最大的文件描述符//将要监视的文件描述符添加到集合中FD_SET(fd1, &readfds);max_fd = max_fd>fd1 ? max_fd : fd1;FD_SET(fd2, &readfds);max_fd = max_fd>fd2 ? max_fd : fd2;FD_SET(fd3, &readfds);max_fd = max_fd>fd3 ? max_fd : fd3;
#if 0//基础版while(1){//select返回时会将没有就绪的文件描述符在集合中擦除//所以循环中使用select时 每次需要重置集合readfds_temp = readfds;if(-1 == select(max_fd+1, &readfds_temp, NULL, NULL, NULL)){perror("select error");}//程序执行到这儿 说明有文件描述符就绪了//我们需要判断谁就绪了if(FD_ISSET(fd1, &readfds_temp)){memset(buff, 0, 128);read(fd1, buff, 128);printf("fifo1:[%s]\n", buff);}if(FD_ISSET(fd2, &readfds_temp)){memset(buff, 0, 128);read(fd2, buff, 128);printf("fifo2:[%s]\n", buff);}if(FD_ISSET(fd3, &readfds_temp)){memset(buff, 0, 128);read(fd3, buff, 128);printf("fifo3:[%s]\n", buff);}}
#endif#if 1
//进阶版//基础版int ret = 0;int i = 0;while(1){readfds_temp = readfds;if(-1 == (ret = select(max_fd+1, &readfds_temp, NULL, NULL, NULL))){perror("select error");}//遍历文件描述符集合 谁还在里面说明谁就绪for(i = 3; i < max_fd+1 && ret != 0; i++){if(FD_ISSET(i, &readfds_temp)){memset(buff, 0, 128);read(i, buff, 128);printf("buff[%d-3]:[%s]\n",i, buff);ret--;//此处的ret--是为了提高效率的}}}
#endifclose(fd1);close(fd2);close(fd3);return 0;
}

client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main(int argc, const char *argv[]){int fd = open("fifo1", O_WRONLY);//fifo2 fiof3char buff[128] = {0};while(1){memset(buff, 0, 128);printf("请输入:");fgets(buff, 128, stdin);buff[strlen(buff)-1] = '\0';write(fd, buff, 128);}close(fd);return 0;
}

这篇关于IO多路复用简介和代码实例(select函数)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

JAVA项目swing转javafx语法规则以及示例代码

《JAVA项目swing转javafx语法规则以及示例代码》:本文主要介绍JAVA项目swing转javafx语法规则以及示例代码的相关资料,文中详细讲解了主类继承、窗口创建、布局管理、控件替换、... 目录最常用的“一行换一行”速查表(直接全局替换)实际转换示例(JFramejs → JavaFX)迁移建

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

MyBatis中的两种参数传递类型详解(示例代码)

《MyBatis中的两种参数传递类型详解(示例代码)》文章介绍了MyBatis中传递多个参数的两种方式,使用Map和使用@Param注解或封装POJO,Map方式适用于动态、不固定的参数,但可读性和安... 目录✅ android方式一:使用Map<String, Object>✅ 方式二:使用@Param

SpringBoot实现图形验证码的示例代码

《SpringBoot实现图形验证码的示例代码》验证码的实现方式有很多,可以由前端实现,也可以由后端进行实现,也有很多的插件和工具包可以使用,在这里,我们使用Hutool提供的小工具实现,本文介绍Sp... 目录项目创建前端代码实现约定前后端交互接口需求分析接口定义Hutool工具实现服务器端代码引入依赖获

利用Python在万圣节实现比心弹窗告白代码

《利用Python在万圣节实现比心弹窗告白代码》:本文主要介绍关于利用Python在万圣节实现比心弹窗告白代码的相关资料,每个弹窗会显示一条温馨提示,程序通过参数方程绘制爱心形状,并使用多线程技术... 目录前言效果预览要点1. 爱心曲线方程2. 显示温馨弹窗函数(详细拆解)2.1 函数定义和延迟机制2.2

pandas使用apply函数给表格同时添加多列

《pandas使用apply函数给表格同时添加多列》本文介绍了利用Pandas的apply函数在DataFrame中同时添加多列,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录一、Pandas使用apply函数给表格同时添加多列二、应用示例一、Pandas使用apply函

Springmvc常用的注解代码示例

《Springmvc常用的注解代码示例》本文介绍了SpringMVC中常用的控制器和请求映射注解,包括@Controller、@RequestMapping等,以及请求参数绑定注解,如@Request... 目录一、控制器与请求映射注解二、请求参数绑定注解三、其他常用注解(扩展)四、注解使用注意事项一、控制

Python中Namespace()函数详解

《Python中Namespace()函数详解》Namespace是argparse模块提供的一个类,用于创建命名空间对象,它允许通过点操作符访问数据,比字典更易读,在深度学习项目中常用于加载配置、命... 目录1. 为什么使用 Namespace?2. Namespace 的本质是什么?3. Namesp

springboot+mybatis一对多查询+懒加载实例

《springboot+mybatis一对多查询+懒加载实例》文章介绍了如何在SpringBoot和MyBatis中实现一对多查询的懒加载,通过配置MyBatis的`fetchType`属性,可以全局... 目录springboot+myBATis一对多查询+懒加载parent相关代码child 相关代码懒

C++简单日志系统实现代码示例

《C++简单日志系统实现代码示例》日志系统是成熟软件中的一个重要组成部分,其记录软件的使用和运行行为,方便事后进行故障分析、数据统计等,:本文主要介绍C++简单日志系统实现的相关资料,文中通过代码... 目录前言Util.hppLevel.hppLogMsg.hppFormat.hppSink.hppBuf