当创建Ext2文件系统时,系统管理员可以根据预期的文件平均长度来选择最佳块大小(从1024B~4096B),当文件的平均长度小于几千字节时,块的大小为1024B是最佳的,这样会产生较少的内部碎片。
内部碎片就是已经被分配出去(能明确指出属于哪个进程)却不能被利用的内存空间;或者说是由于被装入的数据块小于分区大小,从而导致分区内部有空间浪费,这种现象成为内部碎片。
以下Ext2中的索引节点为新特性而引入以下新的字段: 1. 块片(block fragmentation) 系统管理员对磁盘的访问通常选择较大的块,因此较大的块上存放小文件就会浪费很多磁盘空间。所以,如果几个文件存放在同一个块的不同片上可以解决上述问题。 2. 透明地处理压缩文件和加密文件 允许用户透明地存放压缩文件和加密文件,实现文件的保密性和对其他用户的透明性。 3. 逻辑删除 Undelete选项允许用户在必要时很容易回复以前已删除的文件内容。 4. 日志 日志避免文件系统在被突然卸载(例如作为系统崩溃的后果)时对其自动进行的耗时检查。
引导块 | 块组0 | 块组1 | …. | 块组n 引导块:任何Ext2分区中的第一个块从不受Ext2文件系统的管理,因为这一块是为分区的引导扇区所保留的。 块组: 1. 文件系统超级块拷贝 2. 块组描述符的拷贝 3.数据块位示图 4.索引节点位示图 5.索引节点表 6.数据块
超级块包含缓存空闲索引节点号的数组。Ext2超级块的关键字段如下: 1. s_inodes_count:索引节点的总数 2. s_blocks_count:以块为单位的文件系统的大小 3. s_free_blocks_count:空闲块计数器 4. s_free_inodes_count:空闲索引节点计数器 文件操作与超级块的联系 当一个文件被创建时,必须减少Ext2超级块中s_free_inodes_count字段的值和相应的组描述符中bg_free_inodes_count字段的值。 若内核给一个现有的文件追加一些数据,且使得该文件所分配的数据块数页增加时,那就必须修改Ext2超级块中s_free_blocks_count字段值和组描述符中的bg_free_blocks_count字段的值。 即使仅仅重写一个现有文件的部分内容,也要对Ext2超级块的s_wtime(最后一次写操作的时间)字段进行更新。
每个块组都有自己的组描述符(ext2_group_desc),当分配新索引节点和数据块时,会用到bg_free_blocks_count(组中空闲块个数)、bg_free_inodes_count(组中空闲索引节点个数)和bg_used_dirs_count(组中的目录个数)字段。 位示图是位的序列,其中值0表示对应的索引节点块或数据块是空闲的,1表示为占用。
概念:索引节点以静态形式存在于磁盘上,内核通过把它们读进内存索引节点表中来操纵对应的文件。与windows系统不同,unix系统采用文件名与文件描述信息分开存取的方法,文件描述信息单独形成一个称为索引节点的数据结构,类似windows系统中的文件分配表。每个索引节点为ext2_innode结构。 分类: 1. 磁盘索引节点 2. 内存索引节点 磁盘索引节点存储着文件处于未使用状态时的索引节点信息,内存索引节点记录着关于活跃文件的信息。因此内存索引节点不仅包含磁盘索引节点所拥有的所有字段,而且还增加了活跃文件的字段。
Ext2索引节点的长度必须是2的幂,以免造成存放索引节点表的块内碎片。实际上一个128字符的空间中充满了信息,然而256字符的索引节点会造成空间的浪费,而且使用不同索引节点长的Ext2文件系统之间还会造成兼容的问题。因此,引入索引节点的增强属性(extended attribute)来克服上述的问题。这些属性存放在索引节点之外的磁盘块,即是说索引节点的增强属性并没有存放在索引节点本身的数据结构中,因此,具有同样增强属性的索引节点可以共享存放着增强属性的磁盘块。 索引节点中设置i_file_acl字段来指向一个存放增强属性的块,具有同样增强属性的不同索引节点可以共享以个增强属性块。 增强属性结构:ext2_xattr_entry描述符、属性名name、属性值value。
用户可以通过访问控制列表来限定访问文件的用户(用户组)。
内核用文件系统和索引节点号来标志特定的索引节点,并在高层算法中请求分配内存索引节点。 算法iget:分配一个索引节点的内存拷贝,与高速缓冲中找到一个磁盘块的算法getblk()类似。 存取过程: 1. iget分配索引节点的内存拷贝(iget未找到可用的索引节点则报错) 2. 内核把设备号和索引号映射到散列队列上 3. 内核把待存取的磁盘索引节点读进内存 块号=((索引节点号-1) / 每块的索引节点数目) + 索引节点表的起始块号 块内偏移量=((索引节点号-1) mod (每块的索引节点数目)) * 磁盘索引节点大小 注意:内核独立地操纵索引节点锁和引用计数。当进程打开文件时,它就将索引节点的引用计数+1;当引用变得不活跃时,例如当进程关闭一个文件时,它就将索引节点引用计数-1。
释放索引节点时,内核将索引节点引用计数-1。如果引用计数值为0,且它的内存索引节点与磁盘索引节点内容不同,则内核还要往磁盘索引节点回写其中改变的内容。 文件数据改变、文件存取时间改变、文件所有者或存取许可权改变都会引起内存索引节点与磁盘索引节点的差异。
索引节点包含着文件数据在磁盘上的位置的明细表,由于磁盘上的每一块都是编了号的,明细表则是由磁盘块号的集合组成的。 为使索引节点保持较小的结构又能允许组织大文件,内核采用磁盘块地址表来描述索引节点与数据块的映射关系。磁盘块以文件物理结构中的索引分配结构组织(直接地址、一次间址、二次间址等)。 文件字节容量计算 1. 假设文件系统中的一个逻辑块大小大为1024B,并且假设一个块号为4B(32位)的整数编址,则每块可容纳2^10 / 2^2 = 2^8个块。 2. 假设一个文件有10个间接块,一个一次间址,一个二次间址,一个三次间址,则该文件最大字节容量为 10 * 1K = 10KB(直接块) 256 * 1K = 256KB(一次间址) 256 * 256 * 1K = 64MB(二次间址) 256 * 256 * 256 * 1K = 16GB(三次间址) 则这个文件的最大字节容量为 16GB+64MB+256KB+10KB
进程存取文件中的数据时使用了字节偏移量。文件表(File Table)保存着文件的字节偏移量(还有指向索引节点的指针)。内核把用户的字节流看法转换成块的看法–>文件作为从字节地址0开始直至整个文件大小的字节流,并且将每个字节流对应上逻辑块,文件是从第0个逻辑块开始,直至到相应于该文件大小的逻辑块号为止。 bmap算法:逻辑文件字节偏移量到文件系统块的块映射。
Ext2以一种特殊的文件实现了目录。这种特殊文件的数据块ext2_dir_entry_2把文件名和相应的索引节点号存放在一起。Ext2目录项中的字段如下: 1. inode:索引节点号 2. rec_len:目录项长度 3. name_len:文件名长度 4. file_type:文件类型 5. name:文件名 因为相率的原因,目录项的长度总是4的倍数,并在必要时用null字符(\0)来填充文件名的末尾。
内核在内部是使用索引节点而不是路径名工作,所以利用算法namei将路径名转换成索引节点号。 在unix系统中进程打开文件”/etc/passwd”的路径名转换步骤: 1. 内核分析文件名,遇到”/”,获得系统根对应索引节点。 2. 在把根作为工作索引节点之后,读入字符”etc”。 3. 权限验证:(1) 检查该”etc”是否为目录文件 (2) 检查进程是否具有必要的搜索许可权–》再对根目录中数据一块一块地存取,直至找到”etc”这一个目录表项的位置。 4. 找到这一登记项后,释放根索引节点(算法iput),并且根据刚刚找到的目录表项中的索引节点号,为”etc”分配索引节点(算法iget)。
工作索引节点:算法namei在分析路径名时使用称之为工作索引节点的中间索引节点。搜索从哪儿开始,哪儿就是第一个工作索引节点。
内核使用算法iget分配一个已知的索引节点,比如在算法namei中,内核通过把一个路径名分量与目录中的一个名字匹配来决定索引节点号。而这里阐述算法ialloc如何将一个磁盘索引节点分配给一个新建立的文件。 首先文件系统包含一个索引节点线性表,如果它的类型字段为0,则说明这个索引节点是空闲的。当一个进程需要一个新的索引节点时,从理论上说,内核能搜索索引节点表,以寻找一个空闲节点。然而这样的搜索代价太高了(至少对每个索引节点都需要一个读操作,而且可能是从磁盘读)。为改善性能,文件系统超级块包含一个数组,以便把文件系统中空闲的索引节点号缓存起来。 ialloc算法过程: 1. 内核首先验证无其他进程锁住了对超级块空闲索引节点表的存取。(1)若超级块中索引节点号表非空,则内核分配下一个索引节点号,使用算法iget为新分配的磁盘索引节点分配一个空闲的内存索引节点,并把磁盘索引节点读入到内存索引节点中,将索引节点的各字段初始化,并返回这一上了锁的索引节点。 (2)若超级块中索引节点号表为空,则内核搜索磁盘,并把尽可能多的空闲索引节点号放到超级块中。 内核一块接一块地读磁盘上的索引节点表,并且填入超级块索引节点号表中直至满额。同时记住它所找到的最高序号的索引节点表,称之为铭记索引节点。这是内核填入超级块中的最后一个索引节点,下次内核搜索磁盘上的空闲索引节点时,就从铭记索引节点开始搜索,这样可以避免重复搜索已不含空闲索引节点的磁盘块。
当进程往文件上写入数据时,内核必须从文件系统中分配磁盘块,超级块中包含一个用来把文件系统中的空闲磁盘块高速缓冲起来的数组。实用程序mkfs(文件系统生成)把一个文件系统中的数据块组织到一张链表中,表中的每个链是一个磁盘块,块中包含的是一个数组,数组的分量是空闲磁盘块号和链表上下一块的块号。 算法alloc从超级块获得空闲块。当分配的是超级块中最后的可以块时,内核把它作为指向包含一张空闲块表的指针看待,读取该块,将新的块号表项填充超级块数组,然后使用原来的块号。它为该快创建一个缓冲区,并清除缓冲区的数据,此时,磁盘块可以分配,并且内核有了一个缓冲区。 算法alloc: 1. 内核将一个可用的块分配出去,一旦分配出去,就不能对该块进行再分配,直到该块变为空闲为止。 2. 当所分配的是超级块高速缓冲中的最后一个空闲块时,内核把它作为指向包含一张空闲块表的块的指针。它读该块,把新的块号填充超级块数组,然后这最后一块继续使用原来的块号。这样该磁盘块就能被分配了。 3. 如果文件系统不包含空闲块了,则进程调用者将收到错误提示。