返回顶部
首页 > 资讯 > 操作系统 >Linux高性能I/O框架库Libevent怎么用
  • 450
分享到

Linux高性能I/O框架库Libevent怎么用

2023-06-27 11:06:32 450人浏览 独家记忆
摘要

本文小编为大家详细介绍“linux高性能I/O框架库Libevent怎么用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Linux高性能I/O框架库Libevent怎么用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知

本文小编为大家详细介绍“linux高性能I/O框架库Libevent怎么用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Linux高性能I/O框架库Libevent怎么用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

Linux服务器程序必须处理的三类事件:

  • I/O事件

  • 信号

  • 定时事件

在处理这三类事件时我们通常需要考虑如下三个问题:

  • 统一事件源。很明显,统一处理这三类事件既能使代码简单易懂,又能避免一些潜在的逻辑错误。

  • 可移植性。不同的操作系统具有不同的I/O复用方式,比如Solarisdev/poll文件,FressBSDkqueue机制,Linuxepoll系统调用

  • 并发编程的支持,在多进程和多线程环境下,我们需要考虑各执行实体如何协同处理客户连接、信号和定时器,以避免竞态条件。

幸运的是,开源社区提供了很多优秀的I/O框架库,他们不仅解决了上述问题,让开发者可以将精力完全放在程序的逻辑上,而且稳定性、性能等各方面都相当出色。而Libevent就是其中相对轻量级的框架库。

I/O框架库概述

I/O框架库以库函数的形式,封装了较为底层的系统调用,给应用程序提供了一组更便于使用的接口。这些库函数往往比程序员自己实现的同样功能的函数更合理、更高效、且更健壮。因为它们经受住了真实网络环境下的高压测试,以及时间的考验。

各种I/O框架库的实现原理基本相似,要么以Reactor模式实现,要么以Procator模式实现(高性能服务器程序框架 - 两种高效的事件处理模式),要么同时以这两种模式实现。举例来说,基于Reactor模式的I/O框架库包含如下几个组件:

  • 句柄Handle

  • 事件多路分发器EventDemultiplexer

  • 事件处理器Eventhandler

  • 具体的事件处理器ConcreteEventHandler

  • Reactor

  1. 句柄: I/O框架库要处理的对象,即I/O事件、信号和定时事件,统一称为事件源。一个事件源通常和一个句柄绑定在一起。句柄的作用是,当内核检测到就绪事件时,它将通过句柄来通知应用程序这一事件。在Linux环境下,I/O事件对应的句柄是文件描述符,信号事件对应的句柄就是信号值。

  2. 事件多路分发器:事件的到来是随机的、异步的。我们无法预知程序何时收到一个客户连接请求,又亦活收到一个暂停信号。所以程序需要循环地等待并处理事件,这就是事件循环。在事件循环中,等待事件一般使用I/O复用技术来实现。I/O框架库一般将系统支持的各种I/O复用系统调用封装成统一的接口,称为事件多路分发器。事件多路分发器的demultiplex方法是等待事件的核心函数,其内部调用的是selectpollepoll_wait等函数。此外事件多路分发器还需实现reGISter_eventremove_event方法,以供调用者往事件多路分发器中添加事件和从事件多路分发器中删除事件。

  3. 事件处理器和具体时间处理器:事件处理器执行事件对应的业务逻辑。它通常包含一个或多个handle_event回调函数,这些回调函数在事件循环中被执行。I/O框架库提供的事件处理器通常是一个接口,用户需要继承它来实现自己的事件处理器,即具体事件处理器。因此,事件处理器中的回调函数一般被声明为需函数,以支持用户的扩展。此外,事件处理器一般还提供一个get_handle方法,它返回与该事件处理器关联的句柄。那么事件处理器和句柄有什么关系?当时间多路分发器检测到有事件发生时,它是通过句柄来通知应用程序的。因此,我们必须将事件处理器和句柄绑定,才能在事件发生时获取到正确的事件处理器。

  4. Reactor:Reactor是I/O框架的核心。它提供的几个主要方法是:

    • handle_events:该方法执行事件循环。它重复如下过程:等待事件,然后依次处理所有就绪事件对应的事件处理器。

    • register_handler: 该方法调用事件多路分发器的register_event方法来往事件多路分发器中注册一个事件。-remove_handler:该方法调用事件多路分发器的remove_event方法来往删除事件多路分发器中注册一个事件。

Libevent源码分析

Libevent是开源社区的一款高性能的I/O框架库,具有如下特点:

  • 跨平台支持

  • 统一事件源

  • 线程安全

  • 基于Reactor模式的实现

(推荐微课:Linux微课)

一个实例

下面是用Libevent库实现的一个“Hello World”程序。

include <sys/signal.h>

#include <event2/event.h>void signal_cb(int fd, short event, void *arGC){    struct event_base* base = (event_base*)argc;    struct timeval delay = {2, 0};    printf("Caught an interrupt signal; exiting cleanly in two seconds....\n");    event_base_loopexit(base, &delay);}void timeout_cb(int fd, short event, void* argc){    printf("timeout\n");}int main(int argc, char const *argv[]){    struct event_base* base = event_base_new();    struct event* signal_event = evsignal_new(base, SIGINT, signal_cb, base);    event_add(signal_event, NULL);    timeval tv = {1, 0};    struct event* timeout_event = evtimer_new(base, timeout_cb, NULL);    event_add(timeout_event, &tv);    event_base_dispatch(base);    event_free(timeout_event);    event_free(signal_event);    event_base_free(base);    return 0;}

上述代码虽然简单,但却基本描述了Libevent库的主要逻辑:

  1. 调用event_base_new函数创建event_base对象。一个event_base相当于一个Reactor实例。

  2. 创建具体的事件处理器,并设置它们所从属的Reactor实例。evsignal_newevtimer_new分别用于创建信号事务处理器和定时事件处理器。

define evsignal_new(b, x, cb, arg)  

    event_new((b), (x), EV_SIGNAL|EV_PERSIST, (cb), (arg))#define evtimer_new(b, cb, arg)     event_new((b), -1, 0, (cb), (arg))

可见,他们的统一入口是event_new函数,即用于创建通用事件处理器的函数,定义如下:

event_new(struct event_base base, evutil_Socket_t fd, short events, void (cb)(evutil_socket_t, short, void ), void arg)其中,base参数指定行

其中:

  • base参数指定新创建的事件处理器从属的Reactor

  • fd参数指定与事件处理器关联的句柄。创建I/O事件处理器时,应该给fd参数传递文件描述符;创建信号事件处理器时,应该给fd参数传递信号值,比如之前实例代码中的SIGINT;创建定时事件处理器时则应该给fd参数传递-1

  • events参数指定事件类型,定义如下:

    #define EV_TIMEOUT  0x01       #define EV_READ     0x02             #define EV_WRITE    0x04            #define EV_SIGNAL   0x08           #define EV_PERSIST  0x10             #define EV_ET       0x20

上述代码中,EV_PERSIST的作用是:事件被触发后,自动重新对这个event调用event_add函数。

  • cb参数指定目标事件对应的回调函数,相当于事件处理器handle_event方法.

  • arg则是Reactor传递给回调函数的参数。

event_new函数成功时返回一个event类型的对象,也就是Libevent的事件处理器。Libevent用单词“event”来描述事件处理器,而不是事件,所以约定如下:

  • 事件指的是一个句柄上绑定的事件,比如文件描述符 0 上的可读事件

  • 事件处理器,也就是event结构提类型的对象,除了包含事件必须具备的两个要素(句柄和事件类型)外,还有很多其他成员,比如回调函数

  • 事件由事件多路分发器管理,事件处理器则由事件队列管理,事件队列包括多种,比如event_base中的注册事件队列。

  • 事件循环对一个被激活事件(就绪事件)的处理,指的是执行该事件对应的事件处理器中的回调函数。

  1. 调用event_add函数,将事件处理器添加到注册事件队列中,并将该事件处理器对应的事件添加到事件多路分发器中。even_add函数相当于Reactor中的register_handler方法。

  2. 调用event_base_dispatch函数来执行事件循环

  3. 事件循环结束后,使用*_free系列释放系统资源

(推荐课程:Linux就该这么学)

源代码组织结构

  • 头文件目录include/event2。该目录是自Libevent主板本升级到2.0之后引入的,是提供给应用程序使用的,比如event.h头文件是核心函数,Http.h头文件提供HTTP协议相关服务,rpc.h头文件提供远程过程调用支持。

  • 源码根目录下的头文件。这些头文件分为两类:

  • 一类是对include/event2目录下的部分头文件的包装

  • 另外一类是供Libevent内部使用的辅助性头文件,它们的文件名都具有*-internal.h的形式。

  • 通用数据目录compat/sys。该目录下仅有一个文件----queue.h。它封装了跨平台的基础数据结构,包括单向链表、双向链表、队列、尾队列和循环队列。

  • sample目录。提供一些示例代码

  • test目录。提供一次额测试代码

  • WIN32-Code。提供windows平台上的一些专用代码。

  • event.c文件。该文件时间Libevent的整体框架,主要是eventevent_base两个结构体的相关操作。

  • debpoll.ckqueue.cevport.cselect.cwin32select.cpoll.cepoll.c文件。它们分别封装了如下I/O复用机制:/dev/pollkqueueevent portsPOSIX selectWindows selectpollepoll。这些文件的主要内容相似,都是针对结构体eventop所定义的接口函数的具体实现。

  • minheap-internal.h:该文件实现了一个事件堆,以提供对定时事件的支持。

  • signal.c:提供对信号的支持。其内容也是针对结构体eventop所定义的接口函数的具体实现

  • evmap.c文件:它维护句柄(文件描述符或信号)与时间处理器的映射关系

  • event_tagging.c:提供往缓冲区中添加标记数据,比如一个正数,以及从缓冲区中读取标记数据的函数

  • event_iocp文件:提供对Windows ioCP(Input/Output Completion Port,输入输出完成端口)的支持

  • buffer*.c文件:提供对网络I/O缓冲的控制,包括:输入输出数据过滤,传输速率限制,使用SSL(Secure Sockets Layer)协议对应用数据进行保护,以及零拷贝文件传输等。

  • evthread*.c文件:提供对多线程的支持

  • listener.c:封装了对监听socket的操作,包括监听连接和接受连接

  • logs.c文件。它是Libevent日志文件系统

  • evutil.cevutil_rand.cstrlcpy.carc4random.c文件:提供了一些基本操作,比如生成随机数、获取socket地址信息、读取文件、设置socket属性等

  • evdns.chttp.cevrpc.c地址信息:分别提供了对DNS协议、HTTP协议和RPC(Remote Procddure Call,远程过程调用)协议的支持

  • epoll_sub.c文件,该文件未见使用

在整个源码中,event-internal.hinclude/event2/event_struct.hevent.cevmap.c等4个文件最为重要。它们定义了eventevent_base结构体,并实现了这两个结构体的相关操作。

读到这里,这篇“Linux高性能I/O框架库Libevent怎么用”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网操作系统频道。

--结束END--

本文标题: Linux高性能I/O框架库Libevent怎么用

本文链接: https://lsjlt.com/news/309892.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Linux高性能I/O框架库Libevent怎么用
    本文小编为大家详细介绍“Linux高性能I/O框架库Libevent怎么用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Linux高性能I/O框架库Libevent怎么用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知...
    99+
    2023-06-27
  • 怎么理解I/O性能
    本篇内容主要讲解“怎么理解I/O性能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解I/O性能”吧!为了理解I/O性能,你必须要详细了解存储文件的存储层次...
    99+
    2024-04-02
  • 怎么更改Linux I/O调度器来调整性能
    这篇文章主要讲解了“怎么更改Linux I/O调度器来调整性能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么更改Linux I/O调度器来调整性能”吧!为了从 Linux 服务器榨取尽可...
    99+
    2023-06-16
  • Cassandra的磁盘I/O性能怎么优化
    要优化Cassandra的磁盘I/O性能,可以考虑以下几个方面: 使用SSD硬盘:Solid State Drive (SSD)硬...
    99+
    2024-05-11
    Cassandra
  • Linux高性能服务器处理框架12步走
    终于开始学习epoll了,虽然不明白的地方还是很多,但从理论到实践,相信自己动手去写一个具体的框架后,一切会清晰很多。1、首先需要一个内存池,目的在于:...
    99+
    2023-06-05
  • 怎么深入理解Linux高性能网络架构
    本篇文章为大家展示了怎么深入理解Linux高性能网络架构,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。 1. 落寞的小黑上周北京很冷,周五晚上大白下班奔地铁站,收到了好基友小黑的微信:于是...
    99+
    2023-06-15
  • .Net性能测试框架Crank怎么使用
    这篇文章主要介绍“.Net性能测试框架Crank怎么使用”,在日常操作中,相信很多人在.Net性能测试框架Crank怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”.Net性能测试框架Crank怎么使用...
    99+
    2023-06-21
  • Gin-高性能 Golang Web框架的介绍和使用
    偶遇 Gin 我之前一直在使用 Beego 框架来做应用的 Api,因为它的写法跟 PHP 的 MVC 一样,上手简单,所以对它的表现还算满意。用的久了,发现 Beego 的编程思想就是照搬了 PHP 的那一套,写法上倒没什么,但是在...
    99+
    2024-04-02
  • 如何使用Python来提高Spring框架的性能?
    好的,下面是文章的内容: Spring框架是一个非常流行的Java企业级应用程序开发框架,它提供了丰富的特性和功能,让开发者可以快速构建高效的应用程序。然而,在处理大量数据时,Spring框架的性能可能会受到影响。本文将介绍如何使用Pyth...
    99+
    2023-09-16
    bash spring load
  • PHP 应用程序性能优化中 CodeIgniter 框架的高性能实践
    codeigniter 框架通过以下实践提升 php 应用程序性能:启用 apc 缓存以加速 php 代码执行。使用数据库缓存存储频繁查询的结果,避免数据库交互。优化查询以减少不必要的数...
    99+
    2024-05-03
    php 性能优化 css
  • VB.NET框架类库怎么用
    小编给大家分享一下VB.NET框架类库怎么用,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!VB.NET经过长时间的发展,很多用户都很了解VB.NET了,这里我发表...
    99+
    2023-06-17
  • 怎么提高数据库性能
    这篇文章将为大家详细讲解有关怎么提高数据库性能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。以下是提升数据库性能的6种实用的方式,无需增加更强大的服务器,也无需重写代码或...
    99+
    2024-04-02
  • SpringBoot2中怎么整合ElasticSearch框架实现高性能搜索引擎
    SpringBoot2中怎么整合ElasticSearch框架实现高性能搜索引擎,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1、核心依赖<dependency>...
    99+
    2023-06-02
  • 开源的性能测试框架p-unit怎么用
    本篇文章为大家展示了开源的性能测试框架p-unit怎么用,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。认识p-unit:一款开源的性能测试框架p-unit 是一款开放源码的性能测试框架,和 JUni...
    99+
    2023-06-03
  • 如何调优PHP-FPM提高Yii框架应用的性能
    一、介绍Yii框架是一种高性能的PHP框架,它广泛应用于开发高流量的Web应用程序。然而,在高并发环境下,Yii框架的性能可能会受到限制。为了最大限度地提高Yii框架应用的性能,我们可以通过调优PHP-FPM来实现。二、PHP-FPM简介P...
    99+
    2023-10-21
    性能 应用 调优 yii php-fpm
  • Laravel框架:构建高性能Web应用程序的秘诀
    Laravel是一个基于PHP编程语言的Web应用程序框架。它通过提供简单、优雅的语法和强大的功能,让Web应用程序的开发变得更加容易和快速。Laravel框架的设计和实现是为了创建高质量、高性能的Web应用程序。在本文中,我们将探讨La...
    99+
    2023-08-16
    laravel 学习笔记 shell
  • 如何在 ASP 框架中使用 npm 缓存提高性能?
    在开发 ASP.NET 应用程序时,我们通常使用 NuGet 包管理器来引用第三方依赖项。但是,如果你已经在项目中使用了 npm 包管理器,你可能会想知道如何在 ASP.NET 应用程序中使用 npm 缓存来提高性能。 npm 缓存是一个本...
    99+
    2023-11-09
    框架 缓存 npm
  • Linux环境中的Go语言框架:哪些具备高性能和可扩展性?
    在现代软件开发中,高性能和可扩展性是非常重要的特征。Go语言作为一种快速、高效、并发的语言,已经成为许多开发人员的首选语言。在Linux环境中,Go语言的框架也在不断发展,以满足不同应用程序的需求。在本文中,我们将介绍几个在Linux环境...
    99+
    2023-08-02
    linux 框架 unix
  • 怎么在Linux中如何使用iotop和iostat监控磁盘I/O活动
    本篇内容介绍了“怎么在Linux中如何使用iotop和iostat监控磁盘I/O活动”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是 i...
    99+
    2023-06-16
  • 高性能跨平台网络通信框架 HP-Socket 5.6.1怎么更新
    今天就跟大家聊聊有关高性能跨平台网络通信框架 HP-Socket 5.6.1怎么更新,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。v5.6.1 更新一、SSL 组件更新所有 SSL ...
    99+
    2023-06-03
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作