zircon的event实现及async loop机制

zircon中的event是一种异步并发的机制。用户空间可以对8个信号bit位进行设置、清除和等待。
event的创建接口为zx_event_create()
zx_event_create
    sys_event_create
        EnforceBasicPolicy //判断当前进程是否有创建event的权限
        EventDispatcher::Create //用默认权限创建EventDispatcher对象
        event_out->make //传递给用户态event句柄
发送和清除信号的接口为zx_object_signal()
zx_object_signal
    sys_object_signal
        GetDispatcherWithRights //获取handle对应的dispatcher(EventDispatcher对象)
            dispatcher->user_signal_self
                SoloDispatcher::user_signal_self
                    Dispatcher::UpdateState
                        Dispatcher::UpdateStateHelper
                            StateObserver::OnStateChange 
                                TODO:1
StateObserver是一个基类,这里会遍历此dispatcher的所有observer,调用其OnStateChange方法。
dispatcher的observer对象的添加流程需要结合另一个对象分析——async::WaitMethod
WaitMethod继承自WaitBase,它可以保存异步等待的上下文及其handler程序。
WaitBase有两个私有成员:async_wait_t wait_;async_dispatcher_t* dispatcher_(作用后面分析)
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;
};
WaitMethod在实例化时会将等待的对象(object)、事件(trigger)及事件回调(handler)设置好。
然后调用WaitBase::Begin方法,开始等待事件:
WaitBase::Begin
    async_begin_wait
        dispatcher->ops->v1.begin_wait
            async_loop_begin_wait
                首先会将async_dispatcher_t强转为async_loop_t(前者为后者的第一个成员);
                zx_object_wait_async //这里会将wait的object(以event为例)、trigger以及loop的port作为参数传入。
                    sys_object_wait_async 
                        PortDispatcher::MakeObserver
                            PortObserver //构造PortObserver对象
                            observers_.push_front //添加到port的observers_列表
                            dispatcher->AddObserver //这里会调用event的dispatcher的AddObserver
                                Dispatcher::AddObserver
                                    Dispatcher::AddObserverHelper
                                        observer->OnInitialize //需要注意,这里会将上次保存的signals_信号(见Dispatcher::UpdateStateHelper方法)作为初始值传入,触发一次queue操作
                                            PortObserver::OnInitialize
                                                PortObserver::MaybeQueue
                                                    【PortDispatcher::Queue
                                                        sema_.Post //释放信号量,会唤醒等待队列】
                                        observers_.push_front //添加到event的observers_列表
                list_add_head //加入loop的等待列表
分析到这里,我们可以看出上一节中遍历event dispatcher的所有observer对象,并调用其OnStateChange方法,将会调用到这里PortObserver对象的OnStateChange方法,继续:
TODO:1 PortObserver::OnStateChange
    PortObserver::MaybeQueue
        PortDispatcher::Queue
            sema_.Post //释放信号量,会唤醒等待队列

前面分析了event信号的发送流程,还缺少一个接收流程。分析接收流程,可能避不开一个对象——async::Loop,因为,前面WaitBase::Begin流程的关键入参dispatcher就由loop对象而来。
async::Loop是异步dispatch loop的C++封装。
创建:
async_loop_create
    loop->dispatcher.ops = &async_loop_ops; //设置dispatcher的ops回调
    zx_port_create //创建port对象
    zx_timer_create //创建timer对象
    
运行:
async_loop_run
    async_loop_run_once
        zx_port_wait //这里会阻塞等待port对象上的包到达
            sys_port_wait
                PortDispatcher::Dequeue
                    sema_.Wait //在port上等待信号量
                packet_out.copy_to_user //将包拷贝到用户态
        async_loop_dispatch_wait //还可能是其他几种,这里暂时以async_loop_dispatch_wait为例
            wait->handler //执行wait的回调,这里就会执行WaitMethod中的事件handler

到这里,应该基本就清楚了:

首先会创建一个loop对象,loop对象内嵌一个port对象;
然后,loop调用run方法,在port上无限阻塞等待包到达后进行包分发、回调。

另一方面,event对象从loop对象获取dispatcher,借助WaitMethod机制,在开始等待(Begin)时,创建PortObserver,
并将其同时添加到loop对象的port和event本身的observer中。

当event需要发信号时,调用zx_object_signal,并最终陷入内核遍历调用其EventDispatcher的observer的OnStateChange方法;
这里就会调用到PortObserver::OnStateChange,并释放信号量,唤醒在port上等待的loop分发流程,执行event通过WaitMethod机制注册的回调handler;
整个流程基本完成。

需要注意的是,目前异步loop等待机制只支持一种option参数——ZX_WAIT_ASYNC_ONCE,这将导致每次发送信号,调用OnStateChange后自动删除observer对象,
即wait一次,创建observer,然后接收到一个包后删除observer;下次需要重新来一次这个流程:
WaitBase::Begin一次,其回调执行一次;如果需要回调再执行,需要再次执行WaitBase::Begin!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值