热门标签 | 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函数

推荐阅读
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • Go语言实现堆排序的详细教程
    本文主要介绍了Go语言实现堆排序的详细教程,包括大根堆的定义和完全二叉树的概念。通过图解和算法描述,详细介绍了堆排序的实现过程。堆排序是一种效率很高的排序算法,时间复杂度为O(nlgn)。阅读本文大约需要15分钟。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
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社区 版权所有