NativeLooper构造
本文承接 NativeMessageQueue封装,只研究 libutils::Looper 从“尚未存在”到“可以等待事件”的构造过程。核心问题是:构造函数初始化了哪些不可变状态,eventfd 为什么先于 epoll,唤醒 FD 如何成为 epoll 的固定节点,线程局部绑定和 FD 请求表又怎样连接到后续 pollOnce()。
1. 字段分工
源码文件:system/core/libutils/include/utils/Looper.h
相关字段:mAllowNonCallbacks、mWakeEventFd、mEpollFd、mRequests
const bool mAllowNonCallbacks;
android::base::unique_fd mWakeEventFd;
mutable std::mutex mLock;
std::atomic<bool> mPolling;
android::base::unique_fd mEpollFd;
bool mEpollRebuildRequired;
std::unordered_map<SequenceNumber, Request> mRequests;
std::unordered_map<int, SequenceNumber> mSequenceNumberByFd;
std::atomic<uint64_t> mRequestsGeneration;
SequenceNumber mNextRequestSeq;
std::vector<Response> mResponses;
size_t mResponseIndex;
nsecs_t mNextMessageUptime;构造阶段真正要建立的是三个基础条件:有一个可写入的 wake FD,有一个把 wake FD 注册进去的 epoll FD,以及一组记录未来 FD 请求的空容器。mResponses、mNextMessageUptime 等字段服务于后续 poll,不代表构造时已经有事件或 native 消息。
2. 构造入口
源码文件:system/core/libutils/Looper.cpp
相关函数:Looper::Looper()
constexpr uint64_t WAKE_EVENT_FD_SEQ = 1;
static const int EPOLL_MAX_EVENTS = 16;
Looper::Looper(bool allowNonCallbacks)
: mAllowNonCallbacks(allowNonCallbacks),
mSendingMessage(false), mPolling(false),
mEpollRebuildRequired(false), mRequestsGeneration(0),
mNextRequestSeq(WAKE_EVENT_FD_SEQ + 1),
mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {
mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
LOG_ALWAYS_FATAL_IF(mWakeEventFd.get() < 0,
"Could not make wake event fd: %s", strerror(errno));
std::scoped_lock _l(mLock);
rebuildEpollLocked();
}初始化列表先把控制状态设为“没有发送消息、没有 poll、没有待重建”;序列号从 wake FD 保留值之后开始。构造体函数再创建 wake FD,并在锁内建立 epoll 集合。allowNonCallbacks 只决定之后能否注册没有 callback 的 FD,不改变 wake FD 的注册。
3. Wake FD
源码文件:system/core/libutils/Looper.cpp
相关函数:构造函数、wake()
mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
LOG_ALWAYS_FATAL_IF(mWakeEventFd.get() < 0,
"Could not make wake event fd: %s", strerror(errno));eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC) 创建计数型 FD:写入表示有唤醒请求,读取消费计数;非阻塞避免 wake/awoken 卡住,CLOEXEC 避免 FD 带入后续 exec。unique_fd 接管内核 FD 的关闭责任。
4. Epoll初始集
源码文件:system/core/libutils/Looper.cpp
相关函数:rebuildEpollLocked()
void Looper::rebuildEpollLocked() {
if (mEpollFd >= 0) mEpollFd.reset();
mEpollFd.reset(epoll_create1(EPOLL_CLOEXEC));
LOG_ALWAYS_FATAL_IF(mEpollFd < 0,
"Could not create epoll instance: %s", strerror(errno));
epoll_event wakeEvent = createEpollEvent(EPOLLIN, WAKE_EVENT_FD_SEQ);
int result = epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD,
mWakeEventFd.get(), &wakeEvent);
LOG_ALWAYS_FATAL_IF(result != 0,
"Could not add wake event fd to epoll instance: %s", strerror(errno));
for (const auto& [seq, request] : mRequests) {
epoll_event eventItem = createEpollEvent(request.getEpollEvents(), seq);
epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, request.fd, &eventItem);
}
}重建先关闭旧 epoll,再创建新实例,固定加入 wake FD,最后恢复 mRequests 中的业务请求。构造第一次调用时请求表为空,所以至少得到一个只监听 wake FD 的 epoll 集。
5. 锁与RAII
构造函数在调用 rebuildEpollLocked() 前取得 mLock,函数名中的 Locked 表明它要求调用者持锁。std::scoped_lock 负责离开作用域时释放锁;unique_fd 负责构造失败或析构时关闭已取得的内核 FD。这里没有手写 close 的补偿路径。
6. 线程绑定
源码文件:system/core/libutils/Looper.cpp
相关函数:getForThread()、setForThread()、prepare()
thread_local static sp<Looper> gThreadLocalLooper;
void Looper::setForThread(const sp<Looper>& looper) {
gThreadLocalLooper = looper;
}
sp<Looper> Looper::getForThread() {
return gThreadLocalLooper;
}
sp<Looper> Looper::prepare(int opts) {
bool allowNonCallbacks = opts & PREPARE_ALLOW_NON_CALLBACKS;
sp<Looper> looper = Looper::getForThread();
if (looper == nullptr) {
looper = sp<Looper>::make(allowNonCallbacks);
Looper::setForThread(looper);
}
return looper;
}线程绑定发生在 native gThreadLocalLooper,不是 Java Looper.sThreadLocal。NativeMessageQueue 构造时也会复用或创建同一个 native Looper。
7. 参数语义
源码文件:system/core/libutils/include/utils/Looper.h
相关常量:PREPARE_ALLOW_NON_CALLBACKS
enum {
PREPARE_ALLOW_NON_CALLBACKS = 1 << 0
};
Looper(bool allowNonCallbacks);allowNonCallbacks 允许 addFd() 注册空 callback,调用者随后自己检查 pollOnce() 返回值;关闭时,空 callback 注册会被拒绝。它不是“是否允许 Looper 运行”,也不是 Java MessageQueue.mQuitAllowed。
8. 序列号初值
源码文件:system/core/libutils/Looper.cpp
相关函数:构造函数、addFd()
constexpr uint64_t WAKE_EVENT_FD_SEQ = 1;
mNextRequestSeq(WAKE_EVENT_FD_SEQ + 1)
if (mNextRequestSeq == WAKE_EVENT_FD_SEQ) mNextRequestSeq++;
const SequenceNumber seq = mNextRequestSeq++;wake FD 使用保留序列号,业务 FD 从后续序列号开始。epoll 返回时通过序列号区分 wake 事件和业务请求,避免直接把可复用的 FD 数值当作稳定身份。
9. 构造失败
eventfd()、epoll_create1() 或把 wake FD 加入 epoll 失败,当前源码使用 LOG_ALWAYS_FATAL_IF。这表示等待器无法建立时不会返回一个空 Looper 让上层继续。普通业务 FD 的 addFd() 失败则返回 -1,是另一条运行时路径。
10. 首次状态
构造完成后:mAllowNonCallbacks 固定;wake eventfd 已创建;epoll 已监听 wake FD;请求表为空;请求代数为 0;下一个业务序列号为 3;没有 response 可返回;mNextMessageUptime 为 LLONG_MAX。Looper 已具备等待和唤醒能力,但尚未注册业务 FD 或 native Message。
11. 动手验证
rg -n "Looper::Looper|eventfd|rebuildEpollLocked|WAKE_EVENT_FD_SEQ" \
system/core/libutils/Looper.cpp
rg -n "gThreadLocalLooper|Looper::prepare|setForThread|getForThread" \
system/core/libutils/Looper.cpp按 eventfd → epoll_create1 → EPOLL_CTL_ADD(wake) → 请求表恢复的顺序阅读,再比较 Looper::prepare() 和 NativeMessageQueue 的线程绑定入口。
12. 边界说明
本文不展开 pollInner() 的超时、事件分发和 wake 读取,也不展开 addFd() 的 FD 复用修复;这些行为建立在本文构造出的 wake/epoll 初始状态上。构造源码能支持资源、锁、序列号和失败策略,不能据此推断一次具体 poll 的返回结果。
