# 引入多进程和进程间通信

*本文是一篇科普文章，旨在帮助读者理解 CKB 在  Meepo 升级中引入的 Spawn 功能是什么，如何工作，以及能做什么。*

*尽管本文不会深入到具体实现细节，但我希望读者具备以下背景知识：*

* *对 CKB 的运行模式，如* [*CKB-VM*](https://docs.nervos.org/docs/tech-explanation/ckb-vm)*、*[*Script (smart contract)*](https://en.wikipedia.org/wiki/Inter-process_communication)*），有基本了解*
    
* *知道操作系统中的*[*进程*](https://en.wikipedia.org/wiki/Process_\(computing\))*、*[*协程*](https://en.wikipedia.org/wiki/Coroutine)*、*[*IPC（进程间通信）*](https://en.wikipedia.org/wiki/Inter-process_communication)*等概念*
    

## CKB 传统合约开发的挑战

在此前的 CKB 合约中，如果需要使用某个复杂算法，通常是直接将其嵌入到合约代码中。虽然这种方式简单直接，但也带来了不少问题：

* 代码难以维护、无法方便地更新
    
* 代码体积大，导致交易费用升高
    
* 所需的库与现有依赖发生冲突
    
* 目标语言性能不足，甚至该语言根本没有可用的实现。
    

为了解决这些问题，CKB 在 Meepo 分叉中引入了一套全新的多进程机制 Spawn。

## 源于 Unix 设计的 ckb-spawn

早在 2021 年，作为 CKB 解决链上 脚本间交互（inter-script interaction） 的方案的首次尝试，我们引入了 `ckb_exec`方案。 `ckb_exec` 的设计灵感来自 Unix 中的 exec 系统调用，其核心思想是：当前进程上下文被销毁，转而执行另一个脚本，如“切换进程”。然而在实际使用中，开发者很快遇到了一些关键限制，如无法返回值、执行上下文被完全清除、无法灵活地进行组合调用，这些限制让 exec 难以应对复杂合约逻辑的拆分与协作。

为解决上述问题，我们进一步借鉴了 Unix 程序控制设计中的 spawn 机制。它允许创建一个新的子进程，同时使原始进程继续执行。这种多进程机制即 `ckb_spawn`——具体包含了一组 API，核心是通过 `ckb_spawn` 创建子进程，并在此基础上实现一系列交互。

注：为了简便，如无特殊注明，这篇文章后面的 spawn 和 exec 都分别指 ckb-spawn 和 ckb-exec。

### Spawn 相对于 Exec 的优势

虽然 `exec` 和 `spawn` 都涉及子进程启动，但两者有本质区别：

* **Exec**：当父进程调用 `exec` 时，当前的执行上下文会被目标脚本**完全替换**。子脚本执行完成后，整个合约执行也随之**结束**——执行不会返回到父进程。
    
* **Spawn**：当父进程调用 `spawn` 时，会创建一个与父进程**并存**的**子进程**。子进程执行完成后，控制权可以**返回**到父进程，父进程随后继续执行。父子进程之间可以通过**管道**(pipe) 实现通信。
    

从严格意义上讲，Spawn 更像是“真正”的多进程；而 Exec 更像是“切换到另一个进程并终结当前上下文”。

下图直观地描绘了二者的区别，可以看出：Exec Parent 其实并没退出，而是上下文切换到了 Exec Child；而 Spawn 则是可以在 Parent 和 Child 之间来回切换。Spawn 机制使父进程和子进程能够通过管道通信，实现复杂逻辑的拆分和协作。

![image](https://yakihonne.s3.ap-east-1.amazonaws.com/3eba5ef41b206b1d49e8b1be7241d7ead5dd87b737261da64c3bc0e2751f23ae/files/1752480446668-YAKIHONNES3.png align="left")

## CKB 的多进程机制详解

其实 CKB 并没有原生的[并行](https://en.wikipedia.org/wiki/Parallel_computing)（parallelism）机制，本次 meepo 硬分叉未引入真正的并行执行能力，默认内存限制也未改变。但我们可以通过CKB-VM 调度模拟，实现类似并行的多进程功能。这种方法在逻辑上更接近[协程](https://en.wikipedia.org/wiki/Coroutine)（Coroutine）；同时还通过引入管道机制，实现进程间通信。

### 通过 VM 调度，实现多进程

CKB 中的“多进程”机制与操作系统中的多进程概念类似：

* 每个进程拥有独立的堆栈和内存空间
    
* 进程之间无法直接访问彼此的内存
    
* 父子进程之间存在明确的从属关系
    
* 每个进程拥有独立的 PID（process identifier 进程 ID）
    
* 子进程结束后会被系统自动回收资源
    

但是 CKB 与传统操作系统的最大不同在于是否基于时间片轮转机制（Round-Robin Scheduling）——CPU 将执行时间划分为多个固定长度的“时间片”（time slice），每个进程轮流获得一个时间片执行，保证各进程公平使用 CPU，实现真正的并行和抢占式多任务。

传统操作系统的多进程调度通常采用该机制，但 CKB 的多进程调度**并非基于时间片轮转**，而是依赖于特定的 **VM 系统调用**，例如 `ckb_spawn`、`ckb_read`、`ckb_write`、`ckb_wait` 去触发进程切换。换言之，CKB-VM 通过调用驱动的方式模拟多进程行为，执行是串行且受控的，更类似协程而非抢占式多任务。

### 管道机制

由于 CKB 的多进程机制中，父子进程拥有独立的内存空间，且进程间无法直接共享数据，如何实现进程间的有效通信成为关键问题。为此，CKB 引入了管道作为通信方式。

同操作系统中的管道概念类似，CKB 的管道是一种进程间通信（IPC）机制，允许一个进程向另一个进程发送数据，具有以下特点：

* 管道是单向的，有一个输入端和输出端（文件描述符，FD），允许一个进程将数据写入管道，另一个进程从管道读取数据
    
* 在创建子进程前，父进程创建管道并传递对应 FD
    
* 进程通过 FD 读写数据，实现数据传输
    

**需注意**: FD 与进程绑定，只有在创建子进程时才能将 FD 传递给它 （这个绑定也一并移交给它）。

管道由此弥补了进程内存隔离带来的数据交换障碍。

### Spawn 调度流程示意图

下图展示了一次完整的 spawn 调度过程：

![image](https://yakihonne.s3.ap-east-1.amazonaws.com/3eba5ef41b206b1d49e8b1be7241d7ead5dd87b737261da64c3bc0e2751f23ae/files/1752480560635-YAKIHONNES3.png align="left")

这一流程可分为以下四步：

1. `spawn-parent` 使用 `ckb_spawn` 启动了子进程 `spawn-child`（红框）；
    
2. 子进程通过 Pipe 写入一些数据（蓝框）；
    
3. 随后调度回 `spawn-parent`，继续执行父进程的逻辑（绿框）；
    
4. 执行结束后退出。
    

从图中可以清楚看到：整个过程中没有任何并行执行，所有执行都是串行的。这也正体现了 CKB-VM 通过调度模拟并行的设计思想。

## 用 `ckb-script-ipc`简化开发流程

尽管 `ckb_spawn` 系列接口数量不多，但由于涉及多进程调度、进程间通信以及链上资产安全，使用门槛依然较高。为此，我们开发了封装库 `ckb-script-ipc`，旨在简化基于 `spawn` 的开发流程。

它对底层机制做了两层封装：

* **通信模型封装**：将底层的 Pipe 通信抽象为更易理解的 **Client/Server 模型**；
    
    在这个模型中，Client 与 Server 的关系类似 HTTP 通信中的浏览器与服务器：
    
    * **Server**：类似于 HTTP 服务器，提供接口但不主动发起请求；
        
    * **Client**：类似于浏览器，由客户端决定请求的时机，并等待服务端响应。
        
    
    通常，父进程作为 Client，子进程作为 Server。
    
* **代码自动生成**：提供过程宏（procedural macro），用户只需定义一个 `trait`，即可自动生成对应的 Client 端代码；Server 端只需实现该 trait。（目前仅支持 Rust）
    
    借助过程宏，用户只需关注接口定义与实现逻辑，无需手动编写繁琐的通信代码，大大降低了使用 spawn 的复杂度。
    

## 结语

通过引入 Spawn 与管道，CKB 在保持链上安全性的基础上，提供了更灵活的合约（脚本）开发能力。作为一种类似并行的执行模型，这一机制为构建复杂逻辑提供了可行的路径，同时也为后续优化铺平了道路。对于开发者而言，理解这套机制将有助于设计更强大、可维护的合约架构。

在另一篇文章中，我将介绍 `ckb-crypto-service`：一个加密算法接口，允许合约通过 IPC 直接调用算法，无需手动集成。该服务基于 CKB 的多进程与 IPC 能力构建，为合约提供了可靠、高效、跨语言的基础设施。

---

🧑‍💻 本文作者：Han Zishuang 他是 [Nervos Network](https://www.nervos.org/) L1 CKB 区块链的开发者和 DevRel。

欢迎关注他更多关于 CKB 的技术分享：

* [Quantum Computation: New Challenge to CKB’s Security?](https://blog.cryptape.com/quantum-computation-new-challenge-to-ckbs-security)
    
* [Implementing EIP-712 on CKB-VM](https://blog.cryptape.com/implementing-eip-712-on-ckb-vm)
