异步事件库async
程序设计里,有一种称为事件驱动模型的方式。 比如说,一个网络服务器需要监听来自客户端的连接,以及处理客户端发送的请求, 没有客户端的时候,服务器是空闲的,它要等待事件发生然后进行处理。 事件驱动模式是非常常见,也是很基础的。
在linux上,事件驱动是通过epoll,poll等系统本身提供的机制,典型的项目包括nginx网络服务器,缓存服务redis等。
在Android系统上,很常见的looper/handler类库,就是基于epoll的封装,使得多线程的事件分发处理非常方便。
而fuchsia,对应的就是async库, 它是非常底层基础的类库,几乎所有应用都依赖于它,所以要作为第一优先级学习和分析。
async使用
使用async可以参考源码树里的示例,比如echo示例的源码。位于garnet/examples/fidl/echo_server_cpp/http://echo_server.cc
// 包含async库的头文件
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <string>
int main(int argc, const char** argv) {
// 创建loop对象
async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
bool quiet = (argc >= 2) && std::string("-q") == argv[1];
echo::EchoServerApp app(quiet);
loop.Run(); // loop对象的循环,程序会一直在loop里,执行不到下面的return语句, 除非调用loop.quit主动退出
return 0;
}
在编译配置BUILD.gn文件里需要加上对async库的依赖
executable("bin") {
output_name = "echo_server_cpp"
sources = [ "echo_server.cc" ]
deps = [
":lib",
"//zircon/public/lib/async-default", //有3个和async相关的lib
"//zircon/public/lib/async-loop-cpp",
"//zircon/public/lib/async-loop-default",
]
}
回想下linux epoll的事件监听, 原理上要包含:
- 事件监听机制的初始化(比如linux epoll,就需要调epoll_create函数)
- 把需要监听的文件描述符加入到监听机制里(比如linux上读网络数据,那就要把socket fd加入到epoll,用epoll_ctl)
- 然后当前线程在一个死循环里调用事件等待函数(epoll_wait), 当前线程就一直阻塞,直到有事件发生时返回,程序继续往下走,这时候我们要检查是那个描述符的什么事件,相应的进行业务上的处理, 处理完继续循环调等待函数。
epoll代码的主体流程类似于:
//创建 epoll
int epfd = epoll_crete(1000);
//将 listen_fd 添加进 epoll 中
epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fd, &listen_event);
while (1) {
//阻塞等待 epoll 中 的fd 触发
int active_cnt = epoll_wait(epfd, events, 1000, -1);
for (i = 0; i < active_cnt; i++) {
if (evnets[i].data.fd == listen_fd) {
//accept. 并且将新accept 的fd 加进epoll中.
} else if (events[i].events & EPOLLIN) {
//对此fd 进行读操作
} else if (events[i].events & EPOLLOUT) {
//对此fd 进行写操作
}
}
在对比看现在fuchsia的async. 就两行代码, 一行构造loop对象,一行是loop.run进入阻塞。 问题来了
1. loop对象能监听什么样的事件,事件怎么添加进来?
2. 有事件后,上层业务代码是怎么响应,上层业务和底层机制怎么打通, 完全没看到这部分代码?
接下来,探秘async
## async lib源码
代码位置在两个目录
第一个zircon/system/ulib/async-loop会编译成库async-loop-cpp和库async-loop-default
第二个zircon/system/ulib/async会编译成库async-cpp。 这个从编译BUILD.gn文件里能看到.
## async-loop源码
### c++层Loop类
找到loop对象定义和实现,分别位于cpp/loop.h, loop_wrapper.cc. 它是C++的类,但是实际只是一个c的结构体包装, 真正的逻辑是在async_loop_t结构里
class Loop {
public:
explicit Loop(const async_loop_config_t* config);
async_loop_t* loop() const { return loop_; }
async_dispatcher_t* dispatcher() const { return async_loop_get_dispatcher(loop_); }
void Shutdown();
zx_status_t Run(zx::time deadline = zx::time::infinite(), bool once = false);
zx_status_t RunUntilIdle();
void Quit();
zx_status_t ResetQuit();
async_loop_state_t GetState() const;
zx_status_t StartThread(const char* name = nullptr, thrd_t* out_thread = nullptr);
void JoinThreads();
private:
async_loop_t* loop_;
};
在Loop对象的构造函数里,创建async_loop_t实例
Loop::Loop(const async_loop_config_t* config) {
zx_status_t status = async_loop_create(config, &loop_);
ZX_ASSERT_MSG(status == ZX_OK, "status=%d", status);
}
在Loop对象的run方法里,调用async_loop_run
zx_status_t Loop::Run(zx::time deadline, bool once) {
return async_loop_run(loop_, deadline.get(), once);
}
### c层async_loop
#### 结构体定义
既然具体代码在c里,看c的头文件loop.h 和loop.c
typedef struct async_loop async_loop_t;
typedef struct async_loop {
async_dispatcher_t dispatcher; // 事件分发处理的函数结构体
async_loop_config_t config; // immutable 配置信息
zx_handle_t port; // immutable port是接收从kernel的事件的端口,类似linux epoll fd
zx_handle_t timer; // immutable 定时器的描述符
_Atomic async_loop_state_t state;
atomic_uint active_threads; // number of active dispatch threads 当前正在做事件处理的线程数
mtx_t lock; // guards the lists and the dispatching tasks flag 互斥锁
bool dispatching_tasks; // true while the loop is busy dispatching tasks
list_node_t wait_list; // most recently added first 被监听的对象列表
list_node_t task_list; // pending tasks, earliest deadline first, 需要执行的异步任务列表
list_node_t due_list; // due tasks, earliest deadline first 需要执行的超时异步任务列表
list_node_t thread_list; // earliest created thread first
list_node_t irq_list; // list of IRQs
list_node_t paged_vmo_list; // most recently added first
bool timer_armed; // true if timer has been set and has not fired yet
} async_loop_t;
struct async_loop是最核心的数据结构。
#### async_loop的创建过程
- 分配async_loop_t结构体内存
- 初始化各个链表
- 创建接收kernel上报事件的端口port
zx_status_t async_loop_create(const async_loop_config_t* config, async_loop_t** out_loop) {
async_loop_t* loop = calloc(1u, sizeof(async_loop_t)); // 分配内存
if (!loop)
return ZX_ERR_NO_MEMORY;
//初始化各个属性字段,和链表
atomic_init(&loop->state, ASYNC_LOOP_RUNNABLE);
atomic_init(&loop->active_threads, 0u);
loop->dispatcher.ops = (const async_ops_t*)&async_loop_ops;
loop->config = *config;
mtx_init(&loop->lock, mtx_plain);
list_initialize(&loop->wait_list);
list_initialize(&loop->irq_list);
list_initialize(&loop->task_list);
list_initialize(&loop->due_list);
list_initialize(&loop->thread_list);
list_initialize(&loop->paged_vmo_list);
// 创建监听端口, 事件是从kernel通过port上报的
zx_status_t status =
zx_port_create(config->irq_support ? ZX_PORT_BIND_TO_INTERRUPT : 0, &loop->port);
if (status == ZX_OK)
status = zx_timer_create(ZX_TIMER_SLACK_LATE, ZX_CLOCK_MONOTONIC, &loop->timer);
if (status == ZX_OK) {
*out_loop = loop;
if (loop->config.make_default_for_current_thread) {
loop->config.default_accessors.setter(&loop->dispatcher);
}
} else {
// Adjust this flag so we don't trip an assert trying to clear a default dispatcher we never
// installed.
loop->config.make_default_for_current_thread = false;
async_loop_destroy(loop);
}
return status;
}
#### 事件监听循环和分发过程
async_loop_runs是读取底层上报事件循环体。
zx_status_t async_loop_run(async_loop_t* loop, zx_time_t deadline, bool once) {
ZX_DEBUG_ASSERT(loop);
zx_status_t status;
atomic_fetch_add_explicit(&loop->active_threads, 1u, memory_order_acq_rel);// 当前线程进入循环体,+1
do {
status = async_loop_run_once(loop, deadline);
} while (status == ZX_OK && !once);
atomic_fetch_sub_explicit(&loop->active_threads, 1u, memory_order_acq_rel);// 当前线程退出循环体,-1
return status;
}
async_loop_run_once每次阻塞地读取一个事件,然后解析事件包,分发给对应函数处理。
static zx_status_t async_loop_run_once(async_loop_t* loop, zx_time_t deadline) {
async_loop_state_t state = atomic_load_explicit(&loop->state, memory_order_acquire);//检查当前状态
if (state == ASYNC_LOOP_SHUTDOWN)
return ZX_ERR_BAD_STATE;
if (state != ASYNC_LOOP_RUNNABLE)
return ZX_ERR_CANCELED;
zx_port_packet_t packet;//阻塞地从port上读取事件
zx_status_t status = zx_port_wait(loop->port, deadline, &packet);
if (status != ZX_OK)
return status;
if (packet.key == KEY_CONTROL) {// KEY_CONTROL=0
// Handle wake-up packets.
if (packet.type == ZX_PKT_TYPE_USER)
return ZX_OK;
// Handle task timer expirations. 定时器任务
if (packet.type == ZX_PKT_TYPE_SIGNAL_ONE && packet.signal.observed & ZX_TIMER_SIGNALED) {
return async_loop_dispatch_tasks(loop);
}
} else { // packet.key > 0
// Handle wait completion packets.
if (packet.type == ZX_PKT_TYPE_SIGNAL_ONE) {
async_wait_t* wait = (void*)(uintptr_t)packet.key;
mtx_lock(&loop->lock);
list_delete(wait_to_node(wait));
mtx_unlock(&loop->lock);
return async_loop_dispatch_wait(loop, wait, packet.status, &packet.signal);
}
// Handle queued user packets.
if (packet.type == ZX_PKT_TYPE_USER) {
async_receiver_t* receiver = (void*)(uintptr_t)packet.key;
return async_loop_dispatch_packet(loop, receiver, packet.status, &packet.user);
}
// Handle guest bell trap packets.
if (packet.type == ZX_PKT_TYPE_GUEST_BELL) {
async_guest_bell_trap_t* trap = (void*)(uintptr_t)packet.key;
return async_loop_dispatch_guest_bell_trap(loop, trap, packet.status, &packet.guest_bell);
}
// Handle interrupt packets.
if (packet.type == ZX_PKT_TYPE_INTERRUPT) {
async_irq_t* irq = (void*)(uintptr_t)packet.key;
return async_loop_dispatch_irq(loop, irq, packet.status, &packet.interrupt);
}
// Handle pager packets.
if (packet.type == ZX_PKT_TYPE_PAGE_REQUEST) {
async_paged_vmo_t* paged_vmo = (void*)(uintptr_t)packet.key;
return async_loop_dispatch_paged_vmo(loop, paged_vmo, packet.status, &packet.page_request);
}
}
ZX_DEBUG_ASSERT(false);
return ZX_ERR_INTERNAL;
}
事件类型涵盖
- 定时器任务 由async_loop_dispatch_tasks处理
- 等待变量wait 由async_loop_dispatch_wait处理
- 数据包事件 由async_loop_dispatch_packet处理
- irq事件 由async_loop_dispatch_irq处理
- 内存共享事件 由async_loop_dispatch_paged_vmo处理
#### 如何添加事件监听
等待变量wait的监听有这两个函数操作.
// 添加该wait的监听
static zx_status_t async_loop_begin_wait(async_dispatcher_t* async, async_wait_t* wait) {
async_loop_t* loop = (async_loop_t*)async;//检查当前状态
if (atomic_load_explicit(&loop->state, memory_order_acquire) == ASYNC_LOOP_SHUTDOWN)
return ZX_ERR_BAD_STATE;
mtx_lock(&loop->lock);
// 添加监听object, zx_object_wait_async是系统调用
zx_status_t status =
zx_object_wait_async(wait->object, loop->port, (uintptr_t)wait, wait->trigger, wait->options);
if (status == ZX_OK) { // 把该wait加到列表里
list_add_head(&loop->wait_list, wait_to_node(wait));
} else {
ZX_ASSERT_MSG(status == ZX_ERR_ACCESS_DENIED, "zx_object_wait_async: status=%d", status);
}
mtx_unlock(&loop->lock);
return status;
}
// 取消监听
static zx_status_t async_loop_cancel_wait(async_dispatcher_t* async, async_wait_t* wait) {
async_loop_t* loop = (async_loop_t*)async;
mtx_lock(&loop->lock);
// First, confirm that the wait is actually pending.,从列表里找到要删除掉结点
list_node_t* node = wait_to_node(wait);
if (!list_in_list(node)) {
mtx_unlock(&loop->lock);
return ZX_ERR_NOT_FOUND;
}
// Next, cancel the wait. This may be racing with another thread that
// has read the wait's packet but not yet dispatched it. So if we fail
// to cancel then we assume we lost the race.
// zx_port_cancel 是系统调用
zx_status_t status = zx_port_cancel(loop->port, wait->object, (uintptr_t)wait);// 取消监听
if (status == ZX_OK) {
list_delete(node);
} else {
ZX_ASSERT_MSG(status == ZX_ERR_NOT_FOUND, "zx_port_cancel: status=%d", status);
}
mtx_unlock(&loop->lock);
return status;
}
其中添加wait事件监听需要调用者构造一个async_wait_t结构
struct async_wait {
// Private state owned by the dispatcher, initialize to zero with |ASYNC_STATE_INIT|.
async_state_t state;
// The wait's handler function.
async_wait_handler_t* handler;
// The object to wait for signals on.
zx_handle_t object;
// The set of signals to wait for.
zx_signals_t trigger;
// Wait options, see zx_object_wait_async().
uint32_t options;
};
发送和取消定时器异步任务的两个函数操作
static zx_status_t async_loop_post_task(async_dispatcher_t* async, async_task_t* task) {
async_loop_t* loop = (async_loop_t*)async;
ZX_DEBUG_ASSERT(loop);
ZX_DEBUG_ASSERT(task);
//检查当前状态
if (atomic_load_explicit(&loop->state, memory_order_acquire) == ASYNC_LOOP_SHUTDOWN)
return ZX_ERR_BAD_STATE;
mtx_lock(&loop->lock);
async_loop_insert_task_locked(loop, task);//加入task到链表,在这个链表里的task是按照时间顺序排列的,最新执行的放最前面
if (!loop->dispatching_tasks && task_to_node(task)->prev == &loop->task_list) {
//如果该任务是task list头部元素,重新设置定时器超时时间
// Task inserted at head. Earliest deadline changed.
async_loop_restart_timer_locked(loop);
}
mtx_unlock(&loop->lock);
return ZX_OK;
}
// 取消定时器任务
static zx_status_t async_loop_cancel_task(async_dispatcher_t* async, async_task_t* task) {
async_loop_t* loop = (async_loop_t*)async;
// 从task列表里找到要删除的task
mtx_lock(&loop->lock);
list_node_t* node = task_to_node(task);
if (!list_in_list(node)) {
mtx_unlock(&loop->lock);
return ZX_ERR_NOT_FOUND;
}
// Determine whether the head task was canceled and following task has
// a later deadline. If so, we will bump the timer along to that deadline.
// 如果该task是列表的首个元素,
bool must_restart =
!loop->dispatching_tasks && node->prev == &loop->task_list &&
(node->next == &loop->task_list || node_to_task(node->next)->deadline > task->deadline);
list_delete(node);// 删除结点
if (must_restart)// 重新设置定时器超时时间
async_loop_restart_timer_locked(loop);
mtx_unlock(&loop->lock);
return ZX_OK;
}
往端口发送数据包
static zx_status_t async_loop_queue_packet(async_dispatcher_t* async, async_receiver_t* receiver,
const zx_packet_user_t* data) {
async_loop_t* loop = (async_loop_t*)async;
//状态检查
if (atomic_load_explicit(&loop->state, memory_order_acquire) == ASYNC_LOOP_SHUTDOWN)
return ZX_ERR_BAD_STATE;
// 构造包
zx_port_packet_t packet = {.key = (uintptr_t)receiver, .type = ZX_PKT_TYPE_USER, .status = ZX_OK};
if (data)
packet.user = *data;
// 发送到端口上,zx_port_queue是系统调用
return zx_port_queue(loop->port, &packet);
}
其它类型的中断事件irq,和内存 vmo就不列举了
static zx_status_t async_loop_bind_irq(async_dispatcher_t* dispatcher, async_irq_t* irq);
static zx_status_t async_loop_unbind_irq(async_dispatcher_t* dispatcher, async_irq_t* irq);
static zx_status_t async_loop_create_paged_vmo(async_dispatcher_t* async,
async_paged_vmo_t* paged_vmo, uint32_t options,
zx_handle_t pager, uint64_t vmo_size,
zx_handle_t* vmo_out);
static zx_status_t async_loop_detach_paged_vmo(async_dispatcher_t* dispatcher,
async_paged_vmo_t* paged_vmo);
#### 事件处理过程
等待变量wait, 直接调用了在handler函数来处理。这个handler是由调用者在添加事件监听时,构造async_wait_t传入
static zx_status_t async_loop_dispatch_wait(async_loop_t* loop, async_wait_t* wait,
zx_status_t status, const zx_packet_signal_t* signal) {
async_loop_invoke_prologue(loop);
wait->handler((async_dispatcher_t*)loop, wait, status, signal);
async_loop_invoke_epilogue(loop);
return ZX_OK;
}
类似的,定时器任务处理也是通过由调用者在添加事件监听时,构造async_task_t传入handler函数
static void async_loop_dispatch_task(async_loop_t* loop, async_task_t* task, zx_status_t status) {
// Invoke the handler. Note that it might destroy itself.
async_loop_invoke_prologue(loop);
task->handler((async_dispatcher_t*)loop, task, status);
async_loop_invoke_epilogue(loop);
}