select和epoll的实现
select:fd_set是输入结果参数,每次select之后,还得重置fd_set
(1)使用copy_from_user从用户空间拷贝fd_set到内核空间,第一步需要复制所有感兴趣的文件描述符到内核态
(2)注册回调函数__pollwait
(3)遍历所有fd,调用其对应的poll方法(对于socket,这个poll方法是sock_poll,sock_poll根据情况会调用到tcp_poll,udp_poll或者datagram_poll)
(4)以tcp_poll为例,其核心实现就是__pollwait,也就是上面注册的回调函数。
(5)__pollwait的主要工作就是把current(当前进程)挂到设备的等待队列中,不同的设备有不同的等待队列,对于tcp_poll来说,其等待队列是sk->sk_sleep(注意把进程挂到等待队列中并不代表进程已经睡眠了)。在设备收到一条消息(网络设备)或填写完文件数据(磁盘设备)后,会唤醒设备等待队列上睡眠的进程,这时current便被唤醒了。(设备可以用fd表示,设备是通过fd和进程相关联的)
(6)poll方法返回时会返回一个描述读写操作是否就绪的mask掩码,根据这个mask掩码给fd_set赋值。
(7)如果遍历完所有的fd,还没有返回一个可读写的mask掩码,则会调用schedule_timeout是调用select的进程(也就是current)进入睡眠。当设备驱动发生自身资源可读写后,会唤醒其等待队列上睡眠的进程,然后继续循环遍历fd。如果超过一定的超时时间(schedule_timeout指定),还是没人唤醒,则调用select的进程会重新被唤醒获得CPU,进而重新遍历fd,判断有没有就绪的fd。
(8)把fd_set从内核空间拷贝到用户空间。
性能瓶颈:
(1)数千个设备fd在每次调用时,都需要将其从用户空间复制到内核空间, 这里的开销不可忽略,从内核态到用户态的拷贝,也不可忽略
(2)同时每次调用select都需要在内核遍历传递进来的所有fd,对于每个fd都得调用poll方法,这个开销在fd很多时也很大
循环调用poll方法,也就是循环把current进程挂到设备中,目的是设备fd就绪的时候,能够唤醒进程。
epoll:
所有添加到epoll中的事件都会与设备(网卡)驱动程序建立回调关系,也就是说,当相应的事件发生时会调用这个回调方法。这个回调方法在内核中叫ep_poll_callback,它会将发生的事件添加到rdlist双链表中。
epoll的解决方案不像select或poll一样每次都把current轮流加入fd对应的设备等待队列中,而只在epoll_ctl时把current挂一遍(这一遍必不可少)并为每个fd指定一个回调函数,当设备就绪,唤醒等待队列上的等待者时,就会调用这个回调函数,而这个回调函数会把就绪的fd加入一个就绪链表)。epoll_wait的工作实际上就是在这个就绪链表中查看有没有就绪的fd(利用schedule_timeout()实现睡一会,判断一会的效果,和select实现中的第7步是类似的)
epoll:只是在epoll_ctl的时候,把current进程挂到fd设备的等待队列中,而且设置fd对应的回调函数,当fd就绪的时候,唤醒进程,然后将fd加入rdlist链表中。这样在一次epoll中,就只需要挂在设备中一次。而select中,在fd就绪的时候,重新遍历fd的时候,还得调用poll方法,此方法把current(当前进程)挂到设备的等待队列中。
select和epoll的实现的更多相关文章
- select/poll/epoll on serial port
In this article, I will use three asynchronous conferencing--select, poll and epoll on serial port t ...
- Linux下select&poll&epoll的实现原理(一)
最近简单看了一把 linux-3.10.25 kernel中select/poll/epoll这个几个IO事件检测API的实现.此处做一些记录.其基本的原理是相同的,流程如下 先依次调用fd对应的st ...
- Python之路-python(Queue队列、进程、Gevent协程、Select\Poll\Epoll异步IO与事件驱动)
一.进程: 1.语法 2.进程间通讯 3.进程池 二.Gevent协程 三.Select\Poll\Epoll异步IO与事件驱动 一.进程: 1.语法 简单的启动线程语法 def run(name): ...
- 多进程、协程、事件驱动及select poll epoll
目录 -多线程使用场景 -多进程 --简单的一个多进程例子 --进程间数据的交互实现方法 ---通过Queues和Pipe可以实现进程间数据的传递,但是不能实现数据的共享 ---Queues ---P ...
- Python自动化 【第十篇】:Python进阶-多进程/协程/事件驱动与Select\Poll\Epoll异步IO
本节内容: 多进程 协程 事件驱动与Select\Poll\Epoll异步IO 1. 多进程 启动多个进程 进程中启进程 父进程与子进程 进程间通信 不同进程间内存是不共享的,要想实现两个进程间 ...
- 轮询、select、 epoll
网卡设备对应一个中断号, 当网卡收到网络端的消息的时候会向CPU发起中断请求, 然后CPU处理该请求. 通过驱动程序 进而操作系统得到通知, 系统然后通知epoll, epoll通知用户代码. 一. ...
- 五种I/O 模式,select、epoll方法的理解,BIO、NIO、AIO理解 相关文章
一.io方式 Linux网络编程 五种I/O 模式及select.epoll方法的理解 web优化必须了解的原理之I/o的五种模型和web的三种工作模式 五种I/O 模式——阻塞(默认IO模式),非阻 ...
- select与epoll、apache与nginx实现原理对比
转自:http://www.tuicool.com/articles/AzmiY3 关于select与epoll 两种IO模型,都属于多路IO就绪通知,提供了对大量文件描述符就绪检查的高性能方案,只不 ...
- [转]谈谈select, iocp, epoll,kqueue及各种网络I/O复用机制
参考原文:再谈select, iocp, epoll,kqueue及各种I/O复用机制 一.I/O模型概述 介绍几种常见的I/O模型及其区别,如下: blocking I/O nonblocking ...
- 【转】select和epoll模型的差异
http://www.cppblog.com/converse/archive/2008/10/12/63836.html epoll为什么这么快 epoll是多路复用IO(I/O Multiplex ...
随机推荐
- easyui之datagrid之formatter(后台传递常量自动转换值)
1,datagrid之formatter formatter格式化函数有三个参数: value:字段值(一般为后台传递给前台的值): row:当前行数据: index:当前行索引. return值是显 ...
- 12个有趣的c语言面试题
1.gets()函数 问:请找出下面代码里的问题: #include int main(void) { char buff[10]; memset(buff,0,sizeof(buff)); gets ...
- OSCache安装
OSCache是一个基于web应用的组件,他的安装工作主要是对web应用进行配置,大概的步骤如下: 1. 下载.解压缩OSCachehttps://java.net/downloads/oscache ...
- PHP内核介绍及扩展开发指南—Extensions 的编写
Extensions 的编写 理解了这些运行机制以后,本章着手介绍Extensions 的编写,但凡写程序的人都知道hello world,那好,就从hello world开始. 1.1Hello W ...
- 分布式文件系统MFS(moosefs)实现存储共享
分布式文件系统MFS(moosefs)实现存储共享(第二版) 作者:田逸(sery@163.com) 由于用户数量的不断攀升,我对访问量大的应用实现了可扩展.高可靠的集群部署(即lvs+keepali ...
- vim 添加插件
vim 的功能可以通过向它添加plugin得以扩展.所谓的plugin不过是一个vim会自动载入执行的脚本.把一个脚本放到你的plugin目录就可以了,非常容易. plugin基本上分为两类: 全局 ...
- 性能优化之_android布局优化
优化布局的的原则就是减少创建的对象的数量,setContentView话费onCreate到onResume中的大概99%的时间1.使用Relativelayout而不是LinearLayout,Li ...
- mysql导入导出文本文件
MySQL导入出文本文件只能到处数据,不能到处结构,不过也算备份数据一种方法. 导入文本文件 在此像导入csv文件 也是类似 load data local infile 'd:/insert.txt ...
- Django Rest Framework框架 ---- url控制器
Django Rest Framework框架 ---- url控制器
- SQL 批量插入有标识列的数据
代码: SET IDENTITY_INSERT 表名 ON SET IDENTITY_INSERT 表名 OFF