linux下epoll架构

合集下载

百万用户同时在线游戏服务器架构实现

百万用户同时在线游戏服务器架构实现

百万用户在线网络游戏服务器架构实现一、前言事实上100万游戏服务器,在面对大量用户访问、高并发请求方面,基本的解决方案集中在这样几个环节:使用高性能的服务器、高效率的编程语言、高性能的数据库、还有高性能的架构模型。

但是除了这几个方面,还没法根本解决面临的高负载和高并发问题。

当然用户不断地追求更高的机器性能,而升级单一的服务器系统,往往造成过高的投入和维护成本,性价比大大低于预期。

同时全天候的可用性的要求也不能满足要求,如果服务器出现故障则该项服务肯定会终止。

所以单独追求高性能的服务器不能满足要求,目前基本的解决方案是使用集群技术做负载均衡,可以把整体性能不高的服务器做成高可扩展性,高可用性,高性能的,满足目前的要求。

目前解决客户端和服务器进行底层通讯的交互的双向I/O模型的服务器的成熟方案。

1.windows下,比较成熟的技术是采用IOCP,完成端口的服务器模型。

2.Linux下,比较成熟的技术是采用Epoll服务器模型, Linux 2.6内核中提供的System Epoll为我们提供了一套完美的解决方案。

目前如上服务器模型是完全可以达到5K到20K的同时在线量的。

但5K这样的数值离百万这样的数值实在相差太大了,所以,百万人的同时在线是单台服务器肯定无法实现的。

而且目前几个比较成熟的开发框架,比如ICE,ACE等。

这样,当采用一种新的通信技术来实现通信底层时,框架本身就不用做任何修改了(或修改很少),而功能很容易实现,性能达到最优。

目前采用的ace框架个不错的选择方案,可以不受操作系统的影响,移植比较方便。

对于数据库选择可有许多成熟的方案,目前大多数选择的mysql Master/slave模式,以及oracle RAC方案。

基本可以满足目前的要求,但具体的瓶颈不是在数据库本身,应该还是硬件磁盘I/O的影响更大些。

建议使用盘阵。

这有其他成熟的方案,比如采用NAS解决分布数据存储。

其实最为关键的是服务器的架构和实现,数据流量的负载均衡,体系的安全性,关键影响度,共享数据的处理等等多个方面对100万用户的数据处理有影响,所以都要全面的考虑。

linux下epoll使用详解

linux下epoll使用详解

LINUXepoll使用详解●epoll简介:在linux的网络编程中,很长的时间都在使用select来做事件触发。

在linux新的内核中,有了一种替换它的机制,就是epoll。

相比于select,epoll最大的好处在于它不会随着监听fd数目的增长而降低效率。

因为在内核中的select实现中,它是采用轮询来处理的,轮询的fd数目越多,自然耗时越多。

并且,在linux/posix_types.h头文件有这样的声明:#define __FD_SETSIZE 1024表示select最多同时监听1024个fd,当然,可以通过修改头文件再重编译内核来扩大这个数目,但这似乎并不治本。

●epoll接口函数1.int epoll_create(int size)创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。

这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值。

需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd 的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。

2.int epoll_ctl(int epfd, int op, int fd, struct epoll_event*event)epoll的事件注册函数,它不同与select()是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。

第一个参数是epoll_create()的返回值,第二个参数表示动作,用三个宏来表示:EPOLL_CTL_ADD:注册新的fd到epfd中;EPOLL_CTL_MOD:修改已经注册的fd的监听事件;EPOLL_CTL_DEL:从epfd中删除一个fd;第三个参数是需要监听的fd,第四个参数是告诉内核需要监听什么事,struct epoll_event结构如下:typedef union epoll_data {void *ptr;int fd;__uint32_t u32;__uint64_t u64;} epoll_data_t;struct epoll_event {__uint32_t events; /* Epoll events */epoll_data_t data; /* User data variable */};events可以是以下几个宏的集合:EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);EPOLLOUT:表示对应的文件描述符可以写;EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);EPOLLERR:表示对应的文件描述符发生错误;EPOLLHUP:表示对应的文件描述符被挂断;EPOLLET:将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。

epoll 用法

epoll 用法

epoll 用法
epoll是一种事件通知机制,用于在 Linux 上实现高效的 I/O 多路复用。

它可以同时监视多个文件描述符,当其中任意一个描述符就绪时,就会通知应用程序进行相应的处理。

epoll 的使用方法主要分为以下几步:
1. 创建 epoll 实例:调用 epoll_create 函数创建一个 epoll 实例,它返回一个文件描述符,用于后续的操作。

2. 添加事件监听:调用 epoll_ctl 函数将需要监听的文件描述符添加到 epoll 实例中,同时指定需要监听的事件类型,如可读、可写等。

3. 等待事件发生:调用 epoll_wait 函数等待事件的发生。

它会阻塞应用程序,直到有文件描述符就绪或者超时。

4. 处理事件:当 epoll_wait 返回时,应用程序需要根据返回的就绪事件列表进行相应的处理,如读取数据、写数据等。

需要注意的是,epoll 使用时需要结合非阻塞 I/O 来使用,以充分发挥其高效的特性。

epoll 的使用相对于传统的 select 和 poll 等方式更加高效,可以大大提高应用程序的性能和并发能力。

因此,在设计高并发网络应用程序时,epoll 是一个非常重要的工具。

- 1 -。

epoll 原理

epoll 原理

epoll 原理
epoll是Linux系统提供的一种高效I/O多路复用方式。

它采用事件驱动的方式实现I/O多路复用,可以同时监控多个文件描述符的状态,并在文件描述符就绪时通知应用程序进行读写操作。

与传统的select 和 poll 系统调用相比,epoll 具有更高的性能和更好的可扩展性。

epoll 基于内核中的事件驱动机制,通过注册回调函数实现对事件的监听和处理。

应用程序可以将一个或多个文件描述符注册到epoll 对象中,当所关注的文件描述符就绪时,内核会通知 epoll 对象,epoll 对象再调用应用程序注册的回调函数进行处理。

epoll 主要包含三个系统调用:epoll_create、epoll_ctl 和epoll_wait。

其中,epoll_create 用于创建 epoll 对象,epoll_ctl 用于向 epoll 对象中添加、修改或删除文件描述符,epoll_wait 则是阻塞等待 epoll 对象中的文件描述符就绪。

与 select 和 poll 不同的是,epoll 不需要在每次调用
epoll_wait 时重新向内核传递文件描述符集合,而是在注册文件描述符时将其添加到内核中的事件表中,这样每次调用 epoll_wait 时只需要从事件表中取出就绪的文件描述符即可,大大减少了内核与用户空间的数据交换次数,提高了系统的效率。

总之,epoll 是 Linux 平台上一种高效的 I/O 多路复用机制,采用事件驱动的方式实现对文件描述符的监控和处理。

它相对于传统的 select 和 poll 有更好的性能和可扩展性,是实现高并发网络编
程的重要工具之一。

c语言epoll详解

c语言epoll详解

c语言epoll详解摘要:1.简介- 什么是C 语言epoll- epoll 的优势2.epoll 原理- epoll 的工作机制- epoll 的事件处理3.epoll 的使用- 安装epoll 模块- 创建epoll 实例- 添加、修改、删除事件- 查询事件- 处理事件4.epoll 的例子- 简单的epoll 例子- 更复杂的epoll 例子5.epoll 的应用场景- 网络编程- 服务器开发正文:C 语言epoll 详解C语言epoll是一种高效的I/O事件处理机制,相较于传统的select和poll,epoll在性能上有很大的优势,因此被广泛应用于网络编程和服务器开发等领域。

1.简介epoll是Linux下的一种I/O事件处理机制,它能够实现对大量I/O进行监控,只有发生变化的I/O才会通知用户进程。

这使得用户进程可以更加高效地处理I/O事件,避免了不必要的上下文切换和资源浪费。

2.epoll 原理epoll 的工作机制类似于一个事件驱动的系统。

它包含一个内核模块和一个用户进程。

内核模块负责管理I/O 资源,用户进程通过epoll_create、epoll_ctl 等系统调用与内核模块进行交互,实现对I/O 资源的监控和事件处理。

当用户进程调用epoll_wait 时,内核模块会遍历所有注册的I/O 资源,检查它们的状态是否发生变化。

如果某个I/O 资源的状态发生了变化,内核模块就会将这个变化通知给用户进程。

用户进程可以根据收到的通知来执行相应的操作。

3.epoll 的使用要在C 语言中使用epoll,首先需要安装epoll 模块。

安装方法如下:```#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>MODULE_LICENSE("GPL");MODULE_AUTHOR("Your Name");MODULE_DESCRIPTION("An epoll module");module_init(epoll_init);module_exit(epoll_exit);```接下来,可以创建epoll 实例、添加、修改、删除事件以及查询事件。

c++ epoll原理

c++ epoll原理

c++ epoll原理在Linux系统中,epoll是一种高效的I/O多路复用机制,它提供了一种方便而高效的方法来监控文件描述符(文件、管道、socket 等)上的事件,如读、写、异常等。

在C语言编程中,epoll是Linux 的一种事件驱动的I/O机制,通过它可以对一个或多个文件或socket 描述符进行非阻塞性监控,对感兴趣的事件能以最快速度进行反应。

一、 epoll基本原理在Linux中,epoll基于内核的事件通知机制来实现。

在Linux 中,epoll是多路复用的一种机制,它提供了一个高效的监听机制,可以监听指定文件描述符上的事件(如可读、可写、异常等)的发生。

epoll使用一个文件/dev/epoll作为输入,这个文件是一个文件系统中的特殊文件,它是一个文件描述符的集合。

当一个进程打开/dev/epoll文件时,它就会得到一个文件描述符,这个文件描述符可以用来读取和写入/dev/epoll文件。

当有事件发生时,内核会通知进程。

二、 epoll事件类型epoll提供了多种事件类型,包括以下几种:1. EPOLLIN:表示可读事件。

当在监听的文件描述符上可读数据时,会触发此事件。

2. EPOLLOUT:表示可写事件。

当在监听的文件描述符上有可写的写入操作时,会触发此事件。

3. EPOLLERR:表示出现错误事件。

当在监听的文件描述符上发生错误时,会触发此事件。

4. EPOLLHUP:表示挂断事件。

当在监听的文件描述符上连接断开时,会触发此事件。

5. EPOLLET:表示是否使用非阻塞模式。

如果设置为非阻塞模式,当没有可读或可写事件时,epoll会返回0。

三、 epoll使用方法使用epoll时,首先需要初始化epoll_event结构体数组和打开要监听的/dev/epoll文件,并将文件描述符集合到该文件中。

然后可以不断读取该文件的读操作来获取发生的事件。

当发生事件时,需要调用相应的回调函数来处理事件。

linux epoll 实例

linux epoll 实例

linux epoll 实例epoll是Linux内核为处理大批量文件描述符而作了改进的poll(2),是LINUX下多路复用IO支持的一种机制,它基于事件驱动模型,用户把要发生的事件(就是文件描述符)放入内核的一个poll结构,文件描述符就放在一个数组中,每当一个有效I/O发生,加入到内核队列中,放到用户定义的epoll结构中,这个新发生的事件将立即传送给用户进程,在该进程的某一线程中,使用epoll_Wait()函数等待事件的发生,等待到发生的事件时,epoll会将发生的事件告诉用户程序,比如连接,数据可读等。

epoll的优势:1、内核利用epoll的重新把文件描述符放入有序的数据结构,比poll管理更为高效,更少的遍历处理全部的文件描述符;2、epoll模型支持IO多路复用,同时可以监听到数以千计的fd;3、epoll提供水平触发和边沿触发两种模式;4、epoll支持ET和LT两种类型;5、epoll实现轮询式监视,提升系统性能,使用更轻松和实时;在Linux中使用epoll时,首先need to initilize一个epoll实例,而epoll_create函数来完成这一初始化(epoll_create()的参数是数据要放入epoll的最大句柄数),epoll_create()返回的文件描述符(int类型),被用于后续的epoll操作;然后用epoll_ctl()来添加文件描述符至内核的epoll表头,最后,进程通过调用epoll_wait()来等待某个文件描述符因某种事件发生而Entry Ready状态,epoll_wait()阻塞等待,epoll函数会返回可以操作的文件描述符列表。

epoll能处理上千个fd事件不错过,但是也有其缺点,它不能实现即时通讯,新连接的处理是有延迟的,而且,如果epoll_wait()中断,它会只返回一个已就绪的fd,而不检查其它的fd.综上所述,epoll是LINUX下高效的多路复用IO编程的机制,它能处理上千个fd事件,用在Server开发中是一种正确选择,相对于select/poll很大提高了处理效率,且支持水平触发和边沿触发两种模式,也支持ET和LT两种类型。

linux中select、poll、epoll原理

linux中select、poll、epoll原理

linux中select、poll、epoll原理select、poll和epoll是Linux下常用的I/O多路复用技术,都用于实现高效的事件驱动型的网络编程。

1. select(选择)select是最古老的I/O多路复用机制,它通过在套接字上设置阻塞(阻塞方式)进行等待,一旦有文件描述符准备就绪(可读、可写等),则返回。

select使用fd_set集合来保存要监听的文件描述符,因此其监听的文件描述符数量受到系统给定的FD_SETSIZE限制。

select的实现原理是:在内核中创建一个称为“等待队列”的数据结构(fd_set),该队列保存了需要等待的文件描述符,当某个文件描述符就绪时,会通过和用户进程的映射表通知用户进程。

select通过轮询所有注册的文件描述符,检查哪些文件描述符已经准备好,并将准备好的文件描述符从用户态拷贝到内核态。

select的缺点是每次调用都需要轮询全部的注册文件描述符,效率较低。

2. poll(轮询)poll是在select的基础上进行改进的多路复用技术。

poll与select的最大区别在于,它没有限制文件描述符的数量,并且使用了一个pollfd结构体数组来保存每个文件描述符及其关注的事件。

poll在内核中创建一个称为“等待队列”的数据结构,该队列保存了需要等待的文件描述符,当某个文件描述符就绪时,会通过和用户进程的映射表通知用户进程。

poll的实现原理是:将用户进程注册要监听的文件描述符及其关注的事件存储在内核中的一个事件表中,当发生事件时,内核会将该事件存储在内核态的事件表中,并通知用户进程。

与select不同的是,poll只需在事件发生时拷贝某些信息到内核态,而不需要拷贝全部的文件描述符。

poll的缺点是,当注册的文件描述符数量较大时,每次调用poll都需要遍历整个事件表,效率较低。

3. epoll(事件通知)epoll是Linux特有的一种I/O多路复用机制,通过内核与用户空间的共享内存来实现高效的事件通知。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ssize_t n;
char line[MAXLINE];
socklen_t clilen;
struct epoll_event ev,events[20]; //声明epoll_event结构体的变量, ev用于注册事件, events数组用于回传要处理的事件
epfd=epoll_create(256); //生成用于处理accept的epoll专用的文件描述符,指定生成描述符的最大范围为256
<2> IO效率不随FD数目增加而线性下降
传统select/poll的另一个致命弱点就是当你拥有一个很大的socket集合,由于网络得延时,使得任一时间只有部分的socket是"活跃"的,而select/poll每次调用都会线性扫描全部的集合,导致效率呈现线性下降。但是epoll不存在这个问题,它只会对"活跃"的socket进行操作---这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。于是,只有"活跃"的socket才会主动去调用callback函数,其他idle状态的socket则不会,在这点上,epoll实现了一个"伪"AIO,因为这时候推动力在os内核。在一些benchmark中,如果所有的socket基本上都是活跃的---比如一个高速LAN环境,epoll也不比select/poll低多少效率,但若过多使用的调用epoll_ctl,效率稍微有些下降。然而一旦使用idle connections模拟WAN环境,那么epoll的效率就远在select/poll之上了。
等待事件的产生,类似于select()调用。参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。该函数返回需要处理的事件数目,如返回0表示已超时。
四、epoll具体使用方法
(1)epoll的接口非常简单,一共就三个函数:
1. int epoll_create(int size);
创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数,给出最大监听的fd+1的值。需要注意的是,当创建好epoll句柄后,它就是会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET:将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
serveraddr.sin_family = AF_INET;
效率非常高,在并发,大流量的情况下,会比LT少很多epoll的系统调用,因此效率高。但是对编程要求高,需要细致的处理每个请求,否则容易发生丢失事件的情况。
在许多测试中我们会看到如果没有大量的idle -connection或者dead-connection,epoll的效率并不会比select/poll高很多,但是当我们遇到大量的idle- connection(例如WAN环境中存在大量的慢速连接),就会发现epoll的效率大大高于select/poll。
<4>内核微调
这一点其实不算epoll的优点,而是整个linux平台的优点。也许你可以怀疑linux平台,但是你无法回避linux平台赋予你微调内核的能力。比如,内核TCP/IP协议栈使用内存池管理sk_buff结构,可以在运行期间动态地调整这个内存pool(skb_head_pool)的大小---通过echo XXXX>/proc/sys/net/core/hot_list_length来完成。再比如listen函数的第2个参数(TCP完成3次握手的数据包队列长度),也可以根据你平台内存大小来动态调整。甚至可以在一个数据包面数目巨大但同时每个数据包本身大小却很小的特殊系统上尝试最新的NAPI网卡驱动架构。
#define LISTENQ 20
#define SERV_PORT 5555
#define INFTIM 1000
void setnonblocking(int sock)
{
int opts;
opts=fcntl(sock,F_GETFL);
if(opts<0)
{
perror("fcntl(sock,GETFL)");
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里
3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
(d)网络监视线程启动循环,epoll_wait()等待epoll事件发生。
(e)如果epoll事件表明有新的连接请求,则调用accept()函数,将用户socket描述符添加到epoll_data联合体,同时设定该描述符为非阻塞,并在epoll_event结构中设置要处理的事件类型为读和写,工作方式为epoll_ET。
2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epoll的事件注册函数,它不同与select()是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。第一个参数是epoll_create()的返回值,第二个参数表示动作,用三个宏来表示:
ev.data.fd=listenfd; //设置与要处理的事件相关的文件描述符
ev.events=EPOLLIN | EPOLLET; //设置要处理的事件类型
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); //注册epoll事件
bzero(&serveraddr, sizeof(serveraddr));
一、Epoll简介
epoll是Linux内核为处理大批量句柄而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著减少程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。
因为它不会复用文件描述符集合来传递结果而迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。
二、Epoll优点
<1>支持一个进程打开大数目的socket描述符(FD)
epoll没有传统select/poll的“一个进程所打开的FD是有一定限制”的这个限制,它所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于select所支持的2048。举个例子,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。
(f)如果epoll事件表明socket描述符上有数据可读,则将该socket描述符加入可读队列,通知接收线程读入数据,并将接收到的数据放入到接收数据的链表中,经逻辑处理后,将反馈的数据包放入到发送数据链表中,等待由发送线程发送。
例子代码:
#include <iostream>
#include <sys/socket.h>
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
events可以是以下几个宏的集合:
EPOLLIN:表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLL_CTL_ADD:注册新的fd到epfd中;
EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
EPOLL_CTL_DEL:从epfd中删除一个fd;
第三个参数是需要监听的fd,第四个参数是告诉内核需要监听什么事,struct epoll_event结构如下:
struct epoll_event {
效率会低于ET触发,尤其在大并发,大流量的情况下。但是LT对代码编写要求比较低,不容易出现问题。LT模式服务编写上的表现是:只要有数据没有被获取,内核就不断通知你,因此不用担心事件丢失的情况。
ET:边缘触发
是高速工作方式,只支持no-block socket。在这种模式下,当描述符从未就绪变为就绪时,内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪,并且不会再为那个文件描述符发送更多的就绪通知,直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如,你在发送,接收或者接收请求,或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK错误)。但是请注意,如果一直不对这个fd作IO操作(从而导致它再次变成未就绪),内核不会发送更多的通知(only once)。
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
相关文档
最新文档