1. 前言

在C语言i中,存储变量的结构体加上一组函数指针,大概就可以算是一个对象模型了;如果将一组函数指针捆绑为结构体,

后期根据配置或者环境需要绑定到不同实现模块中的一组函数,可以认为是C语言面对对象的设计实现了。

2. 概述

事件模型,定义在"libgusterfs/src/"下几个文件中:

event.h    // 事件模型的接口定义:各个结构体的定义
event.c // 实现了最基本的模型的管理相关的函数
eventpool.c // pool模式 具体的实现
eventepoll.c // epool模式,具体的实现

我们首先看看如何定义事件管理模型:

struct event_pool {
struct event_ops *ops; // 一组函数指针, int fd; // 文件操作符
int breaker[2]; int count; // 可以需要监控的SOCKET个数
struct event_slot_poll *reg; // poll 模式使用的,定义于eventpool.c
struct event_slot_epoll *ereg[EVENT_EPOLL_TABLES]; // 定义于eventepoll.c
int slots_used[EVENT_EPOLL_TABLES]; // #define EVENT_EPOLL_TABLES
// 一共定义了1024个表格,每个表格里有1024个槽位,每个槽位是一个SOCKET
int used;
int changed; pthread_mutex_t mutex;
pthread_cond_t cond; void *evcache;
int evcache_size; /* 备注: 目前当使用Epoll模式工作时候使用下面部分代码 */
int eventthreadcount; /* 内部执行线程个数 */
pthread_t pollers[EVENT_MAX_THREADS]; /* poller 线程ID 集合 */
int destroy; // 用来标记线程需要结束的变量
int activethreadcount; /*
* 自动缩放的线程数, 这个数加到已经配置的线程数上. 这仅仅适用于server端, 因为我们将试图将线程数匹配
* bricks的数目. 对客户或者 GlusterD来说,
* 这个变量一直为0。
*
* 下一步: 也会考虑为客户端缩放线程数。
*/
int auto_thread_count; };

这个结构体包括了poll和epoll两种工作模式的不同实现。

接着定义了一组函数指针:

struct event_ops 
{
struct event_pool * (*new) (int count, int eventthreadcount); int (*event_register) (struct event_pool *event_pool, int fd,
event_handler_t handler,
void *data, int poll_in, int poll_out); int (*event_select_on) (struct event_pool *event_pool, int fd, int idx,
int poll_in, int poll_out); int (*event_unregister) (struct event_pool *event_pool, int fd, int idx); int (*event_unregister_close) (struct event_pool *event_pool, int fd,
int idx); int (*event_dispatch) (struct event_pool *event_pool); int (*event_reconfigure_threads) (struct event_pool *event_pool,
int newcount);
int (*event_pool_destroy) (struct event_pool *event_pool);
int (*event_handled) (struct event_pool *event_pool, int fd, int idx,
int gen);
};

这组函数指针在具体实现中将绑定具体的实现,绑定的过程定义于event_pool_new (int count, int eventthreadcount):

struct event_pool * event_pool_new (int count, int eventthreadcount)
{
struct event_pool *event_pool = NULL; // 返回值
extern struct event_ops event_ops_poll; // 引用外部结构体,见 eventpool.c 最后面部分 #ifdef HAVE_SYS_EPOLL_H // 如果支持epoll
extern struct event_ops event_ops_epoll; // 引用外部结构体,见 eventepool.c 最后面部分
event_pool = event_ops_epoll.new (count, eventthreadcount); // 执行pool模块的生成函数
if (event_pool)    
{
event_pool->ops = &event_ops_epoll; // 绑定该模块的操作函数
}
    else
{
gf_msg ("event", GF_LOG_WARNING, 0, LG_MSG_FALLBACK_TO_POLL, "falling back to poll based event handling");
}
#endif if (!event_pool)
{
event_pool = event_ops_poll.new (count, eventthreadcount); // 执行epool模块的生成函数 if (event_pool)
event_pool->ops = &event_ops_poll; // 绑定该模块的操作函数
} return event_pool;
}

而整个event.c中定义的各个函数,仅仅是调用绑定pool或者epoll实现的各个函数。举例如下:

int event_select_on (struct event_pool *event_pool, int fd, int idx_hint, int poll_in, int poll_out)
{
int ret = event_pool->ops->event_select_on (event_pool, fd, idx_hint, poll_in, poll_out);
    return ret;
}

3. epoll 模型的实现

我们首先看看典型的epoll模型如何实现:epoll模型和使用详解(精髓)epoll - I/O event notification facility

在event-epoll.c 中定义了epoll实现的接口函数,

struct event_ops event_ops_epoll =
{
.new = event_pool_new_epoll, // 新建立一个event-pool,创建epoll句柄
.event_register = event_register_epoll, // 将一个新的socket添加到epoll的监控中,
.event_select_on = event_select_on_epoll, //
.event_unregister = event_unregister_epoll, // 取消监控
.event_unregister_close = event_unregister_close_epoll, // 取消监控并关闭socket
.event_dispatch = event_dispatch_epoll, // 建立pollercount个线程,event_dispatch_epoll_worker 线程函数用来处理消息,
// 并在event_dispatch_epoll_handler 中调用注册的函数
.event_reconfigure_threads = event_reconfigure_threads_epoll,
.event_pool_destroy = event_pool_destroy_epoll, // 销毁池
.event_handled = event_handled_epoll,
};

glusterfs 4.0.1 event模块 分析笔记1的更多相关文章

  1. glusterfs 4.0.1 api 分析笔记1

    一般来说,我们写个客户端程序大概的样子是这样的: /* glfs_example.c */ // gcc -o glfs_example glfs_example.c -L /usr/lib64/ - ...

  2. glusterfs 4.0.1 rpc 分析笔记1

    Jimmy的文档:Glusterfs的rpc模块分析 第一节.rpc服务器端实现原理及代码分析 第二节.rpc客户端实现原理及代码分析 第三节.rpc通信过程分析 经过阅读源码对比之前提及的文档,我个 ...

  3. nginx源码分析——event模块

    源码:nginx 1.12.0   一.简介      nginx是一款非常受欢迎的软件,具备高性能.模块化可定制的良好特性.之前写了一篇nginx的http模块分析的文章,主要对http处理模块进行 ...

  4. 一个普通的 Zepto 源码分析(三) - event 模块

    一个普通的 Zepto 源码分析(三) - event 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块, ...

  5. jQuery源码分析--Event模块(1)

    jQuery的Event模块提供了强大的功能:事件代理,自定义事件,自定义数据等.今天记录一下它实现的原理. 我们都知道,在js的原生事件中,有事件对象和回调函数这两样东西.但是事件对象是只读的,所以 ...

  6. Backbone源码解析(一):Event模块

    Backbone是一个当下比较流行的MVC框架.它主要分为以下几个模块: Events, View, Model, Collection, History, Router等几大模块.它强制依赖unde ...

  7. nginx事件模块分析(一)

    nginx ngx_events_module模块分析 ngx_events_module模块是核心模块之一,它是其它所有事件模块的代理模块.nginx在启动时只与events模块打交道,而由even ...

  8. [自娱自乐] 3、超声波测距模块DIY笔记(三)

    前言 上一节我们已经研究了超声波接收模块并自己设计了一个超声波接收模块,在此基础上又尝试用单片机加反相器构成生成40KHz的超声波发射电路,可是发现采用这种设计的发射电路存在严重的发射功率太低问题,对 ...

  9. 读Zepto源码之Event模块

    Event 模块是 Zepto 必备的模块之一,由于对 Event Api 不太熟,Event 对象也比较复杂,所以乍一看 Event 模块的源码,有点懵,细看下去,其实也不太复杂. 读Zepto源码 ...

随机推荐

  1. 如何用UPA优化性能?先读懂这份报告!

    一.概述 打开一份UPA报告时,最先看到的就是概述页面,这也是我们推荐用户第一时间关注的页面.概述页面一开始会列出测试的基本信息,并根据腾讯游戏的性能标准,给出本次测试的结果(通过,不通过和警告): ...

  2. Python-Cpython解释器支持的进程与线程-Day9

    Cpython解释器支持的进程与线程 阅读目录 一 python并发编程之多进程 1.1 multiprocessing模块介绍 1.2 Process类的介绍 1.3 Process类的使用 1.4 ...

  3. python全栈开发-hashlib模块(数据加密)、suprocess模块、xml模块

    一.hashlib模块 1.什么叫hash:hash是一种算法(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法 ...

  4. Python之递归函数

    递归函数 初识递归函数 递归函数的定义:在一个函数里再调用这个函数本身 Python为了考虑保护内存占用情况,有一个递归深度的限制. 探究递归的默认最大深度: def foo(n): print(n) ...

  5. android webview重定向 返回按钮死循环问题修改

    当HTML有重定向的时候,回退时会不断往跳转进入死循环.尝试修改webview缓存加载策略以后,不起作用.在网上查阅资料以后,跟 shouldOverrideUrlLoading的返回值为true还是 ...

  6. Python入门之三元表达式\列表推导式\生成器表达式\递归匿名函数\内置函数

    本章目录: 一.三元表达式.列表推导式.生成器表达式 二.递归调用和二分法 三.匿名函数 四.内置函数 ================================================ ...

  7. android 加速度传感器 ---摇一摇

    package com.eboy.testyaoyiyao;import java.text.SimpleDateFormat;import java.util.Date;import android ...

  8. 【vuejs深入一】深入学习vue指令,自定义指令解决开发痛点

    写在前面  一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. 最近博主我沉淀了几个月,或者说懒了几个月.然而大佬的指点总是一针见血,能够让人看到方向.所以我现在有觉得,一个好的 ...

  9. MySQL获取XML格式数据

    通过再调用mysql工具时使用--xml选项: C:\Users\wang>mysql -uroot -p --xml mydb Enter password: ******** Welcome ...

  10. 调用Kubernetes API操作Kubernetes

    准备工作 首先要准备一个1.5+版本的Kubernetes,并且开放了API Server的http访问端口8080.本文使用的是1.10的版本,没有环境的可以参考我上一篇文章<在CentOS ...