UFS文件系统的数据存储单元有“块”和“段”,每个块包含若干个段。大的文件先分配块进行存放,文件尾部不足一个块的数据就分配段来存放,所以UFS文件系统的位图既有块位图,又有段位图,用这两种位图描述文件系统的分配状态。
注意:UFS文件系统的块位图和段位图不同于其他文件系统的位图,它们是“空闲位图”。当某个块或段未分配时,该块或段对应的位图中的那一个位设置为“1”;而当某个块或段已被分配时,该块或段对应的位图中的那一个位设置为“0”。
每个柱面组都有一个段位图。段位图就位于其所在柱面组的组描述符中。柱面组描述符中的参数会说明段位图的起始地址,而段位图的大小可以通过柱面组中段的个数计算出来。
段位图是由一个个的二进制位组成的一组数据,每个位对应一个段。如果段没有使用,该段的段位图中对应的位就是数值“1”;当该段分配了数据,其段位图对应的位就写入数值“0”。为了定位一个段在其位图中对应的位,可以用当前段号减去其所在柱面组的起始段号,以获得这个段在其柱面组中的相对段号,然后用该相对段号去对应位图中的具体位。例如,一个段在其柱面组中的相对段号为36,则该段在其位图中对应的位就是36位,也就是位图中第4个字节的第4位。
下面看一个实例。在一个Free BSD系统的UFS1文件系统中,第一个柱面组的组描述符中描述了段位图相对于当前柱面组描述符起始位置的字节偏移为1240。用WinHex跳转到柱面组描述符的1240字节处,其部分内容如图5-43所示。
图5-43中的阴影部分都是段位图,起点在图5-43的64D8H偏移处。从64D8H偏移到655BH偏移的数据都是“0”,说明这些位图所对应的段都已经分配了数据。经过计算可以得到这些段号为0~1055。图5-43的655CH偏移处(图中画圈的字节)的值为“40H”,换算为二进制等于“01000000”,高7位为“1”,说明其对应的段未分配,经过简单计算就可得到该段的地址为1062号段。
每个柱面组还会有一个块位图。块位图也位于其所在柱面组的组描述符中。柱面组描述符中的参数会说明块位图的起始地址,而块位图的大小可以通过柱面组中块的个数计算出来。
块位图也是由一个个的二进制位组成的一组数据,但每个位对应一个块。如果块没有使用,该块的位图中对应的位就是数值“1”;当该块分配了数据,其位图对应的位就写入数值“0”。定位一个块的地址很简单,只需要用段号除以每块包含的段数就可以得到块号。
只有当一个块中的所有段在其段位图中对应的位都是“1”时,这个块在块位图中对应的位才被置“1”。
下面还是以图5-43所在的柱面组描述符为例进行说明。该柱面组描述符中描述了块位图相对于当前柱面组描述符起始位置的字节偏移为5396。用WinHex跳转到柱面组描述符的5396字节处,其部分内容如图5-44所示。
图5-44中的阴影部分都是块位图,起点在图5-44的7514H偏移处,从7514H偏移到7523H偏移这16个字节对应128个块。当前文件系统每块包含8个段,所以这16个字节实际上也对应1024个段,即0~1023段。这16个字节都为0值,说明这些位图所对应的块都已经分配了数据。这16个字节的块位图就对应着图5-43中段位图的64D8H偏移到6557H偏移的128个字节。
图5-44的7524H偏移处(图中画圈的字节)的值“00”对应8个块,这8个块所对应的段就是图5-43中段位图的6558H偏移到655FH偏移的8个字节描述的段。段位图的8个字节中有一个字节为“40H”,说明有一个段是空闲的,但只有当一个块中的所有段在其段位图中对应的位都是“1”时,这个块在块位图中对应的位才被置“1”,所以图5-44的7524H偏移处(图中画圈的字节)的值依然为“00”。