0

0

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

青灯夜游

青灯夜游

发布时间:2021-09-17 10:07:14

|

2039人浏览过

|

来源于掘金--zxg_神说要有光

转载

本篇文章带大家了解一下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 的方式,会比默认的方式好一些。

EnableDTS公文传输管理系统3.0
EnableDTS公文传输管理系统3.0

公文是政府与企事业单位处理公务和行政管理工作的重要工具,在各级行政单位中,`办公`的一个重要内容就是办理和制发文件,即`办文`,办文是每个行政管理单位大量日常的工作。借助新的网络信息技术对公文进行高效有序的电子化处理,是办公自动化建设的重要组成部分,也是关系到电子化办公系统建设全局的基础性工程。

下载

进程创建

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调试
node.js调试

node.js调试可以使用console.log()输出调试信息、断点调试和第三方调试工具。详细介绍:1、console.log()输出调试信息,通过在代码中插入console.log()语句,开发人员可以在控制台输出变量的值、函数的执行结果等信息,以便观察代码的执行流程和状态;2、断点调试,可以在代码中设置断点,以便在特定位置暂停代码的执行,观察变量的值和执行流程等。

347

2023.09.19

JavaScript 全栈开发基础(Node.js + 前端)
JavaScript 全栈开发基础(Node.js + 前端)

本专题系统介绍 JavaScript 在全栈开发中的核心知识结构,涵盖 Node.js 基础、Express/Koa 接口构建、前端交互设计、模块化与包管理、数据库连接、前后端数据通信与部署流程。通过完整项目示例,帮助学习者掌握从浏览器到服务器的一体化开发能力,实现真正意义上的全栈入门。

93

2025.11.26

什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

325

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

231

2023.10.07

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

388

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

571

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

388

2023.07.18

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

6

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Node.js 教程
Node.js 教程

共57课时 | 8.6万人学习

【web前端】Node.js快速入门
【web前端】Node.js快速入门

共16课时 | 2万人学习

Node.js-前端工程化必学
Node.js-前端工程化必学

共19课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号