Node 中进程与子进程的区别及使用场景
在 Node 中,进程和子进程是处理并发任务的核心概念。Node 是单线程的,但可以通过创建子进程来处理 CPU 密集型任务或执行外部命令,避免阻塞事件循环。
1. 进程
1.1. 进程定义
进程是运行中的程序实例,每个 Node 应用程序运行时都是一个独立的进程。进程中包含了代码、运行时上下文、系统资源等。
1.2. 进程交互
Node 通过全局的 process 对象与当前运行的进程进行交互,比如获取命令行参数 process.argv、获取环境变量 process.env、退出进程process.exit() 等。
2. 子进程
2.1. 子进程定义
子进程是由主进程派生出来的,用于执行独立的任务。Node 提供了 child_process 模块来创建和管理子进程,常见的子进程类型包括:
exec():执行一个 shell 命令,并返回标准输出。
spawn():启动一个新的进程,并允许流式传输数据,适用于长时间运行的任务。
fork():专门用于创建新的 Node 子进程,并允许与子进程进行进程间通信。
2.2. 子进程的使用场景
执行外部命令:比如调用 shell 命令或其他外部程序,可以使用 exec()。
处理 CPU 密集型任务:例如大文件压缩、图片处理等,可以通过 spawn() 创建子进程并将这些任务移交给子进程处理,防止阻塞主线程。
多进程通信:fork() 提供了与子进程之间进行通信的功能,适合需要父子进程协作的场景。
3. 示例代码
3.1. exec() 示例
const { exec } = require('child_process');// 执行 shell 命令,列出当前目录下的文件
exec('ls -lh', (error, stdout, stderr) => {if (error) {console.error(`执行错误: ${error}`);return;}console.log(`标准输出: ${stdout}`);
});
3.2. spawn() 示例
const { spawn } = require('child_process');// 创建子进程,执行 `ls -lh` 命令
const ls = spawn('ls', ['-lh']);// 子进程的标准输出
ls.stdout.on('data', (data) => {console.log(`输出: ${data}`);
});// 子进程的错误输出
ls.stderr.on('data', (data) => {console.error(`错误: ${data}`);
});// 子进程结束
ls.on('close', (code) => {console.log(`子进程退出,退出码: ${code}`);
});
3.3. fork() 示例
const { fork } = require('child_process');// 创建子进程,执行子文件 `child.js`
const child = fork('./child.js');// 向子进程发送消息
child.send('Hello, child process!');// 接收子进程发来的消息
child.on('message', (msg) => {console.log(`父进程收到消息: ${msg}`);
});
4. 进程与子进程的区别
进程:是 Node 应用程序的运行实例,可以通过全局 process 对象进行交互。
子进程:是从主进程中派生出来的独立执行任务的进程,适用于并发任务、CPU 密集型任务等场景。
5. 总结
进程 是运行中的程序实例,通过 process 模块与其进行交互。
子进程 是为了并行任务处理或执行外部命令,Node 提供了 child_process 模块来创建和管理子进程。