我的一个朋友喜欢在 Linux 环境中编程,但对 Linux 的管理不太了解,最近遇到了一个问题,他的操作系统 (Ubuntu) 报告“XXX 卷上的磁盘空间不足”。但是当他去查看卷时,还剩下700GB。在浪费了很多时间之后,他终于发现自己的 inode 用完了。(他在这个卷上存储了来自备份系统的大量小增量更新,并烧毁了他的所有 inode。)
他问我为什么 Linux 内核报告错误消息(“磁盘空间不足”)而不是正确报告(“inode 不足”)。我不知道,所以我想我会问 StackExchange。
有谁知道为什么会这样?为什么这么多年还没有修好?(我记得 1995 年另一个朋友告诉我这个问题。)
在 PHP 中,fileinode()
函数返回文件的 inode。我想知道是否可以使用它来确定文件是否被重命名、移动或修改。
我做了一些测试,重命名后 inode 似乎保持不变。这种行为是否一致?它适用于任何类型的文件,在任何 Linux 发行版上吗?
我对 Linux mmaps 文件进入主内存的方式感兴趣(在我的上下文中它用于执行,但我猜 mmap 过程对于写入和读取也是相同的)以及它使用的大小。
所以我知道 Linux 通常使用 4kB 页面大小的分页(我可以在内核中的哪个位置找到这个大小?)。但这对于分配的内存究竟意味着什么:假设您有一个大小为几千字节的二进制文件,让我们说 5812B 并执行它。内核中发生了什么:它是否分配了 2*4kB,然后将 5812B 复制到这个空间,在第 2 页浪费了 >3KB 的主内存?
如果有人知道定义页面大小的内核源文件中的文件,那就太好了。
我想我的第二个问题也很简单:我假设 5812B 作为文件大小。是不是这个大小只是从 inode 中获取的?
我目前正在使用backintime
我的文件系统的“快照”。它类似于rsnapshot
它,硬链接到未更改的文件。我最近在我的EXT4
文件系统上用完了 inode 。df -hi
显示我已经使用了 940 万个 inode。当前目录数乘以快照数加上当前文件数的粗略计算表明,我实际上可能使用了 940 万个 inode。
据我了解,EXT4
文件系统可以支持大约 2^32 个 inode。我正在考虑重新格式化分区以使用所有 40 亿个左右的 inode,但我担心这是一个坏主意。在EXT4
文件系统中拥有如此多的 inode 有什么缺点?对于这样的应用程序,是否有更好的文件系统选择?
我在这个页面中看到 inode 有一个链接计数器来知道有多少文件(阅读:“目录条目”)指向这个 inode。有没有办法在不遍历整个文件系统的情况下知道哪些目录包含这些条目?这些信息是否存储在某个地方?
struct inode {
kdev_t i_dev;
unsigned long i_ino;
umode_t i_mode;
nlink_t i_nlink;
uid_t i_uid;
gid_t i_gid;
…
};
Run Code Online (Sandbox Code Playgroud) 我知道这篇文章存在: 为什么硬链接仅在同一文件系统中有效? 但不幸的是它并没有引起我的注意。
https://www.kernel.org/doc/html/latest/filesystems/ext4/directory.html 我正在阅读 Galvin 的操作系统概念,并发现了一些非常有用的资源,例如 Linux 内核文档。
文件系统中可能有许多目录条目引用相同的索引节点号——这些目录条目称为硬链接,这就是硬链接无法引用其他文件系统上的文件的原因。
作者一开始就这么说。但我不明白其背后的原因。
inode 包含的信息:
https://www.grymoire.com/Unix/Inodes.html
既然 inode 包含这些信息,那么让硬链接引用其他文件系统上的文件有什么问题呢?
如果硬链接引用其他文件系统会出现什么问题?
关于硬链接:
“硬链接”一词具有误导性,更好的术语是“目录项”。
目录是一种文件类型,包含(至少)一对文件名和索引节点。目录中的每个条目都是一个“硬链接”,包括符号链接。当您创建新的“硬链接”时,您只是向某个目录添加一个新条目,该目录引用与现有目录条目相同的 inode。
这就是我如何可视化目录概念在操作系统中的样子。根据上面引用的文本,每个条目都是一个硬链接。我看到的唯一问题是多个文件系统可以具有相同范围的索引节点(但我不这么认为,因为索引节点在操作系统中受到限制)。
另外,为什么在 inode 本身中添加有关文件系统的新信息不是很好呢?那不是真的很方便吗?
文件 hello.c 被重命名为 hi.c。如 stat 命令的输出所示,[change] 时间戳已更改。通常在文件的 inode 被修改时更改。为什么用 mv 命令重命名会改变 inode 的内容以及实际上修改了哪个属性?
xyz@linuxPC:~/Documents$ stat hello.c
File: ‘hello.c’
Size: 568 Blocks: 8 IO Block: 4096 regular file
Device: 809h/2057d Inode: 261889 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1000/ xyz) Gid: ( 1000/ xyz)
Access: 2015-04-22 19:54:34.889330399 +0530
Modify: 2015-04-22 19:54:34.241330427 +0530
Change: 2015-06-21 15:46:45.365465523 +0530
Birth: -
xyz@linuxPC:~/Documents$ mv hello.c hi.c
xyz@linuxPC:~/Documents$ stat hi.c
File: ‘hi.c’
Size: 568 Blocks: 8 IO Block: 4096 regular file
Device: 809h/2057d Inode: 261889 Links: …
Run Code Online (Sandbox Code Playgroud) 我知道目录是一个包含行类型为“名称 = 节点编号”的文件。
当我请求像 /home/my_file.txt 这样的路径时,会发生以下步骤:
问题:如果主目录是另一个文件系统的挂载点,驻留在另一个块设备上,这个过程有何不同?当系统理解时,这个目录是挂载点,它是如何做到的?这些信息存储在哪里 - 在 inode、目录文件或其他地方?
例如,显示 inode 编号的根目录列表的一部分:
ls -d1i /*/
inode # name
656641 /bin/
2 /boot/
530217 /cdrom/
2 /dev/
525313 /etc/
2 /home/
393985 /lib/
Run Code Online (Sandbox Code Playgroud)
在这里,主目录和引导目录是挂载点并驻留在自己的文件系统上。运行我的伪代码算法(上面写的)并停留在第 3 步 - 在这种情况下,home inode 号是 2,它位于另一个文件系统和另一个块设备中。
总结:如果你在一个新的挂载命名空间/tmp/a
之上绑定挂载一个文件/tmp/b
,但是随后/tmp/b
父命名空间中的inode发生变化,则绑定挂载在子命名空间中消失。我试图理解为什么。
mount(8) 没有公开绑定挂载单个文件(只是目录)的能力,因此重现它需要一个额外的可执行文件来发出必要的 mount(2) 系统调用。下面是一个简单的例子(参考bmount
如下):
#include <sys/mount.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("requires exactly 2 args\n");
return 1;
}
int err = mount(argv[1], argv[2], "none", MS_BIND, NULL);
if (err == 0) {
return 0;
} else {
printf("mount error (%d): %s\n", errno, strerror(errno));
return 1;
}
}
Run Code Online (Sandbox Code Playgroud)
设置测试用例:
# echo a > /tmp/a; echo b > /tmp/b; echo c > …
Run Code Online (Sandbox Code Playgroud) 我喜欢ncdu的导航和功能,但我不想按大小对文件夹进行排名,而是想按文件计数对它们进行排名。例如,首先列出包含更多文件的文件夹,您可以使用箭头键导航层次结构。
有什么选择可以实现这一点吗?如果没有,我想知道修改源代码以提供我想要的功能会有多困难。也许已经有其他东西可以做到这一点了?
inode ×10
filesystems ×5
linux ×4
files ×2
mount ×2
bind-mount ×1
debian ×1
disk-usage ×1
ext4 ×1
hard-link ×1
kernel ×1
linux-kernel ×1
memory ×1
mmap ×1
mv ×1
ncdu ×1
rename ×1