AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 466244
Accepted
Seninha
Seninha
Asked: 2018-09-02 05:45:00 +0800 CST2018-09-02 05:45:00 +0800 CST 2018-09-02 05:45:00 +0800 CST

当我杀死'cp'时会发生什么?它安全吗?它有什么后果吗?

  • 772

当我在运行时键入+终止复制cp命令时,对 ext4 文件系统有什么影响?CtrlC

文件系统是否损坏?不完整的复制文件所占用的分区空间在删除后是否还能使用?

而且,最重要的是,终止cp进程是否安全?

files filesystems
  • 3 3 个回答
  • 4138 Views

3 个回答

  • Voted
  1. Best Answer
    forest
    2018-09-02T11:59:15+08:002018-09-02T11:59:15+08:00

    这样做是安全的,但自然你可能还没有完成副本。

    当cp命令运行时,它会进行系统调用,指示内核制作文件的副本。系统调用或系统调用是应用程序可以用来向内核请求服务的函数,例如向磁盘读取或写入数据。用户空间进程只是等待系统调用完成。如果您要跟踪来自 的调用cp ~/hello.txt /mnt,它将如下所示:

    open("/home/user/hello.txt", O_RDONLY)           = 3
    open("/mnt/hello.txt", O_CREAT|O_WRONLY, 0644)   = 4
    read(3, "Hello, world!\n", 131072)               = 14
    write(4, "Hello, world!\n", 14)                  = 14
    close(3)                                         = 0
    close(4)                                         = 0
    

    这对要复制的每个文件重复。由于这些系统调用的工作方式,不会发生损坏。当输入这样的系统调用时,致命信号只会在系统调用完成后生效,而不是在它运行时生效(实际上,信号仅在内核空间到用户空间上下文切换期间到达)。请注意,某些信号,例如read(),可以提前终止。

    因此,强制终止进程只会导致它在当前运行的系统调用返回后终止。这意味着文件系统驱动程序所在的内核可以自由地完成将文件系统置于正常状态所需完成的操作。任何此类 I/O 都不会在操作过程中终止,因此不存在文件系统损坏的风险。

    • 26
  2. schily
    2018-09-02T05:52:17+08:002018-09-02T05:52:17+08:00

    由于cp是用户空间命令,因此不会影响文件系统的完整性。

    你当然需要做好准备,如果你杀死一个正在运行的程序,至少有一个文件不会被完全复制cp。

    • 23
  3. Marcus Müller
    2021-11-02T10:54:43+08:002021-11-02T10:54:43+08:00

    森林的答案,虽然很漂亮(在许多情况下是正确的),但不是您在现代系统上看到的⁰。他们是对的——在任何情况下都不会损坏您的文件系统。但在实际情况下,这些天你不会得到半份!

    假设我这样做(只是为了生成一个大文件yesfile,并将其复制到一个文件copy中(不必在同一个文件系统上),同时记录所有系统调用 mady by cp):

    cd /tmp
    yes | head -n$((10**7)) > yesfile
    strace -o strace.output cp yesfile copy
    

    我得到了不同的画面:用户态进程实际上cp并没有读取文件的内容,也没有将其写入另一个文件;这在性能方面会很糟糕:它至少需要两个上下文切换!用户态程序调用read、切换、获取数据、调用write、切换;如果文件大于单个读取缓冲区,则冲洗并重复。现在这种精确的重复模型,只读取有限大小的缓冲区,可能会导致文件中断时复制一半。

    相反,它使用copy_file_range系统调用(参见下面的跟踪¹);man copy_file_range告诉我们:

    系统 copy_file_range() 调用在两个文件描述符之间执行内核内复制,而无需将数据从内核传输到用户空间然后再返回内核的额外成本。len它将源文件描述符中最多字节的数据复制到fd_in目标文件描述符fd_out,覆盖目标文件请求范围内存在的任何数据。

    所以,有一个原子的copy-this-file系统调用,通常会用到,所以中断cp不能中断复制。


    如果您的源文件系统和目标文件系统相同,以及 Btrfs、CIFS、NFS 4.2、OCFS2、overlayfs 或 XFS源(在撰写本文时,仅针对这些 Linux 具有 reflink 功能),情况会变得更好:如果

    ioctl(4, BTRFS_IOC_CLONE or FICLONE, 3)
    

    成功后,系统根本不需要复制文件内容——相反,只需将属于源文件的块列表复制到目标文件;每个块都有一个增加的引用计数器,因此当任何进程写入这些文件中的任何一个时,文件系统都会透明地对其进行写时复制。所以,这些东西更加原子!


    ⁰ 至少,如果我的 GNU coreutils 8.32 和 fedora 34 的反向移植copy_file_range 补丁/Linux 5.13.5 被认为是现代的。
    ¹ 相关的 strace 输出

     156   │ newfstatat(AT_FDCWD, "yesfile", {st_mode=S_IFREG|0644, st_size=20000000, ...}, 0) = 0
     157   │ newfstatat(AT_FDCWD, "copy", 0x7fff982d5e70, 0) = -1 ENOENT (No such file or directory)
     158   │ openat(AT_FDCWD, "yesfile", O_RDONLY)   = 3
     159   │ newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=20000000, ...}, AT_EMPTY_PATH) = 0
     160   │ openat(AT_FDCWD, "copy", O_WRONLY|O_CREAT|O_EXCL, 0644) = 4
     161   │ newfstatat(4, "", {st_mode=S_IFREG|0644, st_size=0, ...}, AT_EMPTY_PATH) = 0
     162   │ ioctl(4, BTRFS_IOC_CLONE or FICLONE, 3) = -1 EOPNOTSUPP (Operation not supported)
     163   │ fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
     164   │ mmap(NULL, 139264, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0be58ca000
     165   │ uname({sysname="Linux", nodename="workhorse", ...}) = 0
     166   │ copy_file_range(3, NULL, 4, NULL, 9223372035781033984, 0) = 20000000
     167   │ copy_file_range(3, NULL, 4, NULL, 9223372035781033984, 0) = 0
     168   │ close(4)                                = 0
     169   │ close(3)                                = 0
     170   │ munmap(0x7f0be58ca000, 139264)          = 0
    
    • -1

相关问题

  • Virtualbox 动态分配磁盘 *.vdi 不断增长

  • 如何找到特定的文件类型并将它们 tar?

  • du/df 和 ls 报告不同的磁盘使用情况

  • Linux 内核开发人员如何处理数百万行代码的工作?他们是一种方法吗?[关闭]

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve