事件驱动模型

事件驱动模型

求助编辑百科名片
事件驱动模型   
事件驱动模型
鼠标的一个点击,移动,键盘的按键按下等等操作,都是对应操作系统的一个事件,然后应用程序接受你的操作进行处理

目录

select
poll
epoll
通常,我们写服务器处理模型的程序时,有以下几种模型:
(1)每收到一个请求,创建一个新的进程,来处理该请求;
(2)每收到一个请求,创建一个新的线程,来处理该请求;
(3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求
上面的几种方式,各有千秋,第(1)中方法,由于创建新的进程的开销比较大,所以,会导致服务器性能比较差,但实现比较简单。第(2)种方式,由于要涉及到线程的同步,有可能会面临死锁等问题。第(3)种方式,在写应用程序代码时,逻辑比前面两种都复杂。综合考虑各方面因素,一般普遍认为第(3)种方式是大多数 网络服务器采用的方式,这也是本文讨论的重点—事件驱动处理库。

编辑本段select

select在linux和windows平台上都支持的,接口基本上相同,但参数的含义略有不同。通常,使用select库的步骤是:
(1)创建所关注的事件的描述符集合(fd_set),对于一个描述符,可以关注其上面的读(read)、写(write)、异常(exception)事件,所以通常,要创建三个fd_set, 一个用来收集关注读事件的描述符,一个用来收集关注写事件的描述符,另外一个用来收集关注异常事件的描述符集合。
(2)调用select(),等待事件发生。这里需要注意的一点是,select的阻塞与是否设置非阻塞I/O是没有关系的。select的原型如下所示:
int select(int  nfds ,
fd_set*  readfds ,
fd_set*  writefds ,
fd_set*  exceptfds,
const struct timeval*  timeout
其中,最后一个参数 timeout,可以设置select等待的时间。如果该值设置为0,那么,select()在有事件发生的时候就立即返回。如果该值不为0,那么,select()会等待指定的时间,然后再返回。select()的返回值指定了发生事件的fd个数。
(3)轮询所有fd_set中的每一个fd ,检查是否有相应的事件发生,如果有,就进行处理。

编辑本段poll

poll库是在linux2.1.23中引入的,windows平台不支持poll. poll与select的基本方式相同,都是先创建一个关注事件的描述符的集合,然后再去等待这些事件发生,然后再轮询描述符集合,检查有没有事件发生,如果有,就进行处理。因此,poll有着与select相似的处理流程:
(1)创建描述符集合,设置关注的事件
(2)调用poll(),等待事件发生。下面是poll的原型:
int poll(struct pollfd * fds, nfds_t  nfds, int  timeout);
类似select,poll也可以设置等待时间,效果与select一样。
(3)轮询描述符集合,检查事件,处理事件。
在这里要说明的是,poll与select的主要区别在与,select需要为读、写、异常事件分配创建一个描述符集合,最后 轮询的时候,需要分别轮询这三个集合。而poll只需要一个集合,在每个描述符对应的结构上分别设置读、写、异常事件,最后 轮询的时候,可以同时检查三种事件。

编辑本段epoll

epoll是和上面的poll和select不同的一个事件驱动库,它是在linux 2.5.44中引入的,它属于poll的一个变种。上面的poll和select库,它们的最大的问题就在于效率。它们的处理方式都是创建一个事件列表,然后把这个列表发给 内核,返回的时候,再去 轮询检查这个列表,这样在描述符比较多的应用中,效率就显得比较低下了。一种比较好的做法是,把描述符列表交给 内核,一旦有事件发生,内核把发生事件的描述符列表通知给进程,这样就避免了 轮询整个描述符列表。epoll就是这样一种模型。下面对epoll的使用进行说明:
(1).创建一个epoll描述符,调用epoll_create()来完成,epoll_create()有一个整型的参数size,用来告诉 内核,要创建一个有size个描述符的事件列表(集合)
int epoll_create(int  size)
(2).给描述符设置所关注的事件,并把它添加到内核的事件列表中去,这里需要调用epoll_ctl()来完成。
int epoll_ctl(int  epfd, int  op, int  fd, struct epoll_event * event)
这里op参数有三种,分别代表三种操作:
a. EPOLL_CTL_ADD,  把要关注的描述符和对其关注的事件的结构,添加到内核的事件列表中去
b. EPOLL_CTL_DEL,把先前添加的描述符和对其关注的事件的结构,从 内核的事件列表中去除
c. EPOLL_CTL_MOD,修改先前添加到 内核的事件列表中的描述符的关注的事件
(3). 等待 内核通知事件发生,得到发生事件的描述符的结构列表,该过程由epoll_wait()完成。得到事件列表后,就可以进行事件处理了。
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)
在使用epoll的时候,有一个需要特别注意的地方,那就是epoll触发事件的文件有两种方式:
(1)Edge Triggered(ET),在这种情况下,事件是由数据到达边界触发的。所以要在处理读、写的时候,要不断的调用read/write,直到它们返回EAGAIN,然后再去epoll_wait(),等待下次事件的发生。这种方式适用要遵从下面的原则:
a. 使用非阻塞的I/O;b.直到read/write返回EAGAIN时,才去等待下一次事件的发生。
(2)Level Triggered(LT), 在这种情况下,epoll和poll类似,但处理速度上可能比poll快。在这种情况下,只要有数据没有读、写完,调用epoll_wait()的时候,就会有事件被触发。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值