点击下方👇关注Android系统攻城狮
第195篇原创文章
每日充电:OS+MultiMedia学习之旅
在PulseAudio中,Mainloop 是整个系统能够运转的的核心驱动。上一篇我们介绍了Hook机制,其实Hook机制解决的是:事件发生后通知谁。而Mainloop机制解决的是:什么时候有事件发生、谁来等待事件、谁来分发事件、最终由谁执行 Callback。
01


先从系统层面看Mainloop在 PulseAudio中的位置,应用程序通过libpulse.so与PulseAudio守护进程通信,守护进程内部由pa_mainloop负责事件循环与分发工作,并与pa_core核心模块交互管理。

02


Mainloop机制本质上是一种:事件等待 - 事件分发模型。它不直接处理业务逻辑,而是负责把系统中发生的事件等到,然后把事件分发给对应callback。

03


pa_mainloop是Mainloop的核心数据结构对象,内部维护了IO事件、定时器、延迟事件等链表,pollfd数组及状态信息,驱动整个事件循环的运行。

以下是核心数据结构字段表功能:

04


PulseAudio通过pa_mainloop_api暴露一组抽象的事件循环接口,而pa_mainloop提供这组接口的默认实现。

05


守护进程创建pa_mainloop,获取API后传递给pa_core,模块随后注册各类事件,最终事件循环开始持续运行。

06


pa_mainloop每次执行一次迭代,会严格分为三个阶段执行:prepare、poll、dispatch。

07


prepare阶段的目标是为本次监听事件做准备,确定监听的事件类型和超时时间。

08


poll或者ppoll(实际调用)是真正执行监控事件的,它会进入循环监听的状态。

ppoll核心代码:
#ifdef HAVE_PPOLL //走此分支structtimespects;m->poll_func_ret = ppoll( m->pollfds, m->n_pollfds, m->prepared_timeout == PA_USEC_INVALID ? NULL : pa_timespec_store(&ts, m->prepared_timeout),NULL);#elsem->poll_func_ret = pa_poll(m->pollfds, m->n_pollfds,usec_to_timeout(m->prepared_timeout));#endif09


根据返回的结果和状态,按优先级分发事件。defer事件优先级最高,其次是定时事件,最后处理fd的IO事件。


10


IO事件从注册到最终回调,经历的完整过程如下所示。

PA_LLIST_PREPEND(pa_mainloop, io_events, e);pa_mainloop->rebuild_pollfds = true;pa_mainloop_wakeup(pa_mainloop);11


Time事件用于定时调度,到期后默认先被禁用,需要在回调中决定是否重新启动。


12


Defer事件用于把一段回调尽快执行,但是没有立即执行。它在下一轮的循环时被发现并分发,执行后会自动清除,避免递归调用。

13


pa_mainloop的核心是一个极简的事件循环,负责等待并执行控制事件。

14


pa_mainloop是PulseAudio的控制循环内核,围绕不同类型事件统一等待与分发。

简而言之,PulseAudio Mainloop的本质:就是把事件等待与事件分发统一抽象起来,用一个控制循环驱动整个上层控制逻辑。
若读者朋友发现有错误、疑问的地方,或者好的建议,欢迎拍砖!!!
精彩文章合集
专栏推荐