news 2026/9/12 10:14:37

Linux PipeWire深度解析之pw_main_loop_get_loop调用流程与实战(八十五)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux PipeWire深度解析之pw_main_loop_get_loop调用流程与实战(八十五)

简介:CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址:Audio工程师进阶系列原创干货持续更新中……】🚀
Android多媒体专栏地址:多媒体系统工程师系列原创干货持续更新中……】🚀
专题一 二:AAOS车载系统+AOSP14系统攻城狮入门视频实战课🚀
专题三:Android14 Binder之HIDL与AIDL通信实战课🚀
专题四:Android15快速自定义与集成音效实战课🚀
专题五:Android15音频策略实战课🚀
专题六:Android15音频性能实战课(无声/杂音/断音/爆音实战案例)🚀

人生格言:人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮


🍉🍉🍉文章目录🍉🍉🍉

  • 🌻1.前言
      • 要点概括
  • 🌻2.应用场景与用法
    • 函数原型
    • 参数说明
    • 返回值
    • 应用场景
  • 🌻3.调用流程剖析
    • 🌻3.1核心步骤
    • 🌻3.2调用流程图
    • 🌻3.3生命周期图
  • 🌻4.实战应用案例
  • 🌻5.一句话总结

🌻1.前言

本篇目的:

Linux PipeWire深度解析之pw_main_loop_get_loop调用流程与实战。

要点概括

  • 核心功能:取得pw_main_loop内部持有的pw_loop指针,让Context、事件源和后续任务绑定到同一个事件循环。

  • 工作机制:该函数不创建新的Loop,只返回pw_main_loop对象内部已经创建好的pw_loop。

  • 典型用途:创建pw_context、注册signal/timer/io/defer事件源、统一驱动PipeWire客户端主循环。

pw_main_loop_get_loop的本质是“从主循环封装对象中取出底层事件循环”。它不是运行主循环的接口,也不是创建Loop的接口。

pw_main_loop_new负责创建pw_main_loop对象,并在内部准备pw_loop。pw_main_loop_get_loop只负责暴露这个内部pw_loop指针。pw_main_loop_run才负责进入事件循环并驱动事件分发。

它和pw_main_loop_run不同。pw_main_loop_run会阻塞当前线程并持续处理事件;pw_main_loop_get_loop只返回指针,不会进入事件循环。

它和pw_main_loop_quit也不同。pw_main_loop_quit用于请求主循环退出;pw_main_loop_get_loop不改变运行状态。

它和pw_loop_new也不同。pw_loop_new创建独立的pw_loop对象;pw_main_loop_get_loop返回的是pw_main_loop内部已经拥有的pw_loop,调用方不能销毁这个返回指针。

🌻2.应用场景与用法

pw_main_loop_get_loop

是PipeWire Main Loop API中用于获取底层pw_loop的接口。

它位于PipeWire客户端初始化主链路中。应用先通过pw_main_loop_new创建主循环对象,再通过pw_main_loop_get_loop取得内部pw_loop,然后把该pw_loop传给pw_context_new,保证Context、Core连接、Registry事件、Stream事件和自定义事件源都在同一个事件循环中调度。

pw_main_loop_get_loop用于从pw_main_loop中取得内部pw_loop指针。

函数原型

structpw_loop*pw_main_loop_get_loop(structpw_main_loop*loop);

参数说明

structpw_main_loop*loop;

loop表示已经通过pw_main_loop_new创建的主循环对象。

该对象负责管理PipeWire客户端常用的主循环封装。它内部持有一个pw_loop,pw_main_loop_get_loop返回的就是这个内部pw_loop。

调用前需要保证loop有效。不能把已经destroy的pw_main_loop继续传给该函数。

返回值

成功时返回:

structpw_loop*

表示pw_main_loop内部持有的底层事件循环对象。

该返回值是借用指针,不表示调用方获得所有权。调用方不能直接释放它,也不能在pw_main_loop_destroy之后继续使用它。

返回NULL通常表示传入对象无效,或者主循环对象没有正确创建。实际开发中,应优先保证pw_main_loop_new成功,再调用pw_main_loop_get_loop。

应用场景

第一类场景是创建PipeWire Context。

PipeWire客户端通常先创建pw_main_loop,再通过pw_main_loop_get_loop取得pw_loop,最后把pw_loop传给pw_context_new。这样Context后续产生的事件可以由同一个主循环驱动。

第二类场景是注册事件源。

应用可以基于返回的pw_loop注册signal、timer、io、defer等事件源。这些事件源和PipeWire内部事件运行在同一个事件循环中,方便统一调度。

第三类场景是客户端程序主循环封装。

简单PipeWire客户端不一定直接管理pw_loop,可以使用pw_main_loop作为上层封装。pw_main_loop_get_loop提供了向底层事件系统对接的入口。

第四类场景是Stream事件调度。

应用创建Context并连接PipeWire服务端后,后续Registry事件、Stream状态变化、process回调等都依赖事件循环驱动。pw_main_loop_get_loop虽然不直接处理Stream数据,但它决定了这些事件挂在哪个Loop上运行。

🌻3.调用流程剖析

🌻3.1核心步骤

1.应用调用pw_init初始化PipeWire库环境。

2.应用调用pw_main_loop_new创建pw_main_loop对象。

3.pw_main_loop_new内部创建并保存一个pw_loop对象。

4.应用调用pw_main_loop_get_loop取得pw_main_loop内部的pw_loop指针。

5.应用把该pw_loop传给pw_context_new创建PipeWire Context。

6.Context后续基于同一个pw_loop处理连接、Registry、Proxy和Stream事件。

7.应用也可以基于该pw_loop注册timer、signal、io、defer等事件源。

8.应用调用pw_main_loop_run进入主循环。

9.pw_main_loop_run驱动底层pw_loop进行poll和dispatch。

10.应用调用pw_main_loop_quit请求主循环退出。

11.应用调用pw_main_loop_destroy销毁主循环对象。

12.pw_main_loop_destroy完成后,pw_main_loop_get_loop返回过的pw_loop指针失效。

🌻3.2调用流程图

🌻3.3生命周期图

🌻4.实战应用案例

下面以“创建PipeWire客户端主循环和Context”为例,说明pw_main_loop_get_loop在真实开发中的位置。

这个案例只保留主链路:创建主循环、取得内部pw_loop、创建Context、连接PipeWire服务端、运行主循环。

#include<pipewire/pipewire.h>structapp_data{structpw_main_loop*main_loop;structpw_context*context;structpw_core*core;};staticvoidinit_pipewire_client(structapp_data*data){structpw_loop*loop;pw_init(NULL,NULL);data->main_loop=pw_main_loop_new(NULL);if(data->main_loop==NULL)return;/* * 此API在主链路作用: * 从pw_main_loop中取得内部pw_loop, * 后续Context和事件源都绑定到这个loop。 */loop=pw_main_loop_get_loop(data->main_loop);if(loop==NULL)return;/* * 此API在主链路作用: * 创建PipeWire Context,并使用上面取得的pw_loop驱动Context事件。 */data->context=pw_context_new(loop,NULL,0);if(data->context==NULL)return;/* * 此API在主链路作用: * 通过Context连接PipeWire服务端,得到Core代理对象。 */data->core=pw_context_connect(data->context,NULL,0);if(data->core==NULL)return;/* * 此API在主链路作用: * 进入主循环,驱动Core、Registry、Stream等事件回调执行。 */pw_main_loop_run(data->main_loop);}staticvoiddestroy_pipewire_client(structapp_data*data){if(data->core!=NULL)pw_core_disconnect(data->core);if(data->context!=NULL)pw_context_destroy(data->context);if(data->main_loop!=NULL)pw_main_loop_destroy(data->main_loop);pw_deinit();}

这个案例中,pw_main_loop_get_loop不负责连接PipeWire服务端,也不负责运行事件循环。它只是把pw_main_loop内部的pw_loop取出来,交给pw_context_new使用。

实际开发中,最容易出现的问题是把pw_main_loop和pw_loop的所有权搞混。

pw_main_loop_get_loop返回的pw_loop不需要手动destroy。它由pw_main_loop管理。应用只需要在最后调用pw_main_loop_destroy,内部资源会跟随主循环对象一起释放。

另一个常见问题是创建了多个Loop。比如Context使用一个Loop,自定义timer使用另一个Loop,最后只有一个Loop被run。这样部分事件永远不会被调度。工程上建议简单客户端优先使用同一个pw_main_loop,并通过pw_main_loop_get_loop取得同一个pw_loop。

如果只是创建普通Stream客户端,典型结构通常是:

data.main_loop=pw_main_loop_new(NULL);loop=pw_main_loop_get_loop(data.main_loop);data.context=pw_context_new(loop,NULL,0);data.core=pw_context_connect(data.context,NULL,0);data.stream=pw_stream_new(data.core,"playback",props);pw_stream_connect(data.stream,PW_DIRECTION_OUTPUT,PW_ID_ANY,flags,params,n_params);pw_main_loop_run(data.main_loop);

在这条链路中,pw_main_loop_get_loop处在主循环创建之后、Context创建之前。它是PipeWire客户端从“主循环封装层”进入“底层事件循环层”的连接点。

🌻5.一句话总结

pw_main_loop_get_loop是PipeWire主循环链路中的取Loop接口:它从pw_main_loop中返回内部pw_loop指针,用于创建Context和注册事件源,但不创建Loop、不运行Loop,也不转移Loop所有权。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 21:46:32

RL训练瓶颈在推理:独立扩展推理集群的架构与实践

先给结论&#xff1a;RL 的真正瓶颈是推理&#xff0c;不是训练 这次我们聊一个偏工程架构&#xff0c;而不是具体工具的主题&#xff1a;强化学习&#xff08;RL&#xff09;在 LLM 上训练时&#xff0c;最容易被忽略的性能瓶颈&#xff0c;是推理&#xff08;Inference&#…

作者头像 李华
网站建设 2026/8/30 21:16:34

三年Android开发大厂面试经验分享,让你扫清Android面试障碍

怎样快速突破初级瓶颈&#xff0c;变身高级开发&#xff1f;怎样在短时间内提高自我身价&#xff0c;月薪提高50%&#xff1f;你是否是个代码高手&#xff0c;面试中却发挥不出来&#xff0c;想进阶却摸不着头脑。博主在互联网行业摸爬滚打&#xff0c;百面成钢。特来总结与分享…

作者头像 李华
网站建设 2026/8/30 13:52:46

【2015-01-17】GNU Readline Library编译及简单分析

[历史归档] 本文原发布于 cstriker1407.info 个人博客&#xff0c;内容为历史存档&#xff0c;仅供参考。 发布时间&#xff1a; 2015-01-17 &#xff5c; 标题&#xff1a;GNU Readline Library编译及简单分析 &#xff5c; 分类&#xff1a; 编程 / C && C &…

作者头像 李华
网站建设 2026/9/2 2:21:13

【2015-01-16】linux的id命令简单笔记

[历史归档] 本文原发布于 cstriker1407.info 个人博客&#xff0c;内容为历史存档&#xff0c;仅供参考。 发布时间&#xff1a; 2015-01-16 &#xff5c; 标题&#xff1a;linux的id命令简单笔记 &#xff5c; 分类&#xff1a; 操作系统 / linux &#xff5c; 标签&…

作者头像 李华
网站建设 2026/9/1 22:19:09

单片机计算机毕设之基于 STM32、ESP-01S 的车载安防数据采集预警终端开发 基于 STM32 单片机的车辆温度监测与防盗报警系统设计(010705)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机&#xff0c;Java、小程序技术领域和毕业项目实战 ✌️…

作者头像 李华