link 计数和 ls 命令
link count and ls command
我正在学习文件 link 计数。只有当 link 计数为 0 时,文件内容才会被删除。在我的测试中,该进程在目录“/home/hel/myfile”中打开一个文件并休眠 10(s)。同时我使用 "rm /home/hel/myfile" 删除它。然后我使用命令 "ls" 并显示没有这样的文件。但实际上文件还存在,因为fd还没有关闭。如果是这样,"ls" 无法显示文件是否真的存在。我对 "ls" 感到困惑。或者如何判断一个文件是否真的存在?
#include <fcntl.h>
#include <stdlib.h>
int main(void)
{
int fd;
fd = open("/home/hel/myfile", O_RDWR);
if (fd < 0) {
exit(-1);
}
sleep(10); // sleep 10(s)
close(fd);
return 0;
}
文件名就像一个指向真实数据的标签。真实数据存储在an inode中。一个索引节点通常只有一个指向它的文件名,link 计数为一。但它可以有多个。
这是一个直观的例子。当你创建一个普通文件时,它会将你的数据放在一个新的索引节点中,并将文件名指向它。
$ echo "foo" > some/file
"some/file" -> [data: "foo", links: 1]
当你制作另一个文件时,同样的事情会发生。
$ echo "bar" > another/file
"some/file" -> [data: "foo", links: 1]
"another/file" -> [data: "bar", links: 1]
但是如果你做一个hard link,现在inode有两个link。
$ ln some/file some/link
"some/file" -> [data: "foo", links: 2]
^
"some/link" -----/
"another/file" -> [data: "bar", links: 1]
事实上,普通文件很难link。除了文件名,没有什么可以区分 some/file
和 some/link
。两者都不是 "real" 文件,它们都是 links.
如果 link 被删除,link 计数会减少。这就是为什么在某些语言中您调用 unlink
来删除文件的原因。
$ rm some/file
"some/link" -> [data: "foo", links: 1]
"another/file" -> [data: "bar", links: 1]
当它到达0时,inode可以被覆盖。数据仍然存在,但没有任何指向它的东西。这就是您有时可以恢复已删除文件的原因。
$ rm some/link
[data: "foo", links: 0]
"another/file" -> [data: "bar", links: 1]
文件句柄呢?他们不会更改 link 计数。相反,在 Unix(不是 Windows)上,操作系统会跟踪给定 inode 有多少个打开的句柄。只要有一个打开的句柄,它就不会允许 inode 被覆盖。
fd = open("another/file", O_RDWR);
[data: "foo", links: 0]
fd ---\
\/
"another/file" -> [data: "bar", links: 1]
$ rm another/file
[data: "foo", links: 0]
fd -> [data: "bar", links: 0]
close(fd);
[data: "foo", links: 0]
[data: "bar", links: 0]
这使您可以执行诸如创建临时文件、打开句柄以对其进行读取和写入以及立即将其删除等操作。然后程序可以继续读写临时磁盘存储,但没有人可以看到该文件。
我正在学习文件 link 计数。只有当 link 计数为 0 时,文件内容才会被删除。在我的测试中,该进程在目录“/home/hel/myfile”中打开一个文件并休眠 10(s)。同时我使用 "rm /home/hel/myfile" 删除它。然后我使用命令 "ls" 并显示没有这样的文件。但实际上文件还存在,因为fd还没有关闭。如果是这样,"ls" 无法显示文件是否真的存在。我对 "ls" 感到困惑。或者如何判断一个文件是否真的存在?
#include <fcntl.h>
#include <stdlib.h>
int main(void)
{
int fd;
fd = open("/home/hel/myfile", O_RDWR);
if (fd < 0) {
exit(-1);
}
sleep(10); // sleep 10(s)
close(fd);
return 0;
}
文件名就像一个指向真实数据的标签。真实数据存储在an inode中。一个索引节点通常只有一个指向它的文件名,link 计数为一。但它可以有多个。
这是一个直观的例子。当你创建一个普通文件时,它会将你的数据放在一个新的索引节点中,并将文件名指向它。
$ echo "foo" > some/file
"some/file" -> [data: "foo", links: 1]
当你制作另一个文件时,同样的事情会发生。
$ echo "bar" > another/file
"some/file" -> [data: "foo", links: 1]
"another/file" -> [data: "bar", links: 1]
但是如果你做一个hard link,现在inode有两个link。
$ ln some/file some/link
"some/file" -> [data: "foo", links: 2]
^
"some/link" -----/
"another/file" -> [data: "bar", links: 1]
事实上,普通文件很难link。除了文件名,没有什么可以区分 some/file
和 some/link
。两者都不是 "real" 文件,它们都是 links.
如果 link 被删除,link 计数会减少。这就是为什么在某些语言中您调用 unlink
来删除文件的原因。
$ rm some/file
"some/link" -> [data: "foo", links: 1]
"another/file" -> [data: "bar", links: 1]
当它到达0时,inode可以被覆盖。数据仍然存在,但没有任何指向它的东西。这就是您有时可以恢复已删除文件的原因。
$ rm some/link
[data: "foo", links: 0]
"another/file" -> [data: "bar", links: 1]
文件句柄呢?他们不会更改 link 计数。相反,在 Unix(不是 Windows)上,操作系统会跟踪给定 inode 有多少个打开的句柄。只要有一个打开的句柄,它就不会允许 inode 被覆盖。
fd = open("another/file", O_RDWR);
[data: "foo", links: 0]
fd ---\
\/
"another/file" -> [data: "bar", links: 1]
$ rm another/file
[data: "foo", links: 0]
fd -> [data: "bar", links: 0]
close(fd);
[data: "foo", links: 0]
[data: "bar", links: 0]
这使您可以执行诸如创建临时文件、打开句柄以对其进行读取和写入以及立即将其删除等操作。然后程序可以继续读写临时磁盘存储,但没有人可以看到该文件。