IO多路复用之epoll篇
前言
前两篇分别介绍了IO多路复用的select()和poll()。
select()解决了传统的网络编程中,一个线程只能服务一个客户端连接的问题,但是最多只能同时监听1024个文件描述符,并且效率比较低。poll()解决了select()监听文件描述符个数限制的问题,但是并没有解决效率的问题。
本篇介绍epoll(),既解决了描述符个数限制的问题,又解决了效率问题。
前两篇分别介绍了IO多路复用的select()和poll()。
select()解决了传统的网络编程中,一个线程只能服务一个客户端连接的问题,但是最多只能同时监听1024个文件描述符,并且效率比较低。poll()解决了select()监听文件描述符个数限制的问题,但是并没有解决效率的问题。本篇介绍epoll(),既解决了描述符个数限制的问题,又解决了效率问题。
前一篇介绍了IO多路复用中的select(),但是select()的缺点很明显,监控描述符的个数不能超过1024个,所以后来为了解决这个问题,引入了poll(),理论上poll()监听的描述符个数不受限制,但是实际能监控的描述符个数和机器自身的硬件配置有关系。
在Linux系统下,select()为最早支持IO多路复用的系统调用。该接口相比poll()、epoll()来说,更为简单,但是效率较低,而且最大只支持FD_SETSIZE(1024)个描述符。如果对并发数量的要求高于1024,请考虑使用poll()或者epoll()。
在联网的Linux环境上安装PostgreSQL、PostGIS,可能就是几句命令的事儿,相关的依赖可以自动安装,但是在离线的环境下安装,需要先编译安装各个依赖。
本文以麒麟服务器4.0.2为测试环境,离线编译安装PostgreSQL 12.2和PostGIS 3.0.5。有联网的环境,安装方法请参考其他教程。
因为工作中开发以C++为主,python不太常用,所以每次学过之后,很快就忘记了。
写这篇博客的目的,是为了记录python的基本语法,每当用到的时候可以速查。
当然这篇不是python的入门教程,更偏向于python与C++之间的差异。
Reactor为Douglas C. Schmidt提出的一种设计模式,翻译为反应器模式,或者分发器模式。很多开源的项目都使用了此设计模式,如muduo、Redis、Nginx、Netty。
本文假定读者有一定的C/C++的网络编程经验,并且对IO多路复用有一定的了解,如select、poll、epoll等函数。
本文主要面向对Reactor有一定了解,但是并不知道C++类应该如何设计的读者。
Libevent 的 evbuffer 功能实现了一个字节队列,针对将数据添加到末尾和从前面删除数据进行了优化。
Evbuffers 通常用于执行缓冲网络 IO 的“缓冲”部分。它们不提供调度 IO 或在 IO 准备好时触发 IO 的功能:这是 bufferevents 所做的功能。
这一章节讲述一些bufferevent的高级特性,对初学者来说并不是必须的。如果你刚刚学习如何使用bufferevent,可以跳过本章节。
有时,你需要编写一个与自己通信的网络程序。例如,您可以编写一个程序来通过某个协议建立隧道用户连接,而该程序有时也希望通过该协议建立自己的连接隧道。当然,您可以通过打开与您自己的侦听端口的连接并让您的程序使用自己来实现这一点,但是,让您的程序通过网络堆栈与自己对话会浪费资源。
相反,您可以创建一对成对的bufferevent,以便写入一个的所有字节都被另一个接收(反之亦然),但不使用socket。
大多数时候,除了响应事件之外,应用程序还希望执行一些数据缓冲。例如,当我们想要写入数据时,通常的模式运行如下:
<event2/util.h>头文件定义了许多函数,您可能会发现这些函数对使用 Libevent 实现可移植应用程序很有帮助。 libevent 在内部使用这些类型和函数。
event是libevent的基本操作单元,每一个event代表一系列条件的集合,包括:
在你使用libevent的函数之前,你应该先创建一个或多个event_base结构,每一个event_base拥有event集合,并且轮询它们看哪个处于active状态。