对select函数的理解
对select函数的理解
1. 处理多个socket链接的方法
阻塞模式下服务端要解决多个客户链接的问题的3个思路:
- 每个客户端的socket对应一个内核线程,在这个线程内部进行阻塞的read
- 单线程,自己记录一个socket列表,循环去内核中查询socket是否ready
- 单线程,系统提供一个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函数步骤:
- 初始化 fd_set,把要监控的fd仍进去
- 调用select,阻塞
- 阻塞结束后,遍历查看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的内部实现:
- readfds 从用户空间传递到内核空间
- 将当前进程加入到 readfds 中的每个socket的等待队列
- 当socket来数据了就把 线程唤醒(移出等待队列)
- 把有数据的fds 从内核空间搞到用户空间
- 用户空间看一遍fds,知道哪个socket有数据了,然后read、accept
select的问题:
- 每次调用select就要把readfds 传到内核,wake的时候再拿回来需要传递1024 * 4 bytes
- 每次需要把当前线程加入到所有socket的等待队列
- 每次需要遍历一遍readfds来查看那个socket有数据
每次调用select都会有以上两次传递和两次遍历,当链接个数多时,性能下降比较快:
select可能的改进:
- readfds一直都在内核中维护,不要每次都送进来
- 可以动态单个变更内核中的readfds
- 就绪列表,传给内核一个指针,内核把这个指针指向就绪的sockets (避免来回传递所有的socket)
对select函数的理解的更多相关文章
- (十二)select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型,原型:int select(int maxfd,fd_set *rdset ...
- select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)
select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型, 原型: int select(int maxfd,fd_set *rds ...
- linux网络编程:select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)
从别人的博客中转载过来了这一篇文章,经过重新编辑排版之后展现于此,做一个知识点保存与学习. select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复 ...
- select()函数用法一
select()函数用法以及FD_ZERO.FD_SET.FD_CLR.FD_ISSET select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用 ...
- 转 select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型,原型:int select(int maxfd,fd_set *rdset ...
- select 函数1
Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不太爱用Select写程序,他们只是习惯写诸如connect.accept.recv或recvfrom这样的阻塞程序( ...
- 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函数用于在非阻塞中 ...
- I/O多路复用——select函数与poll函数
1 区别 同:(1)机制类似,本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理.(2)包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就 ...
- select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET (转)
select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复用输入/输出模型,原型: #include <sys/time.h> ...
随机推荐
- EF用导航熟悉遍历从表时,删除主表出错
var entitys= Repository.Table.Where(a => ids.Contains(a.UUID)).ToList(); entitys.ForEach(a => ...
- 阿里云服务器centOS安装Docker
环境准备 1.需要有Linux的基础 2.centOS 7 环境查看 # 系统内核是 3.10 以上的 [root@iz2zeaet7s13lfkc8r3e2kz ~]# uname -r -.el7 ...
- 你确信 X-Forwarded-For 拿到的就是用户真实 IP 吗?
X-Forwarded-For 拿到的就是真实 IP 吗? 1.故事 在这个小节开始前,我先讲一个开发中的小故事,可以加深一下大家对这个字段的理解. 前段时间要做一个和风控相关的需求,需要拿到用户的 ...
- BST and Heap详解
BST(Binary Search Tree) 基本特点: 二叉树 集合中的数据具有可比较大小的关键码 数据之间满足BST特性 中序遍历可得到一个递增的数据序列(可作为判断一棵二叉树是否是BST的方法 ...
- 前后端分离,如何在前端项目中动态插入后端API基地址?(in docker)
开门见山,本文分享前后端分离,容器化前端项目时动态插入后端API基地址,这是一个很赞的实践,解决了前端项目容器化过程中受制后端调用的尴尬. 尴尬从何而来 常见的web前后端分离:前后端分开部署,前端项 ...
- Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
试题 算法提高 转圈游戏 问题描述 n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏.按照顺时针方向给 n 个位置编号,从0 到 n-1.最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在 ...
- Java实现 LeetCode 227 基本计算器 II(二)
227. 基本计算器 II 实现一个基本的计算器来计算一个简单的字符串表达式的值. 字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 . 整数除法仅保留整数部分. 示例 1: 输入: ...
- Java实现 LeetCode 172 阶乘后的零
172. 阶乘后的零 给定一个整数 n,返回 n! 结果尾数中零的数量. 示例 1: 输入: 3 输出: 0 解释: 3! = 6, 尾数中没有零. 示例 2: 输入: 5 输出: 1 解释: 5! ...
- java实现第四届蓝桥杯好好学习
好好学习 汤姆跟爷爷来中国旅游.一天,他帮助中国的小朋友贴标语.他负责贴的标语是分别写在四块红纸上的四个大字:"好.好.学.习".但是汤姆不认识汉字,他就想胡乱地贴成一行. 请你替 ...
- java实现第四届蓝桥杯组素数
组素数 题目描述 素数就是不能再进行等分的数.比如:2 3 5 7 11 等. 9 = 3 * 3 说明它可以3等分,因而不是素数. 我们国家在1949年建国.如果只给你 1 9 4 9 这4个数字卡 ...