• 【Redis分析 】之网络库分析


    源码分析版本:4.0.1

    文件结构

    redis的网络通信模块由8个文件构成
    在这里插入图片描述

    作用如下

    文件作用
    ae.c统一epoll、evport、kqueue、select网络事件处理接口, 函数实现
    ae.h统一epoll、evport、kqueue、select网络事件处理接口,函数原型,共享结构体定义
    ae_epoll.c封装epoll网络事件处理库到统一的接口
    ae_evport.c封装evport网络事件处理库到统一的接口
    ae_kqueue.c封装kqueue网络事件处理库到统一的接口
    ae_select.c封装select网络事件处理库到统一的接口

    统一网络库底层接口

    被统一的网络事件处理接口如下,参考:ae_epoll.c, ae_evport.c, ae_kqueue.c,ae_select.c

    接口作用
    aeApiState底层网络库需要的fd、事件等数据共享结构体
    aeApiCreate创建网络句柄,比如epoll句柄,在这个基础上才能进行网络事件的监听处理
    aeApiResize修改网络库存放事件的容器大小,就是修改aeApiState结构体的events数组的大小
    aeApiFree删除aeApiState这个共享结构体
    aeApiAddEvent将网络fd的读写操作交给网络库进行处理,比如给这个epoll进行处理
    aeApiDelEvent从网络操作库中删除对某个fd的监听,一般服务器往客户端写完数据后,主动断开客户端连接时会使用
    aeApiPoll轮询获取网络正在发生io读写事件的事件
    aeApiName获取底层网络库的名字,比如epool,kqueue等

    #统一网络库上层接口
    参考 ae.h, ae.c,封装通用的结构体和函数

    网络读写事件aeFileEvent结构体

    /* File event structure */
    typedef struct aeFileEvent {
        int mask; /* one of AE_(READABLE|WRITABLE) */
        aeFileProc *rfileProc;
        aeFileProc *wfileProc;
        void *clientData;
    } aeFileEvent;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这个结构体封装了网络数据读写事件的处理函数原型,和客户端传过来的数据。
    aeFileProc是处理函数的原型的宏定义,宏定义参考如下:

    typedef void aeFileProc(
        struct aeEventLoop *eventLoop,
        int fd,
        void *clientData,
        int mask
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    实际使用时,网络读写事件的函数处理需要自行编写

    定时事件aeTimeEvent结构体

    /* Time event structure */
    typedef struct aeTimeEvent {
        long long id; /* time event identifier. */
        long when_sec; /* seconds */
        long when_ms; /* milliseconds */
        aeTimeProc *timeProc;
        aeEventFinalizerProc *finalizerProc;
        void *clientData;
        struct aeTimeEvent *next;
    } aeTimeEvent;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这个定时事件是redis用来处理后台定时任务使用的,比如处理客户端连接超时,服务端断开操作活跃的fd

    /* A fired event */
    typedef struct aeFiredEvent {
        int fd;
        int mask;
    } aeFiredEvent;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    就是正在等待读、正在等待写的网络fd,一般以一个数组出现
    mask字段表示是等待读,还是等待写,对应的值如下

    #define AE_READABLE 1
    #define AE_WRITABLE 2
    
    • 1
    • 2

    网络库上层接口核心结构体aeEventLoop

    /* State of an event based program */
    typedef struct aeEventLoop {
        int maxfd;   /* highest file descriptor currently registered */
        int setsize; /* max number of file descriptors tracked */
        long long timeEventNextId;
        time_t lastTime;     /* Used to detect system clock skew */
        aeFileEvent *events; /* Registered events */
        aeFiredEvent *fired; /* Fired events */
        aeTimeEvent *timeEventHead;
        int stop;
        void *apidata; /* This is used for polling API specific data */
        aeBeforeSleepProc *beforesleep;
        aeBeforeSleepProc *aftersleep;
    } aeEventLoop;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    操作aeEventLoop相关函数

    在这里插入图片描述

    主要是对aeEventLoop结构体进行操作,这里拿几个核心的函数举例

    aeCreateEventLoop()

    这个函数主要是创建aeEventLoop结构体,并根据setsize参数给events, fired分配内容空间然后再调用aeApiCreate驱动底层的网络库,比如epoll的epoll_create(),然后保存到aeEventLoop的apidata属性上

    aeMain()

    主要是启动无限循环、轮询处理活跃的fd,如果epoll,底层则调用epoll_wait获取可读写的fd:ae.c::aeMain() -> ae.c::aeProcessEvents() -> ae_epoll.c::aeApiPool() -> ae_epoll.c::epoll_wait()

    aeCeateFileEvent()

    注册网络fd到底层网络库上,并注册当读写事件发生时,需要执行的业务回调函数拿epoll举例,调用到epoll经过的步骤:ae.c::aeCreateFileEvent() -> ae_epoll.c::aeApiAddEvent() -> epoll_ctl()

    anet.h & anet.c

    主要是封装socket操作,屏蔽系统底层socket操作的差异性,提供更好用的api,比如创建tcp server等

    在这里插入图片描述
    这里就拿创建tcp server来看看它的流程

    anetTcpServer()

    anet.c::anetTcpServer() -> anet.c::_anetTcpServer() -> ::socket() -> anet.c::anetListen() -> ::listen()
    核心代码就是调用系统socket库的listen函数建立起了一个tcp的server
    在这里插入图片描述

    参考资料:

    http://qiankunli.github.io/2018/06/15/redis.html
    https://juejin.cn/post/6844903909387927560

  • 相关阅读:
    LeaRun.net快速开发动态表单
    服务器安装Ubuntu20及系统扩容
    Thanos工作原理及组件简介
    自定义线程池+countdownlatch
    label studio 结合 MMDetection 实现数据集自动标记、模型迭代训练的闭环
    用户行为数据案例
    第三节:样式、选择器
    当我们的执行 java -jar xxx.jar 的时候底层到底做了什么?
    AQS介绍
    计算机毕业设计之java+SSM酒店客房预定管理系统
  • 原文地址:https://blog.csdn.net/qq_34462436/article/details/126515055