epoll函数

linux中epoll模型

可紊 提交于 2019-12-24 01:06:21
epoll是linux内核为处理大批量文件描述符而作了改进的poll,是linux下IO复用select/poll的增强版本。 一、epoll的主要接口是: 1、创建 (1)int epoll_create(int maxfds); maxfds是支持的最大句柄数。该函数会返回一个新的epoll句柄,之后的函数调用都用这个句柄来操作。用完之后,记得用close()关闭这个创建出来的epoll句柄,否则可能导致系统fd被耗尽。 (2)int epoll_reate1(int flag); 上面创建的方法在linux 2.6.8之后,maxfds是被忽略的,所以建议采用epoll_create1(0)这种方法。另外epoll_create1(EPOLLCLOEXEC)表示生成的epoll fd具有“执行后关闭”的特性。 2、事件注册 int epoll_ctl(int epfd,int op,int fd,struct epoll_event* event); epoll的事件注册函数,它不同于select/poll在监听的时候告诉内核要监听什么事件,而是先注册要监听的事件类型。 (1)epfd为(1)返回的epoll句柄 (2)op表示动作,用三个宏来表示: EPOLL_CTL_ADD:注册新的fd到epfd中 EPOLL_CTL_MOD:修改已注册的fd的监听事件 EPOLL

Python多种方式实现并发的Web Server

喜欢而已 提交于 2019-12-22 04:07:30
什么是epoll 我们在 Python多种方式实现并发的Web Server 的最后使用单进程+单线程+非阻塞+长连接实现了一个可并发处理客户端连接的服务器。他的原理可以用以下的图来描述: 解释: 1.HTTP服务器是我们使用 单进程+单线程+非阻塞+长连接实现 的web服务器。 2.在实现的时候,我们创建了一个存放已接受Socket连接的列表,该列表是在应用程序的内存空间中的。如图中深蓝色部分 3.当有3个客户端接入的时候,列表中一共存在3个对应的socket句柄,分别对应三个小黄框。 4.灰色小框代表服务器接收请求的socket。 5.我们在进行无限循环的时候,首先是检查是否有新的客户端接入,相当于检查灰色小框是否有数据到达。然后轮询3个小黄框对应socket是否有数据到达。轮询的效率是很低的。 6.服务器在使用accept和recv时,实际上是委托操作系统帮他检查是否有数据到达,由于这个列表的socket都处于用户内存空间,所以需要将其复制到内核空间。操作系统检查完毕后,如果有数据就返回数据给应用程序,如果没有数据就以异常的方式通知应用程序。而且不光这样,操作系统可能还同时在运行其他的应用程序,这样效率会非常低。 我们再来看epoll的图: 解释: 1.我们可以看到,在结构上,最大的区别在于,存放socket的列表不处于应用程序内部。在epoll中

linux timerfd系列函数总结

不想你离开。 提交于 2019-12-21 08:46:07
网上关于timerfd的文章很多,在这儿归纳总结一下方便以后使用,顺便贴出一个timerfd配合epoll使用的简单例子 一、timerfd系列函数   timerfd是Linux为用户程序提供的一个定时器接口。这个接口基于文件描述符,通过文件描述符的可读事件进行超时通知,因此可以配合select/poll/epoll等使用。 下面对timerfd系列函数先做一个简单的介绍: (1)timerfd_create()函数 #include <sys/timerfd.h> int timerfd_create(int clockid, int flags); /* timerfd_create()函数创建一个定时器对象,同时返回一个与之关联的文件描述符。 clockid:clockid标识指定的时钟计数器,可选值(CLOCK_REALTIME、CLOCK_MONOTONIC。。。) CLOCK_REALTIME:系统实时时间,随系统实时时间改变而改变,即从UTC1970-1-1 0:0:0开始计时,中间时刻如果系统时间被用户改成其他,则对应的时间相应改变 CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响 flags:参数flags(TFD_NONBLOCK(非阻塞模式)/TFD_CLOEXEC(表示当程序执行exec函数时本fd将被系统自动关闭

HTTP手记

安稳与你 提交于 2019-12-20 20:50:32
---------------------tcp/ip模型和osi模型--------------------- tcp/ip协议模型 osi模型 应用层      应用层         表示层         会话层 传输层      传输层 网络层      网络层 链路层      数据链路层         物理层 ---------------------交换机--------------------- 1、网络交换机介绍: 网络交换机(又称“网络交换器”),是一个扩大网络的器材,能为子网络中提供更多的连接端口,以便连接更多的计算机 具有性能价格比高、高度灵活、相对简单、易于实现等特点 以太网技术已成为当今最重要的一种局域网组网技术,网络交换机也就成为了最普及的交换机 2、交换机的作用: 转发过滤:当一个数据帧的目的地址在MAC地址表中有映射时,它被转发到连接目的节点的端口而不是所有端口(如该数据帧为广播帧则转发至所有端口) 学习功能:以太网交换机了解每一端口相连设备的MAC地址,并将地址同相应的端口映射起来存放在交换机缓存中的MAC地址表中 ---------------------路由器--------------------- 1. 路由器简介 路由器(Router)又称网关设备(Gateway)是用于连接多个逻辑上分开的网络

基于epoll的聊天室程序

风格不统一 提交于 2019-12-17 03:11:37
epoll相对于poll和select这两个多路复用的I/O模型更加的高效。epoll的函数很简单,麻烦的地方在于水平触发和边沿触发。 用张图来说明下 ET(边沿)只是在状态反转时触发,比如从不可读到可读。而LT(水平)就是如果可读,就会一直触发。所以在使用ET的时候要做一些额外的处理,比如可读的,一直把缓冲区读完,进入不可读状态,下次来数据才会触发。 下面贴出代码,只是一个简单的练习的例子 socketheads.h C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #ifndef SOCKETHEADS_H #define SOCKETHEADS_H #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include <fcntl.h> #include <netinet/in.h> #include <arpa/inet.h> #endif //SOCKETHEADS_H zepoll.h C++ 1 2 3 4 5 6 7 8 9 10 11 12

epoll详解

无人久伴 提交于 2019-12-14 12:03:41
什么是 epoll ? epoll是 Linux 下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,因为它会复用文件描述符集 合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符 集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种IO事件的电平触发 (Level Triggered)外,还提供了边沿触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。 Linux 2.6内核中对/dev/epoll设备的访问的封装(system epoll)。 这个使我们开发网络应用程序更加简单,并且更加高效。 为什么要使用epoll? 同样,我们在linux系统下,影响效率的依然是I/O操作,linux提供给我们select/poll/epoll等多路复用I/O方式 (kqueue暂时没研究过) ,为什么我们对epoll情有独钟呢?原因如下: 1.文件描述符数量的对比。 epoll并没有fd(文件描述符)的上限,它只跟系统内存有关

select、poll、epoll优缺点

别等时光非礼了梦想. 提交于 2019-12-10 21:14:48
select、poll、epoll都是IO多路复用。 I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。 select的缺点 每次调用select,都需要将进程加入到所有fd的等待队列,每次唤醒都需要从每个队列中移除; 每次都需要将fd集合从用户态传递给内核;进程被唤醒后,程序并不知道哪些fd就绪,还需要再比遍历一次; 因为遍历开销较大,默认只能监视1024个fd poll poll 和 select相似,只是fd集合的方式不同,但是解决了select文件描述符的最大上限 epoll(eventpoll) 功能分离, 将等待队列和阻塞进程分开。 create-创建结构体(eventpoll),ctl-增删fd, wait-唤醒 新增就绪队列 内核维护一个就绪列表,引用就绪的fd,就能避免一次遍历 epoll工作方式:创建eventpoll, 通过ctl增删fd,若fd就绪后,调用回到函数将就绪fd放入就绪列表中,并唤醒在wait中进入睡眠的进程(select 和poll

我对网络IO的理解

回眸只為那壹抹淺笑 提交于 2019-12-06 13:47:17
Unix/Linux系统下IO主要分为磁盘IO,网络IO,我今天主要说一下对网络IO的理解,网络IO主要是socket套接字的读(read)、写(write),socket在Linux系统被抽象为流(stream)。 网络IO模型 在Unix/Linux系统下,IO分为两个不同阶段: 等待数据准备好 从内核向进程复制数据 阻塞式I/O 阻塞式I/O(blocking I/O)是最简单的一种,默认情况下,socket 套接字的系统调用都是阻塞的,我以recv/recvfrom 理解一下网络IO的模型。当应用层的系统调用recv/recvfrom时,开启Linux的系统调用,开始准备数据,然后将数据从内核态复制到用户态,然后通知应用程序获取数据,整个过程都是阻塞的。两个阶段都会被阻塞。 阻塞I/O模型 图片来源于《Unix网络编程卷1》 阻塞I/O下开发的后台服务,一般都是通过多进程或者线程取出来请求,但是开辟进程或者线程是非常消耗系统资源的,当大量请求时,因为需要开辟更多的进程或者线程有可能将系统资源耗尽,因此这种模式不适合高并发的系统。 非阻塞式I/O 非阻塞IO(non-blocking I/O)在调用后,内核马上返回给进程,如果数据没有准备好,就返回一个error ,进程可以先去干其他事情,一会再次调用,直到数据准备好为止,循环往返的系统调用的过程称为轮询(pool)

一文让你读懂懂阻塞、非阻塞、同步、异步IO

倖福魔咒の 提交于 2019-12-06 01:24:02
介绍 在谈及网络IO的时候总避不开阻塞、非阻塞、同步、异步、IO多路复用、select、poll、epoll等这几个词语。在面试的时候也会被经常问到这几个的区别。本文就来讲一下这几个词语的含义、区别以及使用方式。 Unix网络编程一书中作者给出了五种IO模型: 1、BlockingIO - 阻塞IO 2、NoneBlockingIO - 非阻塞IO 3、IO multiplexing - IO多路复用 4、signal driven IO - 信号驱动IO 5、asynchronous IO - 异步IO 这五种IO模型中前四个都是同步的IO,只有最后一个是异步IO。信号驱动IO使用的比较少,重点介绍其他几种IO以及在Java中的应用。 阻塞、非阻塞、同步、异步以及IO多路复用 在进行网络IO的时候会涉及到用户态和内核态,并且在用户态和内核态之间会发生数据交换,从这个角度来说我们可以把IO抽象成两个阶段:1、用户态等待内核态数据准备好,2、将数据从内核态拷贝到用户态。之所以会有同步、异步、阻塞和非阻塞这几种说法就是根据程序在这两个阶段的处理方式不同而产生的。 同步阻塞 当在用户态调用read操作的时候,如果这时候kernel还没有准备好数据,那么用户态会一直阻塞等待,直到有数据返回。当kernel准备好数据之后,用户态继续等待kernel把数据从内核态拷贝到用户态之后才可以使用

android6.0系统Healthd深入分析

女生的网名这么多〃 提交于 2019-12-05 17:36:08
概述 Healthd是android4.4之后提出来的一种中介模型,该模型向下监听来自底层的电池事件,向上传递电池数据信息给Framework层的BatteryService用以计算电池电量相关状态信息,BatteryServcie通过传递来的数据来计算电池电量显示,剩余电量,电量级别等信息,如果收到过温报警或者严重低电报警等信息,系统会直接关机,保护硬件。 主模块处理流程 Healthd模块代码是在system/core/healthd/,其模块入口在healthd的main函数,函数代码如下: int main(int argc, char **argv) { int ch; int ret; klog_set_level(KLOG_LEVEL); healthd_mode_ops = &android_ops; if (!strcmp(basename(argv[0]), "charger")) { healthd_mode_ops = &charger_ops; } else { while ((ch = getopt(argc, argv, "cr")) != -1) { switch (ch) { case 'c': healthd_mode_ops = &charger_ops; break; case 'r': healthd_mode_ops =