📔
饥人谷前端体系课程笔记
黑马程序员笔记前端面试押题前端精进
  • 课程大纲
  • Git入门
    • 3. 软件安装详解
    • 4. Mac环境搭建
    • 5. 命令行入门
    • 6. 本地仓库
    • 7. Git远程仓库-GitHub
  • HTML全解
    • 8. HTML概览
    • 9. HTML标签
    • 10. HTML重难点
    • 11. HTML实践 & 手机调试
  • CSS全解
    • 12. CSS基础
    • 13. CSS布局(上)
    • 14. CSS布局(下)
    • 15. CSS定位
    • 16. CSS动画
  • HTTP全解
    • 17. URL 是什么
    • 18. 请求和响应 & Node.js Server
  • JS全解
    • 19. JavaScript概览
    • 20. 内存图与JS世界(精品课)
    • 21. Canvas 实践—画图板
    • 22. JS语法
    • 23. JS数据类型
    • 24. JS 对象
    • 25. JS 对象分类
    • 26. JS 数组
    • 27. JS 函数
    • 28. JS 实战,会动的代码
    • 29. JS运算符
    • 30. JS总结
  • JS编程接口
    • 31. DOM编程
    • 32. 手写DOM库
    • 33. JQuery中的设计模式(上)
    • 34. JQuery中的设计模式(下)
    • 35. DOM事件与事件委托
  • 项目 前端导航站点
    • 前端导航项目笔记
  • 前后分离
    • 40. AJAX的原理
    • 41. 异步与Promise
    • 42. 跨域、CORS、JSONP
    • 43. 静态服务器
    • 44. AJAX实战:Cookie、Session
  • JS进阶MVC
    • 48. MVC(上)
    • 49. MVC(中)
    • 50. MVC(下)
  • 项目构建
    • 51. Webpack(上)
    • 52. Webpack(下)
  • 算法与数据结构
    • 62. 伪代码与流程图
  • React全解
    • 75. React起手式
    • 76. React类组件和函数组件
    • 77. Class组件详解
    • 78. 函数组件
    • 79. Hooks原理解析
    • 80. Hooks各个击破
    • 81. 精通Redux
  • Node.js
    • 84. Node.js技术架构
    • 85. 文件模块
    • 86. 单元测试之文件模块
    • 87. 调试 Node.js 程序
    • 88. 静态服务器
    • 89. 命令行翻译工具
    • 90. 操作数据库
    • 91. 数据库基础知识
    • 92. Stream 流
    • 93. child_process
    • 94. 总结
  • TypeScript
    • 112. 基础
    • 113. 泛型
  • Next.js全解
    • Next.js 上
    • Next.js 下
  • ES6精讲
    • Promise,async/await
  • 大屏可视化笔记
    • 大屏可视化项目
  • SCSS全解
    • SCSS全解
  • 拓展
    • 一次性弄懂性能优化
    • Web性能优化
由 GitBook 提供支持
在本页
  • 进程 Process
  • 了解CPU
  • 进程的两个状态
  • 阻塞(se)
  • 进程的三个状态
  • 线程Thread的引入
  • 线程Thread
  • child_process
  • API - exec
  • 使用流
  • options
  • API - execFile
  • API - Spawn
  • API - fork
  • 代码
  • 那怎么操作线程呢
  • 一些历史
  • workerthreads API

这有帮助吗?

  1. Node.js

93. child_process

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

  • 进程

  • 线程

  • Node.js的进程控制

  • Node.jis的线程控制

进程 Process

场景

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

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

定义

进程是程序的执行实例

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

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

特点

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

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

了解CPU

特点

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

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

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

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

多程序并发执行

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

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

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

进程的两个状态

阻塞(se)

等待执行的进程中

都是非运行态

一些(A)在等待CPU资源

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

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

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

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

进程的三个状态

线程Thread的引入

分阶段

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

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

而是线程的容器

引入原因

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

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

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

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

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

线程Thread

概念

CPU调度和执行的最小单元

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

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

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

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

举例

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

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

分析

子进程V.S.线程

child process

用于新建子进程

child_process

使用目的

去执行一个命令行程序

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

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

进程的运行结果

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

API - exec

const child_process = require('child_process')
const {exec} = child_process

exec('ls', (error, stdout, stderr)=>{
//stdout标准输出就是黑色窗口
	console.log(error)
	console.log(stdout)
	console.log(stderr)
})

exec(cmd,options, fn)

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

同步版本: execSync

流

返回一个流

Promise

可以使其 Promise 化,用util.promisify

const exec2 = util.promisify(exec);
const userInput = '. && rm -rf /'

exec2(`ls ${userInput}`).then(data =>{
	console.log(data.stdout);
})

有漏洞

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

推荐使用 execFile

使用流

var exec = require('child_process' ).exec ;
var child = exec('ls -1');
child.stdout.on('data', function(data) {
console.log('stdout :'  + data);
});
child.stderr.on('data', function(data) {
console.log('stdout:' + data) ;
});
child.on('close',function(code) {
console.log('closing code:' + code) ;
});

options

几个常用的选项

cwd - Current working directory

env-环境变量

shell-用什么 shell

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

const userInput = ".";
execFile("echo ${NODE_ENV}",["-la",userInput],{
	cwd: 'C:\\',
  env:{NODE_ENV: 'development'},
  shell: '默认路径',  //默认是bash
  maxBuffer: 2*1024*1024 //默认是1024 * 1024
},(error, stdout) =>{
	console.log(error);
	console.log(stdout);
})

API - execFile

执行特定的程序

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

const userInput = ".";
execFile("ls",["-la",userInput],(error,stdout) => {
	console.log(error);
	console.log(stdout);
})

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

const streams = execFile("ls",["-la",userInput]);
streams.stdout.on('data',(chuck)=>{
	console.log(chuck);
})

同步版本:execFileSync

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

API - Spawn

Spawn

spawn是产卵的意思。

用法与execFile方法类似

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

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

const streams = spawn("ls",["-la", userInput],{
	cwd: 'C:\\',
	env:{NODE_ENV: 'development'}
});

streams.stdout.on('data',(chuck) => {
	console.log(chuck.toString())//chuck里面存的是buffer
})

经验

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

API - fork

fork

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

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

fork是spawn的语法糖

特点

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

会多出一个send方法

见下页

代码

n.js

var n =child_process.fork('./child.js');       
n.on('message',  function(m)
console.log('PARENT got message:', m);
});
n.send({ hello: 'world' });

.child.js

process.on('message',  function(m)  {
	console.log('CHILD got message:', m);
});
process.send({ foo: 'bar'});

那怎么操作线程呢

刚才讲的都是进程啊

一些历史

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)

postMessage

事件列表

message

exit

再见

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

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

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

上一页92. Stream 流下一页94. 总结

最后更新于2年前

这有帮助吗?

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

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

(做线程间的通信)

execFile
文档
中文
parentPort
截屏2023-05-14 上午12.36.40