目录
文件复制
进程创建
总结
首页 web前端 js教程 浅谈Node.js+COW技术进行进程创建和文件复制

浅谈Node.js+COW技术进行进程创建和文件复制

Sep 17, 2021 am 10:07 AM
node.js 文件复制

本篇文章带大家了解一下COW(Copy-On-Write)技术,介绍一下COW技术+Node.js 的进程创建和文件复制的应用,希望对大家有所帮助!

浅谈Node.js+COW技术进行进程创建和文件复制

COW 不是奶牛,是 Copy-On-Write 的缩写,这是一种是复制但也不完全是复制的技术。

一般来说复制就是创建出完全相同的两份,两份是独立的:

1.png

但是,有的时候复制这件事没多大必要,完全可以复用之前的,这时候可以只是引用之前的那份,在写内容的时候才去复制对应的一部分内容。这样如果内容用于读的话,就免去了复制,而如果需要写,才会真正复制部分内容来做修改。

2.png

这就叫做“写时复制”,也就是 Copy-On-Write。

原理很简单,但是在操作系统的内存管理和文件系统中却很常见,Node.js 里面也因为这种技术变“懒”了。

本文我们来探究下 Copy-On-Write 在 Node.js 的进程创建和文件复制的应用。【推荐学习:《nodejs 教程》】

文件复制

文件复制这件事最常见的思路就是完全写一份相同的文件内容到另一个位置,但是这样有两个问题:

  • 完全写一份相同的内容,如果同样的文件复制了几百次,那么也创建相同的内容几百次么?太浪费硬盘空间了
  • 如果写到一半断电了怎么办?覆盖的内容如何恢复?

怎么办呢?这时候操作系统设计者就想到了 COW 技术。

用 COW 技术实现文件复制以后完美解决了上面两个问题:

  • 复制只是添加一个引用到之前的内容,如果不修改并不会真正复制,只有到第一次修改内容的时候才去真正复制对应的数据块,这样就避免了大量硬盘空间的浪费。
  • 写文件时会先在另一个空闲磁盘块做修改,等修改完之后才会复制到目标位置,这样就不会有断电无法回滚的问题

在 Node.js 的 fs.copyFile 的 api  就可以使用 Copy-On-Write 模式:

默认情况下,copyFile 会写入目标文件,覆盖原内容

const fsPromises = require('fs').promises;

(async function() {
  try {
    await fsPromises.copyFile('source.txt', 'destination.txt');
  } catch(e) {
    console.log(e.message);
  }
})();
登录后复制

但是可以通过第三个参数指定复制的策略:

const fs = require('fs');
const fsPromises = fs.promises;
const { COPYFILE_EXCL, COPYFILE_FICLONE, COPYFILE_FICLONE_FORCE} = fs.constants;

(async function() {
  try {
    await fsPromises.copyFile('source.txt', 'destination.txt', COPYFILE_FICLONE);
  } catch(e) {
    console.log(e.message);
  }
})();
登录后复制

支持的 flag 有 3 个:

  • COPYFILE_EXCL: 如果目标文件已存在,会报错(默认是覆盖)
  • COPYFILE_FICLONE: 以 copy-on-write 模式复制,如果操作系统不支持就转为真正的复制(默认是直接复制)
  • COPYFILE_FICLONE_FORCE:以 copy-on-write 模式复制,如果操作系统不支持就报错

这3个常量分别是 1,2,4,可以通过按位或把它们合并之后传入:

const flags = COPYFILE_FICLONE | COPYFILE_EXCL;
fsPromises.copyFile('source.txt', 'destination.txt', flags);
登录后复制

Node.js 支持操作系统的 copy-on-write 技术,在一些场景下可以提升性能,建议使用 COPYFILE_FICLONE 的方式,会比默认的方式好一些。

进程创建

fork 是常见的创建进程的方式,而它的实现就是一种 copy-on-write 技术。

我们知道,进程在内存中分为代码段、数据段、堆栈段这 3 部分:

  • 代码段:存放要执行的代码
  • 数据段:存放一些全局数据
  • 堆栈段:存放执行的状态

如果基于该进程创建一个新的进程,那么要复制这 3 部分内存。而如果这三部分内存是一样的内容,那就浪费了内存空间。

所以 fork 并不会真正的复制内存,而是创建一个新的进程,引用父进程的内存,当做数据的修改的时候,才会真正复制该部分的内存。

3.png

这也是为什么把进程创建叫做 fork,也就是分叉,因为不完全是独立的,只是某部分做了分叉,成了两份,但是大部分还是一样的。

但如果要执行的代码不一样怎么办呢,这时候就要用 exec 了,它会创建新的代码段、数据段、堆栈段、执行新的代码。

Node.js 里面同样可以用 fork 和 exec 的 api:

fork:

const cluster = require('cluster');

if (cluster.isMaster) {
  console.log('I am master');
  cluster.fork();
  cluster.fork();
} else if (cluster.isWorker) {
  console.log(`I am worker #${cluster.worker.id}`);
}
登录后复制

exec:

const { exec } = require('child_process');
exec('my.bat', (err, stdout, stderr) => {
  if (err) {
    console.error(err);
    return;
  }
  console.log(stdout);
});
登录后复制

fork 是 linux 进程创建的基础,由此可见 copy-on-write 技术多么重要了。

总结

复制同样的内容多份无疑比较浪费空间,所以操作系统在做文件复制、进程创建时的内存复制的时候都采用了 Copy-On-Write 技术,只有真正修改的时候才会去做复制。

Node.js 支持了 fs.copyFile 的 flags 的设置,可以指定 COPYFILE_FICLONE 来使用 Copy-On-Write 的方式做文件复制,也建议大家使用这种方式来节省硬盘空间,提高文件复制的性能。

进程的 fork 也是 Copy-On-Write 的实现,并不会直接复制进程的代码段、数据段、堆栈段到新的内容,而是引用之前的,只有在修改的时候才会做真正的内存复制。

除此以外,Copy-On-Write 在 Immutable 的实现,在分布式的读写分离等领域都有很多应用。

COW 让 Node.js 变“懒”了,但性能却更高了。

原文地址:https://juejin.cn/post/6999497362255118366

作者:zxg_神说要有光

更多编程相关知识,请访问:编程入门!!

以上是浅谈Node.js+COW技术进行进程创建和文件复制的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

图文详解Node V8引擎的内存和GC 图文详解Node V8引擎的内存和GC Mar 29, 2023 pm 06:02 PM

本篇文章带大家深入了解NodeJS V8引擎的内存和垃圾回收器(GC),希望对大家有所帮助!

一文聊聊Node中的内存控制 一文聊聊Node中的内存控制 Apr 26, 2023 pm 05:37 PM

基于无阻塞、事件驱动建立的Node服务,具有内存消耗低的优点,非常适合处理海量的网络请求。在海量请求的前提下,就需要考虑“内存控制”的相关问题了。 1. V8的垃圾回收机制与内存限制 Js由垃圾回收机

聊聊如何选择一个最好的Node.js Docker镜像? 聊聊如何选择一个最好的Node.js Docker镜像? Dec 13, 2022 pm 08:00 PM

选择一个Node​的Docker镜像看起来像是一件小事,但是镜像的大小和潜在漏洞可能会对你的CI/CD流程和安全造成重大的影响。那我们如何选择一个最好Node.js Docker镜像呢?

深入聊聊Node中的File模块 深入聊聊Node中的File模块 Apr 24, 2023 pm 05:49 PM

文件模块是对底层文件操作的封装,例如文件读写/打开关闭/删除添加等等 文件模块最大的特点就是所有的方法都提供的**同步**和**异步**两个版本,具有 sync 后缀的方法都是同步方法,没有的都是异

Node.js 19正式发布,聊聊它的 6 大特性! Node.js 19正式发布,聊聊它的 6 大特性! Nov 16, 2022 pm 08:34 PM

Node 19已正式发布,下面本篇文章就来带大家详解了解一下Node.js 19的 6 大特性,希望对大家有所帮助!

聊聊Node.js中的 GC (垃圾回收)机制 聊聊Node.js中的 GC (垃圾回收)机制 Nov 29, 2022 pm 08:44 PM

Node.js 是如何做 GC (垃圾回收)的?下面本篇文章就来带大家了解一下。

一起聊聊Node中的事件循环 一起聊聊Node中的事件循环 Apr 11, 2023 pm 07:08 PM

事件循环是 Node.js 的基本组成部分,通过确保主线程不被阻塞来实现异步编程,了解事件循环对构建高效应用程序至关重要。下面本篇文章就来带大家深入了解Node中的事件循环 ,希望对大家有所帮助!

聊聊用pkg将Node.js项目打包为可执行文件的方法 聊聊用pkg将Node.js项目打包为可执行文件的方法 Dec 02, 2022 pm 09:06 PM

​如何用pkg打包nodejs可执行文件?下面本篇文章给大家介绍一下使用pkg将Node项目打包为可执行文件的方法,希望对大家有所帮助!

See all articles