说约翰尼制作了一个EMPTY文件。它被称为foobar.py
。当约翰尼允许执行它时,他便奔跑了chmod 755 foobar.py
。现在该文件的元数据为
-rw-r--r-- 1 johnny staff 0 Dec 27 22:53 foobar.py
该文件中所有元数据存储在哪里?文件的大小为0,那么在将元数据传输到另一个驱动器时如何保存元数据?
说约翰尼制作了一个EMPTY文件。它被称为foobar.py
。当约翰尼允许执行它时,他便奔跑了chmod 755 foobar.py
。现在该文件的元数据为
-rw-r--r-- 1 johnny staff 0 Dec 27 22:53 foobar.py
该文件中所有元数据存储在哪里?文件的大小为0,那么在将元数据传输到另一个驱动器时如何保存元数据?
Answers:
它没有存储在该文件中。它存储在文件系统中,并且所有参数都被一对一地手动复制(尽管有些参数根本无法复制)。
也就是说,大多数操作系统实际上并没有“使用元数据复制文件”调用。文件复制程序只是创建一个名为的新文件foobar.py
,复制整个0字节的数据,然后使用utime()或SetFileTime()使其修改时间与原始修改时间相同。同样,可以使用chmod()重新设置文件权限或复制POSIX ACL属性来“复制”文件权限。
某些元数据未复制。设置所有权需要root特权,因此其他人文件的副本属于您,并占用您的磁盘配额。不能在Unixes上手动设置ctime(属性更改时间)。btime(出生/创建时间)通常也不会被复制。
比较cp -a foo bar
(复制元数据)和cp foo bar
(不复制):
$ strace -v cp foo条 … open(“ foo”,O_RDONLY)= 3 open(“ bar”,O_WRONLY | O_TRUNC)= 4 read(3,“ test \ n”,131072)= 5 write(4,“ test \ n”,5)= 5 read(3,“”,131072)= 0 关闭(4)= 0 关闭(3)= 0 …
$ strace -v cp -a foo条 … -检索原始元数据 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, st_mtime = 2016-12-28T09:16:55 + 0200.816363098, st_ctime = 2016-12-28T09:16:55 + 0200.816363098})= 0 -复制数据 open(“ foo”,O_RDONLY | O_NOFOLLOW)= 3 open(“ bar”,O_WRONLY | O_TRUNC)= 4 read(3,“ test \ n”,131072)= 5 write(4,“ test \ n”,5)= 5 read(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 \ 377 \ 4 \ 0 \ 4 \ 0 \ 377 \ 377 \ 377 \ 377 \ 0 \ 4 \ 0 \ 377 \ 377 \ 377 \ 377“,28,0)= 0 关闭(4)= 0 关闭(3)= 0 …
通常,存储元数据的文件系统不同。在文件系统的ext2-family上,您提到的元数据(所有者,组,权限,时间)存储在inode中。索引节点还将文件占用的块存储(指向)磁盘上。该索引节点并没有存储的文件名。
您可以通过stat
系统调用(man 2 stat
)访问此数据,并使用该stat
工具进行打印(man stat
)。可以linux/include/linux/fs.h
在内核源代码中找到有关inode字段的详细说明。
还有其他类型的元数据(例如ACL权限)存储在不同的位置。
复制文件时,默认情况下不会复制元数据。而是创建具有默认元数据值的新文件。cp
(-p
,--preserve
)有多种选项,它们指示cp
通过读取旧的元数据stat
并相应地修改新的元数据来复制元数据。
根据文件系统的不同,区域会(半)静态或动态保留,以保留元数据(例如权限,大小等)(有时也保留文件名)。
在Unix中,元数据存储在控制文件所在数据区域的inode中(文件名和相关inode编号存储在目录条目中)。
在某些文件系统中,目录条目是与其他文件一样的文件,但从视图中隐藏。FAT和FAT32就是这样的文件系统(尽管FAT的根目录是“特殊”的)。创建文件时,可以在文件中添加/编辑一个条目,该条目描述了文件所在的文件夹。每个条目都足够大,可以存储文件大小,名称和日期,并且别无其他(长名称占用多个条目;默认条目大小为32个字节,可以使用旧的8 + 3字符格式保存一个名称。 (假设我的记忆正常)。Ext系统与此类似,但是目录条目是动态调整大小的,仅包含名称和inode指针;所有其他信息都在索引节点中。这样,两个条目可能指向同一文件,这对于管理重复文件很有用。
在某些文件系统中,除了元数据之外,inode可能足够大以容纳少量数据,因此,如果文件可以容纳在那里,则不会占用额外的磁盘空间。您创建一个45字节的文件,并且可用磁盘空间完全不变。这些字节存储在 inode 内部。我认为ext *系列支持此功能(也支持NTFS)。这有助于管理大量的非常小的文件。
在其他文件系统中,相当于主要文件系统的“虚拟”文件系统存储了这些额外的属性。不仅文件信息,而且可能还有文件图标。
某些系统同时具有这两种功能:NTFS具有完整的目录元数据,其工作方式类似于inode,并且可以创建备用数据流,以保存进一步的信息,这些信息不会(显然)更改“主”文件中的任何内容。