"cp"를 죽이면 어떻게 되나요? 안전 해요? 어떤 결과가 있습니까?

"cp"를 죽이면 어떻게 되나요? 안전 해요? 어떤 결과가 있습니까?

실행 중인 복사 명령을 종료하기 위해 +를 cp입력 하면 Ctrlext4 파일 시스템에 어떤 결과가 발생합니까 ?C

파일 시스템이 손상되었나요? 불완전하게 복사된 파일이 차지하는 파티션 공간을 삭제 후에도 계속 사용할 수 있나요?

그리고 가장 중요한 것은 cp프로세스를 종료해도 안전합니까?

답변1

이것은 안전하지만 당연히 복사를 완료하지 않았을 수도 있습니다.

이 명령을 실행하면 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는 작업 중에 종료되지 않으므로 파일 시스템이 손상될 위험이 없습니다.

답변2

이는 사용자 공간 명령 이므로 cp파일 시스템의 무결성에 영향을 미치지 않습니다.

물론, 실행 중인 프로그램을 종료하면 적어도 하나의 파일이 완전히 복사되지 않을 것이라는 점을 준비해야 합니다 cp.

답변3

숲의 대답, 비록 예쁘지만(많은 경우 정확함) 현대 시스템에서 볼 수 있는 것은 아닙니다⁰. 그들의 말이 맞습니다. 어떤 상황에서도 파일 시스템이 손상되지 않습니다. 그러나 이제 실제적인 경우에는 사본의 절반도 얻지 못할 것입니다!

yesfile(모든 시스템 호출을 기록하는 동안 큰 파일을 생성 하고 파일에 복사하기 위해 copy(동일한 파일 시스템에 있을 필요는 없음) ) 다음과 같이 한다고 가정해 보겠습니다 cp.

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

나는 다른 그림을 얻습니다: 사용자 영역 프로세스 cp아니요실제로 파일의 내용을 다른 파일에 쓰지 않고 읽는 것은 성능 측면에서 끔찍할 것입니다. 최소한 두 개의 컨텍스트 전환이 필요합니다! Userland 프로그램은 호출하고 read, 전환하고, 데이터를 가져오고, 호출하고 write, 전환합니다. 파일이 단일 읽기 버퍼보다 ​​큰 경우 헹구고 반복합니다. 이제 제한된 크기의 버퍼만 읽는 이 정확한 복제 모델은 파일을 절반만 복사할 때 중단을 일으킬 수 있습니다.

대신 copy_file_range시스템 호출을 사용합니다(아래 추적 1 참조) man copy_file_range.

copy_file_range() 시스템 호출은 커널에서 사용자 공간으로 그리고 다시 커널로 데이터를 전송하는 추가 비용 없이 두 파일 설명자 간에 커널 내 복사를 수행합니다. 소스 파일 설명자에서 대상 파일 설명자로 len최대 바이트의 데이터를 복사하여 대상 파일의 요청 범위 내에 있는 모든 데이터를 덮어씁니다 .fd_infd_out

그래서,이 파일의 원자 복사본이 있습니다.시스템 호출, 즉대개인터럽트를 사용하면 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

관련 정보