93. child_process

child_process Node.js 全解-子进程 目录

  • 进程

  • 线程

  • Node.js的进程控制

  • Node.jis的线程控制

进程 Process

场景

notepad.exe是一个程序,不是进程

双击 notepad.exe 时, 操作系统会开启一个进程

定义

进程是程序的执行实例

程序在CPU上执行时的活动叫做进程

实际上并没有明确的定义,只有一些规则

特点

一个进程可以创建另一个进程 (父进程与子进程)

通过任务管理器可以看到进程

了解CPU

特点

一个单核 CPU,在一个时刻, 只能做一件事情

那么如何让用户同时看电影、听声音、 写代码呢?

答案是在不同进程中快速切换

此处以渣男交多个女朋友举例

多程序并发执行

指多个程序在宏观上并行,微观上串行

每个进程会出现 「执行-暂停-执行」的规律

多个进程之前会出现抢资源 (如打印机) 的现象

进程的两个状态

截屏2023-04-28 上午1.01.18
截屏2023-04-28 上午1.01.35

阻塞(se)

等待执行的进程中

都是非运行态

一些(A)在等待CPU资源

另一些(B)在等待1/0 完成(如文件读取)

如果这个时候把CPU分配给B进程,B还是在等I/O

我们把这个B叫做阻塞进程

因此,分派程序只会把CPU分配给非阻塞进程

进程的三个状态

截屏2023-04-28 上午1.02.31
截屏2023-04-28 上午1.02.49

线程Thread的引入

分阶段

在面向进程设计的系统中,进程是程序的基本执行实体

在面向线程设计的系统中,进程本身不是基本运行单位,

而是线程的容器

引入原因

进程是执行的基本实体,也是资源分配的基本实体

导致进程的创建、切换、销毁太消耗CPU时间了

于是引入线程,线程作为执行的基本实体

而进程只作为资源分配的基本实体

此处可以以设计师和工程师分开招聘举例

线程Thread

概念

CPU调度和执行的最小单元

一个进程中至少有一个线程,可以有多个线程

一个进程中的线程共享该进程的所有资源

进程的第--个线程叫做初始化线程

线程的调度可以由操作系统负责,也可以用户自己负责

举例

浏览器进程里面有渲染引擎、 V8引擎、 存储模块、网络模块、用户界面模块等

每个模块都可以放在一个线程里

分析

子进程V.S.线程

child process

用于新建子进程

child_process

使用目的

去执行一个命令行程序

子进程的运行结果将储存在系统缓存之中(最大200Kb)

等到子进程运行结束以后,主进程再用回调函数读取子

进程的运行结果

有两种方式获取child_process的执行结果,一种是用标准输出,一种是用流。

API - exec

exec(cmd,options, fn)

execute 的缩写,用于执行bash命令

同步版本: execSync

返回一个流

Promise

可以使其 Promise 化,用util.promisify

有漏洞

如果 cmd 被注入了,可能执行意外的代码, 比如把根目录全部删掉

推荐使用 execFile

使用流

options

几个常用的选项

cwd - Current working directory

env-环境变量

shell-用什么 shell

maxBuffer-最大缓存,默认1024* 1024字节

API - execFile

execFile

执行特定的程序

命令行的参数要用数组形式传入,无法注入

如果使用流的话,就不需要传后面的回调函数,而且不会引发注入。

同步版本:execFileSync

支持流吗? 试一试就知道了

API - Spawn

Spawn

spawn是产卵的意思。

用法与execFile方法类似

没有回调函数,只能通过流事件获取结果

没有最大200Kb的限制(因为是流)

经验

能用spawn的时候就不要用execFile, 因为execFile有回调限制,最大200kb

API - fork

fork

创建一个子进程,执行Node脚本

fork('./child.js')相当于spawn('node', [./child.js'])

fork是spawn的语法糖

特点

会多出一个message事件,用于父子通信

会多出一个send方法

见下页

代码

n.js

.child.js

那怎么操作线程呢

刚才讲的都是进程啊

一些历史

child process. exec

v0.1.90加入Node.js

new Worker

v10.5.0加入Node.js

vl1.7.0之前需要--experimental-worker开启

这个线程API太新了

所以我们应该不会经常用到

效率

目前效率并不够高,文档(中文)自己都写了

workerthreads API

API列表

isMainThread

new Worker(filename)

parentPort(做线程间的通信)

postMessage

事件列表

message

exit

再见

如果你对进程、线程感兴趣推荐学习任意一本 关于操作系统的教科书

方方看得是《操作系统原理》, 不推荐黑皮书

截屏2023-05-14 上午12.36.40

常用的是spawn和fork,spawn用来执行任意程序,fork用来执行nodejs的程序

最后更新于

这有帮助吗?