AndroidT(13) init 进程 -- second stage init 中的 Epoll (三)

news/2024/10/30 12:52:13/

1. 概览

  在进入 second stage init 讲解之前,先来看看它事件监听及处理的机制 – Epoll 类,它实际上是对 epoll 的封装,使他变得更加适合再 init 中来跟踪事件以及分发触发方法等。整个类只有 4 个方法,在如此小巧的条件下实现了:事件监听的注册、卸载、跟踪以及收集事件的处理方法。这也意味着用户在注册后,在等待到事件后可以直接调用返回的处理方法列表。

2.整体使用骨架

  second init 中就是使用 Epoll 来跟踪事件并处理的,下面看下 Epoll 的使用流程。

//system\core\init\init.cpp
SecondStageMain//code 1Epoll epoll;epoll.Open();//code 2InstallInitNotifier(&epoll); auto clear_eventfd = [] {uint64_t counter;TEMP_FAILURE_RETRY(read(wake_main_thread_fd, &counter, sizeof(counter)));};epoll->RegisterHandler(wake_main_thread_fd, clear_eventfd)//code 3while (true) {auto pending_functions = epoll.Wait(epoll_timeout);for (const auto& function : *pending_functions) {(*function)();}}

2.1 Epoll 的实例化 – code1

  Epoll 构造方法使用的是空的并没做什么,再 Open 中也是很简单的申请了一个 epoll 的句柄,并记录在 epoll_fd_类变量中。

//system\core\init\epoll.cpp
Result<void> Epoll::Open() {if (epoll_fd_ >= 0) return {};epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));if (epoll_fd_ == -1) {return ErrnoError() << "epoll_create1 failed";}return {};
}

2.2 注册监听对象及处理方法 – code2

  Epoll 的监听对象只能是 fd 也就是文件句柄,它的回调方法原型如下,

//system\core\init\epoll.h
typedef std::function<void()> Handler;

  准备好监听对象和它的处理方法后就可以调用 RegisterHandler 注册到 Epoll 中了,来看看它的定义

Result<void> Epoll::RegisterHandler(int fd, Handler handler, uint32_t events)//aInfo info;info.events = events;info.handler = std::make_shared<decltype(handler)>(std::move(handler));auto [it, inserted] = epoll_handlers_.emplace(fd, std::move(info));//bepoll_event ev;ev.events = events;ev.data.ptr = reinterpret_cast<void*>(&it->second);//cepoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ev)

  可见注册分为如下几个步骤
    a) 构建 Info 信息,其中包括它对 fd 中关心的事件类型,比如默认值 EPOLLIN,如果来这个事件就意味着 fd 句柄有数据可以读取了。还有用来处理 fd 数据的回调方法 handler。最后将 Info 和 fd 传入到 map epoll_handlers_中去,供后续使用。
    b) 设置 epoll_event 事件,该数据结构则是使用 epoll 的的标准构造方法,其中记录的 events 则是供 kernel 使用的和上面提到的 info.events值一致。并将 Info 实例作为它的私有数据。
    c) 最后调用 epoll_ctl 将 fd 添加到 epoll_fd_中去,如此系统才会对该 fd 实现监听。

2.3 等待事件并返回处理方法 – code3

  可见 Wait 方法会被循环调用不做退出的,这部分的概念和 Looper 还是很相似的,一个线程中只存在一个 Epoll中,并且 Epoll 的回调方法也是该线程执行的。下面就来看看它的实现

Result<std::vector<std::shared_ptr<Epoll::Handler>>> Epoll::Wait(std::optional<std::chrono::milliseconds> timeout)//aconst auto max_events = epoll_handlers_.size();epoll_event ev[max_events];auto num_events = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_, ev, max_events, timeout_ms));//bstd::vector<std::shared_ptr<Handler>> pending_functions;for (int i = 0; i < num_events; ++i) {auto& info = *reinterpret_cast<Info*>(ev[i].data.ptr);if ((info.events & (EPOLLIN | EPOLLPRI)) == (EPOLLIN | EPOLLPRI) &&(ev[i].events & EPOLLIN) != ev[i].events) {// This handler wants to know about exception events, and just got one.// Log something informational.LOG(ERROR) << "Received unexpected epoll event set: " << ev[i].events;}pending_functions.emplace_back(info.handler);}//creturn pending_functions;

    a) 监听 epoll_fd_ 也就是 epoll句柄,只要挂在它上面的任何一个 fd 来事件了,epoll_wait 就会返回。当然超时的话也会返回。
    b) 循环遍历,看看是哪一个 epoll_event 来数据了,可以查看它的 epoll_event.events 成员变量。对于没有注册的事件则会报 Error 级别的log,但不会退出线程。最后再收集下需要处理的 fd 的回调方法,存入 pending_functions 向量中。
    c) 返回 pending_functions 向量,线程只要循环调用它内部的回调方法即可。

for (const auto& function : *pending_functions) {(*function)();
}

3. 总结

  可见使用了 Epoll 后,只要简单的几个步骤即可,作为框架使用还是相当方便的,其中隐藏了 epoll 的数据构造,用户只要提供 监听对象和对于的触发方法即可。不过值得注意的是,这是单线程的,如果注册太多的监听对象,或者某一个处理方法中耗时过长,还是相当影响其他监听事件的处理的。


http://www.ppmy.cn/news/325566.html

相关文章

吃鸡游戏计算机配置,运行端游吃鸡要什么配置

这款游戏可以玩哪种配置? 我可以吃鸡肉h1z1吗? 不发送,GT730性能非常差,我曾经是GT730,买了二手660,现在970、550TI比730要好。 什么样的计算机可以 GTX650,GTX750Ti,R9270X,GTX960,R9390,GTX1050,GTX1050Ti,GTX1060,GTX1080。 除了SteamMachine主机中的GTX850M,…

什么叫计算机游戏,电脑吃鸡游戏叫什么,电脑上的吃鸡游戏叫什么

吃鸡电脑版叫什么 电脑版本&#xff1a;《绝地求生大逃亡》。手机版本比较多&#xff0c;主要比较火的就是网易的《荒野行动》和腾讯的《绝地求生-刺激战场》、《绝地求生-全军出击》。&#xff1c;br&#xff1e;&#xff1c;br&#xff1e;这种游戏之所以叫“吃鸡”&#xff…

吃鸡录屏怎么录到自己的声音 吃鸡录屏怎么隐藏按键

很多人在玩吃鸡游戏时喜欢将自己的游戏过程录制下来&#xff0c;特别是很多游戏主播会录制视频&#xff0c;录制后将视频分享到社交平台。但是在录制时经常会遇到很多问题&#xff0c;如声音、画面清晰度和完整性等。接下来就来分享一下吃鸡录屏怎么录到自己的声音&#xff0c;…

吃鸡游戏计算机配置,手游吃鸡pc端吃什么配置

电脑玩吃鸡需要什么配置?_ 《绝地求生》最低计算机配置:操作系统:64位Windows7,Windows8.1,Windows10处理器:IntelCorei3-4340 / AMDFX- 6300内存:8GBRAM图形:nVidiaGeForceGTX6602GB / AMDRadeonHD78502GBDirectX版本:11网络:宽... 使用计算机玩模拟器的鸡手机游戏需…

吃鸡手游竟然是 Python 写的?

吃鸡”有多热&#xff0c;已经不用多说。但你知道吗&#xff1f;你热爱的“吃鸡”可能是用Python写的。 网易的两大游戏客户端引擎&#xff0c;NeoX 和 Messiah&#xff0c;都是使用 Python 作为脚本语言的。具体来说&#xff0c;服务器端可以说是完全Python&#xff0c;毕竟能…

吃鸡配置文件

//自定义特效等级 [ScalabilityGroups] sg.ResolutionQuality100.000000 //视野距离 sg.ViewDistanceQuality1 sg.AntiAliasingQuality0 sg.ShadowQuality0 sg.PostProcessQuality0 sg.TextureQuality0 sg.EffectsQuality0 sg.FoliageQuality0 //语言 CultureNamezh-CN …

【数据结构与算法】 01 链表 (单链表、双向链表、循环链表、块状链表、头结点、链表反转与排序、约瑟夫环问题)

一、线性表1.1 概念与特点1.2 线性表的存储结构1.3 常见操作1.4 应用场景 二、链表2.1 链表简介2.2 单向链表&#xff08;单链表&#xff09;2.21 基本概念2.22 单链表基本操作2.23 C语言实现▶ 带头结点▶ 不带头结点 2.3 双向链表2.31 基本概念2.32 与单链表比较2.33 双向链表…

OpenCV 项目开发实战--对图像种的斑点进行检测(Python、C++代码实现)

什么是斑点? Blob 是图像中一组连接的像素,它们共享一些共同的属性(例如,灰度值)。在上图中,暗连接区域是斑点,斑点检测旨在识别和标记这些区域。 文末附相关测试代码的下载链接 SimpleBlobDetector 示例 OpenCV 提供了一种基于不同特征检测和过滤斑点的便捷方法。让…