热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【服务器系统设计】select函数的用法及其原理总结

在Linux上,为我们提供了三种IO多路复用的函数供我们使用,select函数是网络通信编程中很常用的一个函数。select函数一般用于检测在一组soc

在Linux上,为我们提供了三种IO多路复用的函数供我们使用,select函数是网络通信编程中很常用的一个函数。select函数一般用于检测在一组socket中是否有事件准备就绪。


select的声明:

#include //for struct timeval
#include //for select/**
* return 状态变化的文件描述符的个数
* @param nfds: linux上的socket也是一种fd(文件描述符),将这个参数的值设置为所有需要使用select函数检测事件的fd的最大值加1
* @param readfds:需要监听可读事件的fd集合
* @param writefds:需要监听可写事件的fd集合
* @param exceptfds: 需要监听的异常事件的fd集合
* @param timeout:超时时间,即在这个参数设定的时间内检测这些fd的事件,超过这个时间后,select函数立即返回。
**/
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout);

fd_set是一个结构体信息,其定义位于/usr/include/sys/select.h中,其定义如下:

typedef struct
{long int __fds_bits[16]; //可以看作128bit的数组
} fd_set

在将一个fd添加到fd_set这个集合中时需要使用FD_SET宏,其定义如下:

void FD_SET(int fd, fd_set* set);

将一个fd从fd_set中删除需要使用FD_CLR,其定义如下:

void FD_CLR(int fd, fd_set* set);

如果需要将fd_set中所有fd全都清除,则使用FD_ZERO,其定义如下:

void FD_ZERO(fd_set* set);

当select函数返回时,我们使用FD_ISSET宏判断在某个fd是否有我们关心的事件,FD_ISSET宏的定义如下:

int FD_ISSET(int fd, fd_set* set);

select函数使用的基本流程

在这里插入图片描述


示例代码

#include
#include
#include
#include
#include
#include
#include
#include
#include static const int INVALID_FD = -1; //自定义代表无效fd的值int main(int argc, char** argv)
{//创建一个监听socketint listenfd &#61; socket(AF_INET, SOCK_STREAM, 0);if(listenfd &#61;&#61; INVALID_FD){std::cout <<"create listen socket error." < clientfds;int maxfd;while(true){fd_set readset;FD_ZERO(&readset);//将监听socket加入待检测的可读事件中FD_SET(listenfd, &readset);maxfd &#61; listenfd;//将客户端的fd加入待检测的可读事件中int clientfds_length &#61; clientfds.size();for(int i &#61; 0; i }

关于以上代码&#xff0c;在实际开发中有几个需要注意的点&#xff0c;如下&#xff1a;


  • select 函数在调用前后可能会修改readfds, writefds和exceptfds这三个集合中的内容&#xff0c;如果想在下次调用select函数时复用这些fd_set变量&#xff0c;则要在下次调用前使用FD_ZERO将fd_set清零&#xff0c;然后调用FD_SET将需要检测事件的fd重新添加到fd_set中。
  • select函数也会修改timeval结构体的值&#xff0c;如果想复用这个变量&#xff0c;则必须给timeval变量重新设置值。
  • select函数的timeval结构体的tv_sec和tv_usec如果都被设置为0&#xff0c;即检测事件的总时间被设置为0&#xff0c;其行为是select检测相关集合中的fd&#xff0c;如果没有需要的事件&#xff0c;则立即返回

select 函数的缺点


  • 每次调用select函数时&#xff0c;都需要把fd集合从用户态复制到内核态中&#xff0c;这个开销在fd较多时会很大&#xff0c;同时每次调用select函数都需要在内核中遍历传递进来的所有fd&#xff0c;这个开销在fd较多时也很大。
  • 单个进程能够监视的文件描述符的数量存在最大限制&#xff0c;在Linux上一般为1024&#xff0c;可以通过先修改宏定义然后重新编译内核来调整这一限制&#xff0c;但这样非常麻烦且效率低下。
  • select函数在每次调用之前都要对传入的参数进行重新设定&#xff0c;这样做也比较麻烦。
  • 在Linux上&#xff0c;select函数的实现原理是其底层使用了poll函数

推荐阅读
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 本文详细介绍了Java反射机制的基本概念、获取Class对象的方法、反射的主要功能及其在实际开发中的应用。通过具体示例,帮助读者更好地理解和使用Java反射。 ... [详细]
  • 【妙】bug称它为数组越界的妙用
    1、聊一聊首先跟大家推荐一首非常温柔的歌曲,跑步的常听。本文主要把自己对C语言中柔性数组、零数组等等的理解分享给大家,并聊聊如何构建一种统一化的学习思想 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • 字符串学习时间:1.5W(“W”周,下同)知识点checkliststrlen()函数的返回值是什么类型的?字 ... [详细]
  • 本文探讨了如何通过编程手段在Linux系统中禁用硬件预取功能。基于Intel® Core™微架构的应用性能优化需求,文章详细介绍了相关配置方法和代码实现,旨在帮助开发人员有效控制硬件预取行为,提升应用程序的运行效率。 ... [详细]
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • 包含phppdoerrorcode的词条 ... [详细]
  • 本文详细介绍了如何在PHP中记录和管理行为日志,包括ThinkPHP框架中的日志记录方法、日志的用途、实现原理以及相关配置。 ... [详细]
  • 本文总结了《编程珠玑》第12章关于采样问题的算法描述与改进,并提供了详细的编程实践记录。参考了其他博主的总结,链接为:http://blog.csdn.net/neicole/article/details/8518602。 ... [详细]
  • 本文总结了Java初学者需要掌握的六大核心知识点,帮助你更好地理解和应用Java编程。无论你是刚刚入门还是希望巩固基础,这些知识点都是必不可少的。 ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 本文探讨了C语言和C++中大小写的处理方式,并详细介绍了如何在C++中实现不区分大小写的字符串比较。通过自定义`char_traits`类,可以灵活地处理字符的比较、复制和转换。 ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
author-avatar
云沏-茶
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有