しばらく何か混乱していました。
[15:40:50][/tmp]$ mkdir a
[15:40:52][/tmp]$ strace rmdir a
execve("/usr/bin/rmdir", ["rmdir", "a"], [/* 78 vars */]) = 0
brk(0) = 0x11bb000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff3772c3000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=245801, ...}) = 0
mmap(NULL, 245801, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff377286000
close(3) = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\36\3428<\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2100672, ...}) = 0
mmap(0x3c38e00000, 3924576, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3c38e00000
mprotect(0x3c38fb4000, 2097152, PROT_NONE) = 0
mmap(0x3c391b4000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b4000) = 0x3c391b4000
mmap(0x3c391ba000, 16992, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3c391ba000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff377285000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7ff377283000
arch_prctl(ARCH_SET_FS, 0x7ff377283740) = 0
mprotect(0x609000, 4096, PROT_READ) = 0
mprotect(0x3c391b4000, 16384, PROT_READ) = 0
mprotect(0x3c38c1f000, 4096, PROT_READ) = 0
munmap(0x7ff377286000, 245801) = 0
brk(0) = 0x11bb000
brk(0x11dc000) = 0x11dc000
brk(0) = 0x11dc000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106070960, ...}) = 0
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7ff370d5a000
close(3) = 0
rmdir("a") = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++
[15:40:55][/tmp]$ touch a
[15:41:16][/tmp]$ strace rm a
execve("/usr/bin/rm", ["rm", "a"], [/* 78 vars */]) = 0
brk(0) = 0xfa8000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3b2388a000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=245801, ...}) = 0
mmap(NULL, 245801, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3b2384d000
close(3) = 0
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p\36\3428<\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2100672, ...}) = 0
mmap(0x3c38e00000, 3924576, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x3c38e00000
mprotect(0x3c38fb4000, 2097152, PROT_NONE) = 0
mmap(0x3c391b4000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b4000) = 0x3c391b4000
mmap(0x3c391ba000, 16992, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x3c391ba000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3b2384c000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f3b2384a000
arch_prctl(ARCH_SET_FS, 0x7f3b2384a740) = 0
mprotect(0x60d000, 4096, PROT_READ) = 0
mprotect(0x3c391b4000, 16384, PROT_READ) = 0
mprotect(0x3c38c1f000, 4096, PROT_READ) = 0
munmap(0x7f3b2384d000, 245801) = 0
brk(0) = 0xfa8000
brk(0xfc9000) = 0xfc9000
brk(0) = 0xfc9000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=106070960, ...}) = 0
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f3b1d321000
close(3) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
newfstatat(AT_FDCWD, "a", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
geteuid() = 1000
newfstatat(AT_FDCWD, "a", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
faccessat(AT_FDCWD, "a", W_OK) = 0
unlinkat(AT_FDCWD, "a", 0) = 0
lseek(0, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek)
close(0) = 0
close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++
ディレクトリとファイルを削除するために別々のシステムコールがあるのはなぜですか?これらの2つの作業が意味的に異なる理由は何ですか?
答え1
ディレクトリの特別な点は、ディレクトリ内で複数のファイルとディレクトリを参照できることです。したがって、親ディレクトリを削除すると、そのファイルはすべてアクセス可能な参照ポイントを失い、プロセスも同じです。この場合、次のようなさまざまrmdir()
なテストがありますunlink()
。
ディレクトリが空でない場合。ディレクトリが空でないと、コンテンツが
unlink
削除/削除されるまでコンテンツを削除できません。ENOTEMPTY pathname contains entries other than . and .. ; or, pathname has .. as its final component. POSIX.1-2001 also allows EEXIST for this condition.
ディレクトリが使用されている場合。プロセスが現在のディレクトリを失うと、問題が発生し、未定義の動作が発生する可能性があります。それらをブロックする方が良いです。
EBUSY pathname is currently in use by the system or some process that prevents its removal. On Linux this means pathname is currently used as a mount point or is the root directory of the calling process.
これらの検査の場合にはunlink()
存在しません。実際にファイル名を削除することができますunlink()
が、それを有効または参照するプロセスでは、問題なくファイル名を変更できます。ファイルはファイル記述子が存在するまで存在し、検索する場所がわからない限り、新しいプロセスからアクセスできません。これは* NIXファイルシステムの虹色の手の魔法の一部です。
unlinkat()
これで、両方にアクションがunlink()
あるかrmdir(2)
、目的のパスに応じてアクションがあります。
答え2
私の個人的なWikiページからコピーしましたunlink("/") と rmdir("/") が失敗するのはなぜですか?:
しかし、特別なファイル形式があります。目次。ファイルシステムの正しい動作を保証するには、ディレクトリへのハードリンクを一貫した方法で維持する必要があります。たとえば、ディレクトリを作成または削除すると、複数のハードリンクが自動的に作成または削除されます/var/tmp/foo
。新しいディレクトリを参照する2つのハードリンクが次の場所に作成されます。
/var/tmp/foo
– あなたが作成を要求した名前自体/var/tmp/foo/.
–.
この新しいディレクトリの名前
さらに、親ディレクトリを参照する別のハードリンクが作成されるため、/var/tmp/foo/..
新しく作成されたディレクトリのリンク数は2になります。
以前のUnixシステムでは、ディレクトリハードリンクを手動で操作できました。これは主にディレクトリの名前を変更するために使用されました。名前変更(2)当時、システムコールは存在しませんでした。ディレクトリまたは他のファイル形式のファイル名を手動で変更するには、次のコマンドを使用して新しい名前を作成します。リンク(2)を押し、次のようにして古い名前を削除します。切断(2);しかし、この方法を使用してディレクトリを操作することは強すぎる場合が多いです。ユーザーはディレクトリを不適切にリンクしたり切断したりすることで、ファイルシステムに不整合が生じやすくなります。たとえば、親ディレクトリを参照せずにハードリンクを作成すると、無限ディレクトリループが発生したり、最初に別の場所にリンクを作成せずにディレクトリハードリンクを削除したりすると、壊れています。」 「システムツリー、これらの不一致が発生すると予想されます。システムチェック(8)次回のシステム起動時に問題が正しく修正されるという保証はありません。
Unixシステムで提供目次(2)このシステムを使用してデフォルトのハードリンクだけでなく、ディレクトリ、inodeを正しく削除するには、ハードリンクを参照するパスパスではなく、ハードリンクがディレクトリタイプinodeを参照し、ディレクトリが空である必要が.
あり..
ます。 。インクルード.
とリンクのみ..
が呼び出しに成功すると、この2つのハードリンク、パスで指定されたディレクトリハードリンク、およびディレクトリinodeが削除されます。