写点什么

Code Like Sync, Works Like Async

  • 2020-10-20
  • 本文字数:2042 字

    阅读完需:约 7 分钟

Code Like Sync, Works Like Async

前言.

打从敲下"Hello World!",咱们算入行了。我开始写代码,和用计算器差不多:


  • 输入:1 + 1

  • 结果:2


代码一路顺着走,不开叉。


生涯第 1 个波折,是学到条件判断,像这样:


  • a = 1,b = 1

  • if a + b = 2 print "这都知道?"else print “答对了”


代码开始有不同走向,有点绕,还能驾驭。


再后来就遇到人生大哉问:妈和媳妇一起掉河里,你救谁?


翻译一下,如何同时运行代码 A 和代码 B(并行)?


为一起救,我学过各种泳姿:


  • 开始用 “定时器/软中断”挺好,不过随着媳妇数(代码块)的增多,猝!

  • 后来折腾“事件驱动/状态机”,就活在连跳/回调地狱里,最终为个 delay 而累猝!

  • 最后“多线程”还行…还活着。


焦头烂额,终于 hold 住。


可人生问题哪止这些,后来更大问题是 3 字:“没钱”


“多线程”虽好,太费钱(资源消耗大)、太折腾(竞争成本高),很多场景受限:


  • 浏览器:没有多线程

  • 嵌入式 MCU:实时性要求高、RAM 受限,甚至没有 RTOS

  • 大链接数 server:微信后台

  • 游戏:魔兽世界


吐血。


小品文已过,咱们言归正传。

1.

近些年,很多编程语言都修订标准,新增 2 个关键字 async/await:


  • 直接包含:C#/JavaScript/Rust/Dart

  • 其它语言(golang/erlang/lua…)没直接包含,也提供类似机制 ,比如 Go goroutine


所有目的,都是为更好的支持异步编程,不约而同的加强 Coroutine。


Coroutine(协程)是老东西(比 UNIX 都早),近些年的广泛使用有其背景:


  • 大量线程用不起(服务器或嵌入式),或者没有线程(浏览器或 MCU 裸机)

  • 然而,异步需求在,开源库 API 设计成异步 IO 渐变主流

  • 可异步代码太难搞,程序一膨胀,不是回调地狱就是全程乱跳。。。

  • 由此不约而同想:代码能不能写起来像同步,跑起来像异步?

  • 做梦之余一看,这不是就是 Coroutine 吗?好好,不止第三方库,要语言层支持,加 promise,再加 async/await


嗯,这段像瞎掰,实际是典型 JavaScript 开发者心态,其它也类似。


远的不说,做嵌入式开发,也常被异步 IO 编程(基于中断/消息/事件)搞得焦头烂额,我也想要“Code like sync, works like async”。


可 C/C++如何做 Coroutine 呢?

2.

方案 1


基于用户态 Scheduler(微信后台方案)


Coroutine 是简单的东西,第一反应就是拿用户态 Scheduler 实现。


即任务切换时,完成真实的换栈:



任务运行上下文(context)可以简视:寄存器/栈信息,当每个协程任务放弃(yield)时,执行 context 切换。看起来和 OS 线程没区别,实际是有的:


  • 所有 Coroutines 共享 1 个 CPU 线程,相互无抢占(协作式,竞争成本低)

  • Coroutine 更轻,尽管 Linux 中单线程只需约 4KB(1 页),然而 1 个 Coroutine 只 0.1KB

  • Coroutine 切换快(约 100T),在多数平台上消耗时间在纳秒级/微秒级


对大量链接的服务器后台,上述优势明显。可以参见腾讯开源协程库: libco。


这是对调用者干净的实现,编程没有限制,PC 端主流协程库都如此实现:


  • libco(微信)/Boost.Context(C++准标准)/libaco/coroutine


换栈的手段也不局限汇编,有系统库或第三方:


  • posix 中 context/Windows 中 fiber/C 标准中 setjump 等。


尽管如此,可对嵌入式编程意义很小:


  • RTOS 中 Task 实现类似,内存消耗/切换成本已经很低

  • RTOS 中 Task 亦可配置成协作式(非抢占)

  • 每种 CPU 都需要移植,等价于再实现 Scheduler,意义不大


方案 2


基于标签语法糖(switch 或 goto 扩展)


这是借用预编译宏和标签,大玩语法游戏的套路。


目前所有类似实现(如 Protothread),都基于 Simon Tatham 的文章,这里简要 1 种核心:



仔细看上述代码,它是合法的。在 switch/case 间,插入不同的语句,用不同 case 分割。由此换个视角看,count 可视为状态索引,每次进入时会恢复到代码对应位置。这是一种不基于换栈的任务切出/切回方式。


把上述 switch/case 手段用宏 crBegin/crFinish/crReturn 包装下,下面两段带 while(1)的死循环代码,就可以在 1 个线程中并发执行:



这是 Coroutine 实现的最轻方式,优点:


  • 完全标准 C 实现,跨平台

  • 每个 Coroutine 只需要额外 1 字节 - 2 字节内存

  • Task 切换无成本


不过,不知道大家发没发现,局部变量该怎么办?


没有换栈,无法用局部变量,必须 static 静态化。由此,这种方式受限明显:


  • 如果用 static 变量,会导致函数无法重入

  • 如果不用 static,就必须传参类似 ctx 参数来代替局部变量


看的出来,让调用者有些难受。


由此,Contiki OS 又对上述方法改良并包装,并用这种机制实现整个操作系统的多任务。


它的代码值得一读,除了这部分,其它模块(uIP/GUI/Timer/Mem)都很漂亮。

3.

大家看的出来,嵌入式系统上 1 和 2 还不够完美,有没有更好的方案?希望:


  • 只用 C99 实现,完全跨平台/跨架构

  • 内存消耗要远小于线程,额外消耗在几个字节内

  • 可以使用局部变量(至少表面上)

  • 对调用者友好,类似其它语言 async/await 的方式


显然需要新方案。


这里卖个关子,感兴趣的朋友可以留言讨论,请持续关注我们公众号哦~


作者介绍


王相宇,滴滴两轮车硬件技术部


本文转载自公众号普惠出行产品技术(ID:gh_ed6841067977)。


原文链接


Code Like Sync, Works Like Async


2020-10-20 14:003087

评论

发布
暂无评论
发现更多内容

双点击账户接管漏洞深度分析

qife122

网络安全 移动安全

京东外卖App独立上线,超级App如何集成海量小程序?

FinClip

2025国内主流低代码平台排行,11月最新盘点,头部厂商全解析

优秀

低代码

结项报告完整版 | 为 Apache DolphinScheduler 添加 gRPC 插件

白鲸开源

大数据 开源 Apache DolphinScheduler 开源之夏

闪耀NeurIPS 2025!快手13篇论文入选,Spotlight 成果跻身前三!

快手技术

NeurIPS 顶会论文

AI 模型训练研发:用智能工程化让大模型“训得快、调得准、落得稳”

上海拔俗

船舶安全AI管理平台:用智能感知筑牢海上“生命防线”

上海拔俗

AI 大语言模型及服务平台:用智能基座让千行百业“接得住、用得好、长得快”

上海拔俗

Gemini3 强势来袭,这次前端真的死了。。。

苍何

国外社交媒体分析服务如何助力海外品牌预判国外市场趋势

沃观Wovision

社交媒体 社媒监测 海外社交媒体监控 社媒分析

大厂严选 | 数据堂2025年度版权数据集热销榜单重磅发布!

数据堂

人工智能 人脸识别 数据集 语音识别 大模型

【效率翻倍】如何设置海外营销自动化工作流?附核心场景SOP

Wolink

跨境贸易 出海 海外社媒营销 海外营销推广 海外红人营销

图解 Apache DolphinScheduler 如何配置飞书告警

白鲸开源

大数据 开源 Apache DolphinScheduler 飞书 任务调度

面向复杂生产场景的 Token 双流:百度百舸开源贡献至 SGLang 社区

Baidu AICLOUD

双流 Qwen DeepSeek 推理加速

不烧钱的海外营销:5个被低估的推广策略与实战案例

Wolink

跨境电商 出海 海外社媒营销 海外营销推广 海外红人营销

教学资源库专业知识图谱:用智能关联让知识“连得上、找得准、学得透”

上海拔俗

比特币跌破 9 万美元,「熊市」已来,8 万美元将成为新的关键「支撑位」?

TechubNews

SLS 脱敏函数实践:构建 LLM 应用数据输出的安全防线

阿里巴巴云原生

阿里云 云原生 sls

淘宝拍立淘API助力电商比价与同款搜索

Datafox(数据狐)

淘宝API 淘宝图片搜索接口 淘宝拍立淘接口 淘宝图搜API 淘宝图片识别接口

模型算法建立验证服务系统:用全链路智能保障 AI“建得对、验得严、用得稳”

上海拔俗

谷歌最强大模型 Gemini 3 炸场

GPU算力

大模型 大语言模型 AI 编程 gpt-5 谷歌Gemini3

见证中国开源生态成长力量:开源鸿蒙五年跨越与未来展望

最新动态

阿里云 Serverless 计算 10 月产品动态

阿里巴巴云原生

阿里云 Serverless 云原生

基于Sermant实现小游戏出海场景的微服务治理

华为云开源

开源 微服务架构 微服务治理 华为云开源

技术型外贸企业如何靠“内容”进行外贸推广,吸引海外大客户?

Wolink

跨境贸易 跨境电商 出海 外贸服务 海外营销推广

如何通过Python SDK获取Collection中已存在的Doc

DashVector

人工智能 数据库 AI 大模型 向量

AI赋能:新一代海外社交媒体分析软件的智能功能对比

沃观Wovision

社交媒体 社媒监测 海外社交媒体监控 社媒分析

Dapp区块链商城开发时间费用以及功能、和传统商城有什么区别

西安链酷科技

【隐语SecretFlow】从论文到社区贡献,一位算法工程师的开源故事

隐语SecretFlow

ManageEngine卓豪-cmdb智能运维管理平台

ServiceDesk_Plus

CMDB ManageEngine卓豪

海外社交媒体分析服务如何助力品牌发现海外增长机会?

沃观Wovision

社交媒体 社媒监测 海外社交媒体监控 社交媒体监测 社媒分析

Code Like Sync, Works Like Async_编程语言_王相宇_InfoQ精选文章