我尝试在Linux和Windows中运行以下代码:
const fs = require("fs/promises")
const {
constants,
existsSync
} = require("fs")
async function copy() {
try {
await fs.writeFile("demo.txt", "Hello World")
await fs.copyFile("demo.txt", "copy.txt", constants.COPYFILE_FICLONE_FORCE)
} finally {
fs.rm("demo.txt")
if (existsSync("copy.txt")) fs.rm("copy.txt")
}
}
copy().catch(console.error)
两者均失败,错误消息:
Linux:
[Error: ENOTSUP: operation not supported on socket, copyfile 'demo.txt' -> 'copy.txt'] {
errno: -95,
code: 'ENOTSUP',
syscall: 'copyfile',
path: 'demo.txt',
dest: 'copy.txt'
}
窗口:
Error: ENOSYS: function not implemented, copyfile 'demo.txt' -> 'copy.txt'] {
errno: -4054,
code: 'ENOSYS',
syscall: 'copyfile',
path: 'demo.txt',
dest: 'copy.txt'
}
nodejs的官方文档说fs.constants.COPYFILE_FICLONE_FORCE
:复制操作将尝试创建写时复制重新链接。如果平台不支持写时复制,那么操作将失败。”
大多数服务器操作系统应该是Windows服务器或Linux。
我确信nodejs的开发人员不会开发一个不起作用的特性,所以我想知道在什么平台上可以使用“fs.constants.COPYFILE_FICLONE_FORCE”文件复制方法。达尔文,BSD,还是其他OS?
以下是一些参考信息:
node version: v16.14.2
windows version: windows 10
windows file system: NTFS
linux version: 5.10.109-1-MANJARO
linux core version: 5.10
linux file system: ext4
4条答案
按热度按时间kqhtkvqz1#
Node.js最初是由Joyent赞助并大量开发的。Joyent也是Illumos(它基于Solaris,Solaris是Sun和后来的Oracle销售的BSD发行版)的忠实支持者。
在早期,node在Illumos上进行了大量测试。还有惊喜。Illumos的默认文件系统是ZFS,它具有写时复制功能。
但是ZFS也可以在其他操作系统上使用(苹果甚至一度为OSX开发了一个官方的ZFS驱动程序),所以如果你使用ZFS之类的东西,你可以在写时复制。我不太确定node的写时复制支持是否适用于其他写时复制文件系统,如Btrfs,但理论上应该是这样。
g52tjvyc2#
这是一个非常先进的FS功能。
如果系统上的文件系统支持特定的Activity(COPYFILE_FICLONE_FORCE),则它将工作。否则,它将失败。它只是说没有/自动/回退。
COW就像是让FS创建一个符号链接到你复制的文件,但是如果(并且只有当)你修改了那个文件,它实际上会创建一个“真实的的”副本并应用你的修改。
所以,如果你需要非常/非常/快速地复制一个文件。也许有时(不是所有时候)它可能需要稍后修改,那么这个选项就很有意义。否则,您可能只需要执行一个“常规”拷贝,让文件系统缓存来处理内务。
wd2eg0qa3#
这是一个文件系统特性,不是操作系统。如果文件系统支持它,那么显然您可以直接调用驱动程序函数来执行写时复制操作
但是,如果操作系统支持,当底层也支持CoW,那么它会更容易,因为你可以利用系统调用,将工作在任何CoW文件系统(ZFS,Btrfs,XFS,ReFS,APFS之间的常见操作系统)。由于您使用的是nodejs,因此会有另一个依赖于nodejs实现系统调用的抽象层
如果你使用ext4,那么你就不走运了,因为它不支持CoW。在Linux上,您必须使用具有CoW支持的FS,如ZFS,Btrfs,XFS。还有一些其他的文件系统支持CoW,比如ext3cow或Next3,但是它们已经过时了
在Windows方面,自Windows Server 2016以来,在ReFS上支持copy-on-write。甚至还有一个.NET library来避免直接调用Win32 API。同样,NTFS是不可能的,根本没有CoW支持。不幸的是,到目前为止,nodejs使用的libuv还没有更新到使用Windows CoW API。有一个closed PRs though
在macOS上,您还可以通过APFS获得CoW支持,但不支持HFS或HFS+。看起来libuv也支持macOS
tzcvj98z4#
提示是在名称ficlone中,这指的是ioctl_ficlone*系列的系统调用,它最初是Linux btrfs特定内核接口的一部分。
系统调用已经被通用化,并成为Linux通用文件系统接口的一部分,因此其他文件系统驱动程序也可以实现系统调用。我相信XFS也为类似的CoW功能实现了这个系统调用。
ext4和ntfs不支持写时复制,所以如果这是您使用的文件系统,那么使用ficlone创建CoW文件将永远不起作用。
这在Windows上可能也不起作用,因为它们使用完全不同的文件系统接口和完全不同的方式来创建CoW文件。当在ReFS上运行时,该标志可能会被shimmed以执行与Windows Filesystem API等效的功能,但我认为当前版本的nodejs不会这样做。