「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ファイルシステムの整合性には影響しません。

もちろん、実行中のプログラムを終了すると、少なくとも1つのファイルが完全にコピーされないことを準備する必要がありますcp

答え3

森の答え、たとえきれいですが(多くの場合正確です)、現代のシステムで見ることはできません⁰。彼らの言葉は正しいです。どんな状況でもファイルシステムが破損することはありません。しかし今、実際のケースでは、コピーの半分も得られないでしょう!

yesfile(すべてのシステムコールを記録している間に大きなファイルを作成してファイルにコピーするためにcopy(同じファイルシステムにいる必要はありません))次のようにしますcp

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

私は別の画像を得ます:ユーザーエリアプロセスcpいいえ実際には、ファイルの内容を他のファイルに書き込むことなく読み取ることは、パフォーマンスの面でひどいものです。少なくとも2つのコンテキスト切り替えが必要です! Userlandプログラムは、呼び出しread、切り替え、データの取得、呼び出しwrite、切り替えを行います。ファイルが単一の読み取りバッファより大きい場合はすすぎ、繰り返します。限られたサイズのバッファだけを読み取るこの正確なレプリケーションモデルは、ファイルを半分だけコピーすると中断を引き起こす可能性があります。

代わりにcopy_file_rangeシステムコールを使用してください(下記のトレース1を参照)man copy_file_range

この copy_file_range() システムコールは、カーネルからユーザースペースにデータを再度カーネルに転送するための追加料金なしで、2つのファイル記述子間でカーネル内のコピーを実行します。ソースファイルディスクリプタからターゲットファイルディスクリプタに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

関連情報