基于多反应堆的高并发服务器【C/C++/Reactor】(中)添加 删除 修改 释放

在上篇文章(处理任务队列中的任务)中我们讲解了处理任务队列中的任务的具体流程,eventLoopProcessTask函数的作用:

  • 处理队列中的任务,需要遍历链表并根据type进行对应处理,也就是处理dispatcher中的任务。
// 处理任务队列中的任务
int eventLoopProcessTask(struct EventLoop* evLoop) {...while (head!=NULL) {struct Channel* channel = head->channel;if(head->type == ADD) {// 添加eventLoopAdd(evLoop,channel);}else if(head->type == DELETE) {// 删除eventLoopRemove(evLoop,channel);}else if(head->type == MODIFY) {// 修改eventLoopModify(evLoop,channel);}...}...return 0;
}
  • 处理dispatcher中的任务 -- 添加 删除 修改
// 处理dispatcher中的任务
int eventLoopAdd(struct EventLoop* evLoop,struct Channel* channel);
int eventLoopRemove(struct EventLoop* evLoop,struct Channel* channel);
int eventLoopModify(struct EventLoop* evLoop,struct Channel* channel);

 一、添加fdDispatcher的文件描述符检测集合中

把文件描述符fdchannel的对应关系存储到channelMap。这么做是为了什么?

  • dispatcher里边,还有dispatch函数指针,也就是dispatcher->dispatch(evLoop,timeout)。这个是一个检测函数,通过调用dipatch函数,就可以得到激活的文件描述符,得到了激活的文件描述符之后,需要通过这个文件描述符找到它所对应的channel
channelMap->list[fd] = channel; 

把文件描述符添加到dispatcher对应的文件描述符检测集合中

  • 首先从evLoop里边把dispatcher这个实例给取出来:evLoop->dispatcher,在dispatcher里边有一系列的函数指针,其中有一个叫做add。这个add就是把文件描述符添加到dispatcher对应的文件描述符检测集合中,函数指针add,指向的底层函数可能是不一样的,这个取决于我们选择的dispatcher模型,它有可能是poll,有可能是epoll,也有可能是select。选择的IO模型不一样,add这个函数指针指向的函数的处理动作也就不一样
evLoop->dispatcher->add(channel,evLoop); 

 (1)eventLoopAdd 

// 将任务队列中的任务添加到Dispatcher的文件描述符检测集合中
int eventLoopAdd(struct EventLoop* evLoop,struct Channel* channel) {int fd = channel->fd;// 取出文件描述符fdstruct ChannelMap* channelMap = evLoop->channelMap;// channelMap存储着channel和fd之间的对应关系// 需要判断channelMap里边是否有fd 和 channel对应的键值对(其中,文件描述符fd对应的就是数组的下标)if(fd >= channelMap->size) {// 没有足够的空间存储键值对 fd->channel ==> 扩容if(!makeMapRoom(channelMap,fd,sizeof(struct Channel*))) {return -1;}}// 找到fd对应的数组元素位置,并存储if(channelMap->list[fd] == NULL) {channelMap->list[fd] = channel;evLoop->dispatcher->add(channel,evLoop);} return 0;
}

1. 主题: 文件描述符与ChannelDispatcher中的交互

2. 重要信息:

  • Channel结构体:封装了文件描述符,并在其中存储了所需的数据
  • 添加文件描述符到Dispatcher:当有新文件描述符需要添加时,它会被放入Dispatcher的检测集合中
  • 文件描述符激活与处理:如果某个文件描述符在Dispatcher的检测集合中被激活,可以通过调用dispatch函数获取这个文件描述符,并进一步找到对应的Channel
  • 回调函数与事件处理:一旦找到对应的Channel,可以根据触发的事件调用在Channel结构体中注册的回调函数
  • ChannelMap结构体:用于存储文件描述符Channel之间的对应关系。它是一个数组,下标(即数组索引)对应文件描述符的值
  • 扩容ChannelMap:如果当前ChannelMap的容量不足,可以通过调用 makeMapRoom 函数进行扩容

3. 总结:详细介绍了如何通过Channel结构体和Dispatcher处理文件描述符,以及如何通过回调函数处理不同的事件。同时,还提到了如何使用和扩容ChannelMap结构体来存储文件描述符与Channel之间的对应关系

4. 思考与理解: 深入理解文件描述符、ChannelDispatcher之间的关系及其工作原理。 在实际编程中,考虑如何有效地使用和扩展ChannelMap结构体,以适应更多的文件描述符和事件处理需求。 考虑如何在代码中实现更清晰的事件处理逻辑,以提高代码的可读性和可维护性

总结:主要描述了如何通过文件描述符在channel中添加、激活和触发事件。其中,channelMap结构体用于存储文件描述符和channel的对应关系,而EventLoop结构体则用于存储channel和文件描述符的对应关系

核心观点 :

  • 文件描述符与channel的对应关系存储在channelMap中,通过数组索引对应文件描述符的值
  • 如果channelMap容量不足,需要调用函数进行扩容

二、从Dispatcher的文件描述符检测集合中删除fd

把任务队列里面的节点从dispatcher的检测集合中删除,调用dispatcher里边的remove函数

  • 如果我们要删除的这个文件描述符并不在channelMap中存储着,说明我们要操作的这个文件描述符并不在dispatcher的检核集合中。因为它在检测集合里边,在添加的时候就会把文件描述符fdchannel的映射关系也存储到channelMap里边去了。故只要它在检测集合里边,它肯定就在channelMap里边。如果它不在channelMap里边,那么它就肯定不在检测集合里边。如果它不在检测集合里边,就无需做任何事情,直接返回-1
  • 如果文件描述符fd在检测集合里,就从中把它删除

int eventLoopRemove(struct EventLoop* evLoop,struct Channel* channel) {int fd = channel->fd;struct ChannelMap* channelMap = evLoop->channelMap;if(fd >= channelMap->size) {return -1;}int ret = evLoop->dispatcher->remove(channel,evLoop);return ret;
}

三、修改Dispatcher的检测集合里边文件描述符事件的函数

当我们需要修改检测集合中的某个文件描述符事件时,首先需要判断该文件描述符是否在channelMap中。如果文件描述符存在,我们可以根据它获取一个非零的地址,这个地址实际上是channel实例的地址

  • 如果获取的地址为,说明传入的文件描述符对应的channel有问题;
  • 如果不为空,我们可以通过evLoop实例调用其函数指针modify

int eventLoopModify(struct EventLoop* evLoop,struct Channel* channel) {int fd = channel->fd;struct ChannelMap* channelMap = evLoop->channelMap;if(fd >= channelMap->size || channelMap->list[fd] == NULL) {return -1;}int ret = evLoop->dispatcher->modify(channel,evLoop);return ret;
}

四、释放channel

// 释放channel
int destroyChannel(struct EventLoop* evLoop,struct Channel* channel);

从检测集合中删除文件描述符后,对应的channel实例没有用了,因此需要释放它。在释放channel之前,我们需要关闭文件描述符,因为不再需要检测它的事件。此外,由于channel本身是一个指向堆内存的指针,我们需要释放这块堆内存。 

// 释放channel
int destroyChannel(struct EventLoop* evLoop,struct Channel* channel) {// 删除 channel 和 fd 的对应关系evLoop->channelMap->list[channel->fd] = NULL;// 关闭 fdclose(channel->fd);// 释放 channel 内存free(channel);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/319036.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

很实用的ChatGPT网站—在线编程模块增补篇

很实用的ChatGPT网站(http://chat-zh.com/)——增补篇 今天介绍一个好兄弟开发的ChatGPT网站,网址[http://chat-zh.com/]。这个网站功能模块很多,包含生活、学习、医疗、法律、经济等很多方面。今天跟大家分享一下,新…

使用 Process Explorer 和 Windbg 排查软件线程堵塞案例分享

目录 1、问题说明 2、线程堵塞的可能原因分析 3、使用Windbg和Process Explorer确定线程中发生了死循环 4、根据Windbg中显示的函数调用堆栈去查看源码,找到问题 4.1、在Windbg定位发生死循环的函数的方法 4.2、在Windbg中查看变量的值去辅助分析 4.3、是循环…

机器学习--ROC AUC

参考 机器学习-ROC曲线 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/347470776一文看懂ROC、AUC - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/81202617 在了解之前,我们先来认识一下以下的概念 针对一个二分类问题,将实例分成正类(postive)或…

下载的 MongoDB bin目录下没有mongo.exe文件问题解决

MongoDB 4.4版本之前,我们可以在MongoDB的安装目录的bin文件夹中找到mongo.exe这个命令行工具。但是从MongoDB 4.4版本开始,MongoDB官方已经不再提供独立的mongo.exe可执行文件,而是将其整合到了mongosh这个新的交互式Shell中。 我们可以访问…

k8s的pod基础

pod:pod是k8s中最小的资源管理组件。 pod也是最小化运行容器化的应用的资源管理对象。 pod是一个抽象的概念,可以理解为一个或者多个容器化应用的集合。 在一个pod当中运行一个容器是最常用的方式。在一个pod当中同时运行多个容器,在一个pod当中可以同…

常见网络协议

1.DNS协议 (域名系统) DNS协议使用的端口号是53 位于OSI模型中的应用层 DNS系统的作用:将域名(网址)解析为IP地址。 DNS的基本原理是:将域名映射到IP地址 DNS工作流程 当用户给定一个域名&#xff0…

Linux磁盘管理与文件系统

目录 前言 一、磁盘基础 1、磁盘的物理结构 2、磁盘的数据结构 3、磁盘存储容量 4、硬盘接口类型 二、磁盘分区 1、磁盘分区的优缺点 2、磁盘两种分区方式 2.1 MBR分区 2.2 GPT分区(了解) 三、管理磁盘分区的工具 1、fdisk 2、blkid 3、free 4、mkfs 5、mkswa…

GitHub上的15000个Go模块存储库易受劫持攻击

内容概要: 目前研究发现,GitHub上超过15000个Go模块存储库容易受到一种名为“重新劫持”的攻击。 由于GitHub用户名的更改会造成9000多个存储库容易被重新劫持,同时因为帐户删除,会对6000多个存储库造成重新劫持的危机。目前统计…

Spark二、Spark技术栈之Spark Core

Spark Core spark核心:包括RDD、RDD算子、RDD的持久化/缓存、累加器和广播变量 学习链接:https://mp.weixin.qq.com/s/caCk3mM5iXy0FaXCLkDwYQ 一、 RDD 1.1 为什么要有RDD 在许多迭代式算法(比如机器学习、图算法等)和交互式数据挖掘中,…

系列五、搭建Naco(集群版)

一、搭建Naco(集群版) 1.1、前置说明 (1)64位Red Hat7 Linux 系统; (2)64位JDK1.8;备注:如果没有安装JDK,请参考【系列二、Linux中安装JDK】 (3&…

《绝地求生》改名卡快速获得方法 绝地求生改名卡怎么获得

《绝地求生》改名卡是很多小伙伴所在意的物品,购买通行证后需要提升一定的等级才能入手,而怎么升级最快最划算呢?今天闲游盒带来“米奇”分享的《绝地求生》改名卡快速获得方法,赶紧来试试吧。 吃鸡刚刚迎来了更新,通行…

Flink版本更新汇总(1.14-1.18)

0、汇总 1.14.0 1.有界流支持 Checkpoint; 2.批执行模式支持 DataStream 和 Table/SQL 混合应用; 3.新增 Hybrid Source 功能; 4.新增 缓冲区去膨胀 功能; 5.新增 细粒度资源管理 功能; 6.新增 DataStream 的 Pulsar …