进程
定义
进程是程序的执行实例,也可以说程序在CPU上执行的活动叫做进程
特点
一个进程可以创建另一个进程(父进程与子进程),可以通过任务管理器查看Chrome的进程
CPU
一个单核CPU在一个时刻只能做一件事情,通过在不同进程之间快速切换实现同时让用户做多件事情
多个程序在宏观上并行,微观上串行,每个进程会出现『执行-暂停-执行』的规律,多个进程之间会出现抢资源的现象
进程的状态
线程
进程是资源分配的基本实体,线程是执行的基本实体,CPU调度和执行的最小单元
一个进程中的线程可以共享进程的所有资源,进程的第一个线程叫做初始化线程,也是主线程,线程的调度可以由操作系统负责,也可以用户自己负责
Node.js的进程控制
通过 child_process这个模块实现,有几个常用的API,接下来依次介绍
exec
语法 exec(cmd[,options],fn)
代码实例
const { exec } = require('node:child_process')
exec('ls ../', (error, stdout, stderr) => {
console.log(error)
console.log(stdout)
console.log(stderr)
})
exec可以返回两个流
stream.stdout stream.stderr
const child_process = require('child_process')
const { exec } = child_process
const stream = exec('ls -l ../')
stream.stdout.on('data', (chunk) => {
// 注意不是stream.on
process.stdout.write(chunk)
})
stream.on('end', () => {})
还可以通过util.promisify封装exec,返回一个promise避免回调地狱
const child_process = require('child_process')
const { exec } = child_process
const util = require('util')
const exec2 = util.promisify(exec) // api都可以用util.promisify封装
exec2('ls -l ../').then((data) => {
console.log(data)
console.log(data.stdout)
})
但是 exec有漏洞,cmd可以被注入
const child_process = require('child_process')
const { exec } = child_process
const util = require('util')
const exec2 = util.promisify(exec)
const userInput = '. && pwd' // /Users/wangdanmeng/Desktop/child_process
exec2(`ls ${userInput}`).then((data) => {
console.log(data.stdout)
})
execFile
语法 child_process.execFile(file[, args][, options][, callback])
可避免注入攻击,也返回两个流
const child_process = require('child_process')
const { execFile } = child_process
const userInput = '. && pwd'
execFile('ls', ['-la', userInput], (error, stdout) => {
console.log(error)
console.log(stdout)
})
spawn
没有回调,通过流事件获取结果,相比execFile,更推荐使用这个
const child_process = require('child_process')
const { spawn } = child_process
const stream = spawn('ls')
stream.stdout.on('data', (chunk) => {
console.log(chunk.toString())
})
fork
创建一个子进程,执行Node脚本
fork('./child.js')相当于spawn('node',['child.js'])
有message和send方法,实现父子进程之间通信,如下面代码所示。控制台会先打印出子进程得到值: { hello: 'world' },三秒后打印出父进程得到值 { foo: 'bar' }
// n.js
const child_process = require('child_process')
const n = child_process.fork('./child.js')
n.on('message', function (m) {
console.log('父进程得到值: ', m)
})
n.send({ hello: 'world' })
// child.js
process.on('message', function (m) {
console.log('子进程得到值:', m)
})
setTimeout(() => {
process.send({ foo: 'bar' })
}, 3000)