保存文件时元数据去哪里了?

保存文件时元数据去哪里了?

假设 Johnny 创建了一个 EMPTY 文件。它被称为foobar.py。当 Johnny 允许执行它时,他运行chmod 755 foobar.py。该文件现在具有以下元数据:

-rw-r--r-- 1 johnny staff    0 Dec 27 22:53 foobar.py

该文件中的所有元数据都存储在哪里?文件大小为 0,那么当文件传输到另一个驱动器时,它如何保留元数据?

答案1

它没有被存储该文件。它存储在文件系统中,所有参数都是手动逐个复制的(尽管有些参数根本无法复制)。

也就是说,大多数操作系统实际上没有“复制带有元数据的文件”调用。文件复制程序只是创建一个名为 的新文件foobar.py,复制整个 0 字节数据,然后使用utime()或者设置文件时间()使其修改时间看起来与原始修改时间相同。同样,文件权限也可以通过使用 chmod() 重新设置或复制 POSIX ACL 属性来“复制”。

某些元数据不会被复制。设置所有权需要 root 权限,因此其他人的文件副本属于你,并占用你的磁盘配额。在 Unix 上,ctime(属性更改时间)无法手动设置;btime(诞生/创建时间)通常也不会被复制。

比较cp -a foo bar(复制元数据)和cp foo bar(不复制元数据):

$ strace -v cp foo bar
打开(“foo”,O_RDONLY) = 3
打开(“bar”,O_WRONLY|O_TRUNC) = 4
读取(3,“测试\n”,131072)= 5
写入(4,“测试\n”,5)= 5
读取(3,“”,131072)= 0
关闭(4)= 0
关闭(3)= 0
$ strace -v cp -a foo bar
 -- 检索原始元数据
lstat("foo", {st_dev=makedev(254, 0), st_ino=60569468, st_mode=S_IFREG|0644,
             st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8,
             st_size=5,st_atime=2016-12-28T09:16:59+0200.879714332,
             时间 = 2016-12-28T09:16:55+0200.816363098,
             st_ctime=2016-12-28T09:16:55+0200.816363098})= 0
 -- 数据已复制
打开(“foo”,O_RDONLY|O_NOFOLLOW) = 3
打开(“bar”,O_WRONLY|O_TRUNC) = 4
读取(3,“测试\n”,131072)= 5
写入(4,“测试\n”,5)= 5
读取(3,“”,131072)= 0
 -- 修改时间已复制
utimensat(4, NULL, [{tv_sec=1482909419, tv_nsec=879714332},
                    {tv_sec=1482909415,tv_nsec=816363098}], 0) = 0
 – 所有权被复制(仅使用“sudo [strace] cp”)
fchown (4, 1000, 1000) = 0
 -- 扩展属性被复制(xdg.origin.url 由浏览器、wget 设置)
flistxattr (3, NULL, 0) = 0
flistxattr(3, “user.xdg.origin.url\0”, 20) = 20
fgetxattr(3, “user.xdg.origin.url”, “https://superuser.com/”, 22) = 22
fsetxattr(4, “user.xdg.origin.url”, “https://superuser.com/”, 22, 0) = 0
 -- POSIX ACL 不存在,因此从 st_mode 构建基本 ACL
 ——(在这种情况下,简单的 fchmod() 也可以起作用)
fgetxattr(3, “system.posix_acl_access”, 0x7ffc87a50be0, 132) = -1 ENODATA (无可用数据)
fsetxattr (4, “system.posix_acl_access”, “\2\0\0\0\1\0\6\0\377\377\377\4\0\4\0\377\377\377\377 \0\4\0\377\377\377\377”, 28, 0) = 0
关闭(4)= 0
关闭(3)= 0

答案2

元数据的存储位置通常因文件系统而异。在 ext2 系列文件系统中,您提到的元数据(所有者、组、权限、时间)存储在索引节点。 inode 还存储文件在磁盘上占用的块(指针)。 inode 不不是存储文件名。

stat您可以使用系统调用 ( )访问此数据man 2 stat,并使用该stat工具将其打印出来 ( )。可以在内核源代码中man stat找到 inode 字段的详细描述。linux/include/linux/fs.h

还有其他类型的元数据(例如ACL 权限) 存储在不同的地方。

复制文件时,默认情况下不会复制元数据。相反,会创建一个具有默认元数据值的新文件。有各种选项cp( -p, --preserve) 指示cp也复制元数据,方法是读取旧元数据并stat相应地修改新元数据。

答案3

根据文件系统,区域以(半)静态或动态的方式保留,以保存元数据,例如权限、大小和其他元数据(有时也包括文件名)。

在 Unix 中,元数据存储在索引节点控制文件所在的数据区域(而文件名和相关的 inode 号存储在目录条目中)。

在某些文件系统中,目录条目与其他文件一样,只是隐藏在视图中。FAT 和 FAT32 就是这样的文件系统(不过 FAT 的根目录比较“特殊”)。创建文件时,您会在文件中添加/编辑一个条目,该条目描述文件所在的文件夹。每个条目都足够大,可以存储文件大小、名称和日期,而不能存储其他任何内容(长名称占用多个条目;默认条目大小为 32 字节,可以容纳旧 8+3 字符格式的单个名称。当然,所有这些都是在我的记忆力正常的情况下进行的)。Ext 系统类似,但目录条目的大小是动态的,并且只包含名称和 inode 指针;所有其他信息都在 inode 中。这样,两个条目可能指向同一个文件,这对于管理重复文件很有用。

在某些文件系统中,inode 可以足够大,除了元数据之外,还可以容纳少量数据,因此如果文件可以放在那里,它就不会占用额外的磁盘空间。您创建一个 45 字节的文件,可用磁盘空间根本不会改变;这些字节存储在里面inode。我认为 ext* 系列支持此功能(NTFS 也支持)。这有助于管理大量非常小的文件。

在其他文件系统中,除了主文件系统之外,还有一个相当于“幻影”文件系统的东西,用于存储这些额外的属性。不仅文件信息,但可能是文件图标也一样。

有些系统同时具备这两种功能:NTFS 具有以 inode 方式工作的完整目录元数据,并且能够创建替代数据流保存进一步的信息,但这些信息显然不会改变“主”文件中的任何内容。

相关内容