【c++】26.浅谈“事件驱动”、select、poll、epoll

浅谈“事件驱动”

1.通常,我们设计一个事件处理模型的程序有两种思路:
  • 一种是通过轮询的方式;
  • 一种通过事件驱动的方式,事件驱动方式也被称为消息通知方式。

下面举个简单收信的例子,来说明两种实现方式的不同:

  • (1) 传统的邮件,邮递员把它放到你家的邮箱里。因为你不知道什么时候有邮件,所以你要经常去检查邮箱,最近到底有没有邮件。这就是所谓的轮询方式,你要时常去检查,有没有发生事件发生,当你检查到有事件发生时,你采取相应措施,处理相关事件。
  • (2)现代的电子邮件,你不用自己去查看邮箱,如果有新邮件,电脑会给你发消息,提示你有新邮件,然后你去查看邮箱。这就是所谓的事件驱动(消息通知),你不用去关心事件什么时候发生,当有事件发生时,会有人通知你,事件发生了,然后你再采取相应的措施,处理相关事件。

通过上面的例子,可以看出,轮询的最大的弊端在于,你要做许多无谓的检查,具体到程序中,就是会有CPU资源的浪费,换言之,就是CPU利用率不高。而事件驱动,就很好的解决了这个问题。不过事件驱动的缺点在于,模型较为复杂,程序写起来会比较复杂,但是,一旦掌握了事件驱动这种模型的基本设计思路,必定能达到事半功倍的效果。

2.网络服务器设计过程中用到的 事件驱动模型

在这里我要说一说,通常的网络服务器设计过程中的事件驱动模型,希望能对需要帮助的朋友一点小小的帮助,这将是我很乐意看到的。

通常,高吞吐大并发网络服务器,都会采用事件驱动模型,其优点就是CPU利用率高,写出来的程序效率比较高。
通常,我们会用select/poll/epoll,这些由系统提供的I/O复用API来实现事件驱动模型。

网络程序中的事件,通常可以分为三类:

  • 一类是可读事件(数据已到达内核,上层应用可以调用相关读接口进行数据读取);
  • 一类是可写事件(内核的写缓冲区有空余,上层应用可以调用相关写接口进行数据写入);
  • 一类是异常(或出错)事件(发生了异常情况,需要进行异常处理)。

selectpoll, 与epoll相比,当并发数比较大的时候,性能差别会比较大,主要是因为内核通知事件的方式不同。

  • selectpoll中,内核只是在通知有多少个fd上发生了事件,并在相应的fd上做了标记,上层应用要想知道具体是那个fd上发生了什么事件,就必须去遍历整个fd的集合。

  • 而在epoll中,操作系统通知事件的方式是,把有事件发生的fd集合返回给上层应用,这样就不需要再去做无谓的遍历了。尤其在并发数比较大(fd集合中fd个数多)的时候,它们之间的性能差别还是挺大的。因此,性能要求比较高的网络服务器的实现,大多都使用epoll

下图所示是一种比较常见的事件驱动(消息通知)模型的简单实现:


上图中,EventMonitor是用来从操作系统获取事件的线程,EventProcessor是实际来处理事件的线程。

EventMonitor中调用select/poll/epoll_wait来获取事件,然后把发生的事件,以消息的方式通知给EventProcessorEventProcessor收到消息后,处理所发生的事件。

这里EventProcessor可以有多个,同一个fd的上事件,一般在同一个EventProcessor上处理。这样,EventMonitor的工作就是获取事件,是比较轻量级的,重量级的运算处理工作都由EventProcessor来处理,通过调整EventProcessor的个数,提高CPU的利用效率,从而提高整个程序的性能。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值