红联Linux门户
Linux帮助

硬盘分区的UUID

发布时间:2016-05-31 16:12:03来源:linux网站作者:smstong

Universally Unique IDentifier, 是一种获取全局唯一命名的标准。


1、UUID的来历

要为一个对象进行命名,并要求这个名字在时间和空间上都是唯一的,这在计算机领域是一个很重要的问题。目前已经存在很多成熟的解决方案,例如IP地址,MAC地址,DNS域名等。但这些方案都存在一个问题,那就是需要一个中央管理机构来批准和统一管理。这样就会带来两个问题:(1)需要一定费用;(2)数量受限。

为了解决这个问题,UUID诞生了。它采用128位长度来表示一个名字,且同时考虑了时间和空间的唯一性,最重要的是它不需要申请注册,任何人都可以使用本地计算机运行程序自动生成。

UUID最早出现在Apollo Network Computing System,后来被用到了OSF的DCE环境,然后被微软拿去使用,并改名GUID。相信大家都记得微软注册表里的奇怪长串数字吧,还有COM组件的名字,都是GUID。


2、硬盘分区命名现状
2.1、卷标名存在的问题

大多数文件系统的元数据部分都会记录硬盘分区的名字。对于如何命名这个分区,也有很多方法,如采用卷标。

硬盘分区的UUID

上面的“系统”,“软件”,“文档”就是分区的卷标名。几乎所有的文件系统类型都对卷标名进行支持。然而卷标名长度有限,并且重复的可能性比较大。可能很多人都给自己的系统分区命名为“系统”。

名字重复会导致一些问题,例如把当把一个硬盘HD1,转移到另外一台带有硬盘HD2的机器上时,如果HD1和HD2存在卷标名相同的分区,那么就会给依赖于卷标名的程序带来问题。


2.2、Linux对分区命名的问题

Linux系统对识别出的硬盘分区采用类似 /dev/sda1,/dev/sdb1这样的格式进行动态命名。假设机器装有两块串口硬盘,Linux会按照识别顺序对第一个识别出的硬盘命名为/dev/sda,对第二块识别出的硬盘命名为/dev/sdb。而问题是识别顺序是随机的,所以启动机器之前不能确定/dev/sda到底是哪块硬盘。

最常见的使用这种名称的地方就是/etc/fstab文件,它被用来设置自动挂载硬盘分区。下面是一个真实系统中的fstab文件中的一行:

/dev/sda1 /storeext4defaults0 0

如果系统有多块硬盘,那么下次启动的时候,/store就不能确定到底挂载了哪个硬盘的第一分区,如果这个挂载点对系统运行非常重要,那么就有可能出现问题。


2.3、GRUB对分区命名的问题

GRUB对分区命名与Linux类似,hd0表示发现的第一块硬盘,hd1表示第二块。存在的问题也与Linux相同。


2.4、UUID在文件系统中的使用

为解决上述问题,UUID被文件系统设计者采用,使其可以持久唯一标识一个硬盘分区。其实方式很简单,就是在文件系统的超级块中使用128位存放UUID。这个UUID是在使用文件系统格式化分区时计算生成的,例如Linux下的文件系统工具mkfs就在格式化分区的同时,生成UUID并把它记录到超级块的固定区域中。

下面是ext2文件系统超级块结构:

struct ext2_super_block
{ __u32   s_inodes_count;    /* 文件系统中索引节点总数 */
__u32   s_blocks_count;    /*文件系统中总块数 */
__u32   s_r_blocks_count;           /* 为超级用户保留的块数 */
__u32   s_free_blocks_count;   /*文件系统中空闲块总数 */
__u32   s_free_inodes_count;   /*文件系统中空闲索引节点总数*/
__u32   s_first_data_block;              /* 文件系统中第一个数据块 */
__u32   s_log_block_size;              /* 用于计算逻辑块大小 */
__s32   s_log_frag_size;              /* 用于计算片大小 */
__u32   s_blocks_per_group; /* 每组中块数 */
__u32   s_frags_per_group;              /* 每组中片数 */
__u32   s_inodes_per_group; /* 每组中索引节点数 */
__u32   s_mtime;                      /*最后一次安装操作的时间 */
__u32   s_wtime;             /*最后一次对该超级块进行写操作的时间 */
__u16   s_mnt_count;       /* 安装计数 */
__s16   s_max_mnt_count;                 /* 最大可安装计数 */
__u16   s_magic;                    /* 用于确定文件系统版本的标志 */
__u16   s_state;                      /* 文件系统的状态*/
__u16   s_errors;                     /* 当检测到有错误时如何处理 */
__u16   s_minor_rev_level;  /* 次版本号 */
__u32   s_lastcheck;       /* 最后一次检测文件系统状态的时间 */
__u32   s_checkinterval; /* 两次对文件系统状态进行检测的间隔时间 */
__u32   s_rev_level;       /* 版本号 */
__u16   s_def_resuid;      /* 保留块的默认用户标识号 */
__u16   s_def_resgid;      /* 保留块的默认用户组标识号*/
/*
* These fields are for EXT2_DYNAMIC_REV superblocks only.
*
* Note: the difference between the compatible feature set and
* the incompatible feature set is that if there is a bit set
* in the incompatible feature set that the kernel doesn't
* know about, it should refuse to mount the filesystem.
*
* e2fsck's requirements are more strict; if it doesn't know
* about a feature in either the compatible or incompatible
* feature set, it must abort and not try to meddle with
* things it doesn't understand...
*/
__u32   s_first_ino;            /* 第一个非保留的索引节点 */
__u16   s_inode_size;           /* 索引节点的大小 */
__u16   s_block_group_nr;       /* 该超级块的块组号 */
__u32   s_feature_compat;       /* 兼容特点的位图*/
__u32   s_feature_incompat;     /* 非兼容特点的位图 */
__u32   s_feature_ro_compat;    /* 只读兼容特点的位图*/
__u8    s_uuid[16];             /* 128位的文件系统标识号*/
char    s_volume_name[16];      /* 卷名 */
char    s_last_mounted[64];     /* 最后一个安装点的路径名 */
__u32   s_algorithm_usage_bitmap; /* 用于压缩*/
/*
* Performance hints.  Directory preallocation should only
* happen if the EXT2_COMPAT_PREALLOC flag is on.
*/
__u8    s_prealloc_blocks;      /* 预分配的块数*/
__u8    s_prealloc_dir_blocks;  /* 给目录预分配的块数 */
__u16   s_padding1;        
__u32   s_reserved[204];        /* 用null填充块的末尾 */
};

可以看到s_uuid[16]就是存放分区UUID的地方。

这样,无论硬盘分区的标识就永远不会重复,而且只要分区没有被重新格式化,那么标识此分区的UUID永远不变。

当然并不是所有的文件系统类型都支持UUID,例如微软的NTFS就不支持,而是采用了一个类似的其他机制。微软永远不走正路,真拿他没办法。


3、GRUB, Linux对硬盘分区UUID的支持
3.1、实例

目前最新版本的GRUB和Linux系统都对硬盘分区的UUID机制提供了良好的支持。
下面是CentOS6系统中/boot/grub/grub.conf配置文件的一部分:

title CentOS (2.6.32-504.el6.x86_64)
root (hd0,0)
kernel /boot/vmlinuz-2.6.32-504.el6.x86_64 ro root=UUID=ec2c1241-2c17-46ea-8cc6-a6a850df3e94 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=autoKEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /boot/initramfs-2.6.32-504.el6.x86_64.img

可以看出,GRUB本身仍采用(hd0,0)的传统方式寻找分区,而为其启动的linux提供了UUID的方式。

下面是CentOS7系统中/boot/grub2/grub.cfg配置文件一部分:

menuentry 'CentOS Linux, with Linux 3.10.0-123.el7.x86_64' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-123.el7.x86_64-advanced-b1e99de2-d388-4882-9b3a-5ced68992ee0' {
load_video
set gfxpayload=keep
insmod gzio
insmod part_msdos
insmod xfs
set root='hd0,msdos1'
if [ x$feature_platform_search_hint = xy ]; then
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'49224d20-43a6-44f2-8cf5-cfa11758a3a7
else
search --no-floppy --fs-uuid --set=root 49224d20-43a6-44f2-8cf5-cfa11758a3a7
fi
linux16 /vmlinuz-3.10.0-123.el7.x86_64 root=UUID=b1e99de2-d388-4882-9b3a-5ced68992ee0 ro rd.lvm.lv=centos/swap vconsole.font=latarcyrheb-sun16 rd.lvm.lv=centos/root crashkernel=autovconsole.keymap=us rhgb quiet LANG=en_US.UTF-8
initrd16 /initramfs-3.10.0-123.el7.x86_64.img

}

可见,GRUB和LINUX均采用了UUID来寻找硬盘分区。

下面是fstab的一部分:
UUID=49224d20-43a6-44f2-8cf5-cfa11758a3a7 /boot xfs defaults 1 2

显然也是采用了UUID来定位硬盘分区。


3.2、注意事项

重新格式化分区时,分区的UUID会变更
所以格式化分区后,需要修改对应的配置文件,更新其UUID。

NTFS文件系统不支持UUID
虽然NTFS不支持UUID,但是其支持一种较短的ID,也可以拿来凑合用。

既然UUID有这么多优势,毫无疑问只要系统支持,就要充分使用它。


4、UUID工具程序

如何查看硬盘分区的UUID

分区的UUID是mkfs工具自动写入的,我们可以使用blkid来查看之。

[root@db001 ~]# blkid
/dev/sda1: UUID="33141ba9-acd3-4021-9de3-bf7460f7c77c" TYPE="ext3"
/dev/sdc1: UUID="ec2c1241-2c17-46ea-8cc6-a6a850df3e94" TYPE="ext4"
/dev/sdc2: UUID="a1dc0e52-777e-450a-8fac-62d7966ff619" TYPE="swap"

生成UUID和分析UUID

为方便大家学习和理解UUID,uuid这个工具提供了很好的实践。它不仅可以用来生成UUID,而且可以对已有的UUID进行分析。

[root@db001 ~]# uuid
3f3418ce-0e79-11e5-b477-00e081de9b4a
[root@db001 ~]# blkid
/dev/sda1: UUID="33141ba9-acd3-4021-9de3-bf7460f7c77c" TYPE="ext3"
/dev/sdc1: UUID="ec2c1241-2c17-46ea-8cc6-a6a850df3e94" TYPE="ext4"
/dev/sdc2: UUID="a1dc0e52-777e-450a-8fac-62d7966ff619" TYPE="swap"
[root@db001 ~]# uuid -d 33141ba9-acd3-4021-9de3-bf7460f7c77c
encode: STR: 33141ba9-acd3-4021-9de3-bf7460f7c77c
SIV: 67895034790306977465223914142060496764
decode: variant: DCE 1.1, ISO/IEC 11578:1996
version: 4 (random data based)
content: 33:14:1B:A9:AC:D3:00:21:1D:E3:BF:74:60:F7:C7:7C
(no semantics: random data only)


本文永久更新地址:http://www.linuxdiyf.com/linux/21130.html