Node.js中child_process.fork同代码跨设备输出顺序不一致原因
Node.js child_process.fork 父子进程通信跨设备输出顺序不一致问题
现象
相同代码分别在macOS Monterey、Ubuntu 20.04设备上运行时,控制台日志打印顺序存在明显差异。代码共包含两个文件:父进程文件app.js、子进程文件child.js。
代码内容
父进程 app.js
var cp = require('child_process'); var child = cp.fork(__dirname + '/child.js'); child.on('message', function(m) { console.log('Parent process received:', m); }); child.send({ hello: 'from parent process' }); child.on('close', (code) => { console.log(`child process exited with code ${code}`); });
子进程 child.js
process.on('message', function(m) { console.log('Child process received:', m); }); process.send({ hello: 'from child process' });
不同环境运行输出
- macOS Monterey 环境输出:
Child process received: { hello: 'from parent process' } Parent process received: { hello: 'from child process' }
- Ubuntu 20.04 环境输出:
Parent process received: { hello: 'from child process' } Child process received: { hello: 'from parent process' }
原因解释
输出顺序差异是无同步逻辑的并发执行的正常表现,和代码正确性无关:
cp.fork创建子进程属于异步操作,父子进程是互相独立的系统调度单元,由操作系统内核分配CPU执行时间,二者的执行进度没有天然的先后绑定关系。- 现有代码逻辑中,父进程发起子进程创建后,会立即绑定消息监听、向子进程发送消息;子进程启动完成后,也会立即绑定自身的消息监听、向父进程发送消息。两个方向的IPC消息传递、回调触发、控制台打印操作完全并行,没有任何代码逻辑约束二者的执行先后。
- 不同操作系统的进程调度策略、IPC通道实现、Node.js事件循环调度细节存在差异:macOS环境下内核调度刚好让子进程先接收到父进程的消息并完成打印,之后父进程才收到子进程的消息触发打印;Ubuntu环境下调度顺序刚好相反,父进程先收到子进程消息完成打印。
- 即使在同一台设备上,CPU占用率、系统负载变化时,多次运行同一段代码也可能出现输出顺序波动。如果需要固定输出顺序,必须手动添加同步协调逻辑,比如约定收到特定消息后再执行下一步发送/打印操作,不能依赖操作系统默认的调度顺序。
内容的提问来源于stack exchange,提问作者Kishan Patel
相关产品推荐
相关产品推荐

