对select函数的理解

1. 处理多个socket链接的方法

阻塞模式下服务端要解决多个客户链接的问题的3个思路:

  1. 每个客户端的socket对应一个内核线程,在这个线程内部进行阻塞的read
  2. 单线程,自己记录一个socket列表,循环去内核中查询socket是否ready
  3. 单线程,系统提供一个ready状态的socket列表,主线程从这个列表中处理socket

思路1,如果链接很多(C10k)线程就会很多,消耗系统资源,并增加调度成本(Java BIO)。

思路2,每次都要遍历一边所有socket,链接很多时效率低,可能大部分链接都没数据(select)。

思路3,比较理想(epoll)。

2. select函数

2.1. 使用方法

函数原型:

select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, struct timeval *restrict timeout);

select() 检查 readfds, writefds 中的 io描符是否可读、可写了,如果有ready状态的,函数就返回。

nfds是总共fd的个数,而不是最大的fd。

使用select函数步骤:

  1. 初始化 fd_set,把要监控的fd仍进去
  2. 调用select,阻塞
  3. 阻塞结束后,遍历查看fd_set中的ready的socket

fd_set 是什么?

一个结构体:

typedef	struct fd_set {
__int32_t fds_bits[__DARWIN_howmany(__DARWIN_FD_SETSIZE, __DARWIN_NFDBITS)];
} fd_set;

结构体中有一个数组,默认是是1024,这就是linux中select的函数限制最大链接数的原因。

重新编译内核才能提高这个数字。

FD_ISSET 就是取对应位置状态值(0,1),并且在用户空间,

用户需要遍历编一遍这个数组来检查是哪个socket有数据。

select的内部实现:

  1. readfds 从用户空间传递到内核空间
  2. 将当前进程加入到 readfds 中的每个socket的等待队列
  3. 当socket来数据了就把 线程唤醒(移出等待队列)
  4. 把有数据的fds 从内核空间搞到用户空间
  5. 用户空间看一遍fds,知道哪个socket有数据了,然后read、accept

select的问题:

  1. 每次调用select就要把readfds 传到内核,wake的时候再拿回来需要传递1024 * 4 bytes
  2. 每次需要把当前线程加入到所有socket的等待队列
  3. 每次需要遍历一遍readfds来查看那个socket有数据

每次调用select都会有以上两次传递和两次遍历,当链接个数多时,性能下降比较快:

select可能的改进:

  1. readfds一直都在内核中维护,不要每次都送进来
  2. 可以动态单个变更内核中的readfds
  3. 就绪列表,传给内核一个指针,内核把这个指针指向就绪的sockets (避免来回传递所有的socket)

对select函数的理解的更多相关文章

  1. (十二)select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET

    select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型,原型:int select(int maxfd,fd_set *rdset ...

  2. select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)

    select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型, 原型: int select(int maxfd,fd_set *rds ...

  3. linux网络编程:select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)

    从别人的博客中转载过来了这一篇文章,经过重新编辑排版之后展现于此,做一个知识点保存与学习. select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复 ...

  4. select()函数用法一

    select()函数用法以及FD_ZERO.FD_SET.FD_CLR.FD_ISSET select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用 ...

  5. 转 select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET

    select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型,原型:int select(int maxfd,fd_set *rdset ...

  6. select 函数1

    Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect.accept.recv或recvfrom这样的阻塞程序( ...

  7. select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET

    http://hi.baidu.com/%B1%D5%C4%BF%B3%C9%B7%F0/blog/item/e7284ef16bcec3c70a46e05e.html select函数用于在非阻塞中 ...

  8. I/O多路复用——select函数与poll函数

    1 区别 同:(1)机制类似,本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理.(2)包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就 ...

  9. select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET (转)

    select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型,原型: #include <sys/time.h>       ...

随机推荐

  1. OpenResty应用实践

    一. 安装OpenResty 创建OpenResty用户 # useradd -M www -s /usr/sbin/nologin 安装OpenResty # apt-get install lib ...

  2. Java——MVC模式

    MVC:Model View Controller 一般用于动态程序设计,实现了业务逻辑和表示层分离 Model:掌控数据源-->程序员编写程序或者实现算法,数据库人员进行数据库操作等:响应用户 ...

  3. [译]深入理解JVM Understanding JVM Internals

    转载: 英文原版地址:http://www.cubrid.org/blog/dev-platform/understanding-jvm-internals/ 翻不了墙的可以看这个英文版:https: ...

  4. Java实现 LeetCode 757 设置交集大小至少为2(排序+滑动窗口)

    757. 设置交集大小至少为2 一个整数区间 [a, b] ( a < b ) 代表着从 a 到 b 的所有连续整数,包括 a 和 b. 给你一组整数区间intervals,请找到一个最小的集合 ...

  5. C# winform 学习(一)

    目标 1.类和对象 2.定义类 3.对象的操作 4.命名空间 一.类和对象 1.理解 1)类:具有共同特征和行为的一类事物的统称 2)对象:类的一个具体唯一的实例 eg: 1路公交车;(类) 车牌为F ...

  6. Java实现 LeetCode 215. 数组中的第K个最大元素

    215. 数组中的第K个最大元素 在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6 ...

  7. Java实现 蓝桥杯 图书排列(全排列)

    标题:图书排列 将编号为1~10的10本书排放在书架上,要求编号相邻的书不能放在相邻的位置. 请计算一共有多少种不同的排列方案. 注意,需要提交的是一个整数,不要填写任何多余的内容. 9 9 10 9 ...

  8. Java实现 LeetCode70 爬楼梯

    70. 爬楼梯 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数. 示例 1: 输入: 2 输出: ...

  9. Java实现 LeetCode 26 删除排序数组中的重复项

    26. 删除排序数组中的重复项 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) ...

  10. Java实现交替字符串

    1 问题描述 输入三个字符串s1.s2和s3,判断第三个字符串s3是否由前两个字符串s1和s2交错而成且不改变s1和s2中各个字符原有的相对顺序. 2 解决方案 此处采用动态规划法,可以较大的提高时间 ...