Linux块设备UUID探究

服务器

浏览数:93

2020-6-8

在使用mount命令和配置fstab时,可以通过LABELUUID来挂载。从过往经验来看,只有GPT分区才有UUID,那MBR分区的UUID是保存在哪里呢?是在分区表,保留扇区,还是在文件系统中?是如何处理的?为了解决心中的疑惑,进行如下分析。

测试UUID与文件系统的关系

  • 查看当前系统中块设备的UUID,没有文件系统时没有UUID
$ lsblk -f
NAME   FSTYPE LABEL UUID                                 MOUNTPOINT
sda                                                      
├─sda1 xfs          b2f2dcbb-03c4-472f-b79c-942895cec1a9 /
├─sda2 swap         2305f62c-86dd-4f32-9f32-c736957996c4 [SWAP]
└─sda3                                                   
sr0

$ blkid
/dev/sda1: UUID="b2f2dcbb-03c4-472f-b79c-942895cec1a9" TYPE="xfs" 
/dev/sda2: UUID="2305f62c-86dd-4f32-9f32-c736957996c4" TYPE="swap"
  • 格式化成vfat文件系统后,查看其UUID,发现只有8位:
$ mkfs.vfat /dev/sda3
mkfs.fat 3.0.20 (12 Jun 2013)

$ lsblk -f
NAME   FSTYPE LABEL UUID                                 MOUNTPOINT
sda                                                      
├─sda1 xfs          b2f2dcbb-03c4-472f-b79c-942895cec1a9 /
├─sda2 swap         2305f62c-86dd-4f32-9f32-c736957996c4 [SWAP]
└─sda3 vfat         72DD-DA7A                            
sr0
  • 格式化成xfs文件系统,查看其UUID,是正常的32位:
$ mkfs.xfs -f /dev/sda3
meta-data=/dev/sda3              isize=512    agcount=4, agsize=1310720 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=5242880, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

$ lsblk -f             
NAME   FSTYPE LABEL UUID                                 MOUNTPOINT
sda                                                      
├─sda1 xfs          b2f2dcbb-03c4-472f-b79c-942895cec1a9 /
├─sda2 swap         2305f62c-86dd-4f32-9f32-c736957996c4 [SWAP]
└─sda3 xfs          cda5c46b-2a4b-47f5-99dd-2083cc5433b4 
sr0
  • 再一次格式化成xfs文件系统,发现UUID发生了变化:
$ mkfs.xfs -f /dev/sda3
meta-data=/dev/sda3              isize=512    agcount=4, agsize=1310720 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=5242880, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

$ lsblk -f             
NAME   FSTYPE LABEL UUID                                 MOUNTPOINT
sda                                                      
├─sda1 xfs          b2f2dcbb-03c4-472f-b79c-942895cec1a9 /
├─sda2 swap         2305f62c-86dd-4f32-9f32-c736957996c4 [SWAP]
└─sda3 xfs          2c0872d1-9646-440f-ae6e-c32c49f35ff2 
sr0

可以看到没有格式化的块设备没有UUID,同时UUID与文件系统类型有关。每格式化一次文件系统,UUID都会发生变化,初步可以推测UUID是存放在文件系统中。

谁创建了磁盘的UUID文件

/dev/disk/by-uuid目录下,会根据磁盘的UUID建立很多块设备文件的符号链接?这是谁干的呢?根据常识,CentOS 7应该是使用的Systemd提供的UDev实现的,不过我们还是来细致分析一下。

  • 开启系统中的审计功能:
$ auditctl -D
$ auditctl -l
No rules

$ auditctl -w /dev/disk/by-uuid -p war

$ auditctl -l
-w /dev/disk/by-uuid -p rwa
  • 再次格式化一个块设备:
$ mkfs.xfs -f /dev/sda3
meta-data=/dev/sda3              isize=512    agcount=4, agsize=1310720 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=5242880, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none

$ lsblk -f
NAME   FSTYPE LABEL UUID                                 MOUNTPOINT
sda                                                      
├─sda1 xfs          b2f2dcbb-03c4-472f-b79c-942895cec1a9 /
├─sda2 swap         2305f62c-86dd-4f32-9f32-c736957996c4 [SWAP]
└─sda3 xfs          8b980779-48e3-4012-b0d0-e08a939965ec 
sr0
  • 查看审计日志,可以看到的确是UDev干的好事:
$ ausearch -f /dev/disk/by-uuid
...

----
time->Thu Aug 16 15:44:42 2018
type=PROCTITLE msg=audit(1534405482.539:3076): proctitle="/usr/lib/systemd/systemd-udevd"
type=PATH msg=audit(1534405482.539:3076): item=2 name="/dev/disk/by-uuid/8b980779-48e3-4012-b0d0-e08a939965ec" inode=5240274 dev=00:05 mode=0120777 ouid=0 ogid=0 rdev=00:00 objtype=CREATE
type=PATH msg=audit(1534405482.539:3076): item=1 name="/dev/disk/by-uuid/" inode=10434 dev=00:05 mode=040755 ouid=0 ogid=0 rdev=00:00 objtype=PARENT
type=PATH msg=audit(1534405482.539:3076): item=0 name="../../sda3" objtype=UNKNOWN
type=CWD msg=audit(1534405482.539:3076):  cwd="/"
type=SYSCALL msg=audit(1534405482.539:3076): arch=c000003e syscall=88 success=yes exit=0 a0=7ffd033e8070 a1=563cfdee2140 a2=0 a3=ffffffff items=3 ppid=412 pid=1207 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="systemd-udevd" exe="/usr/lib/systemd/systemd-udevd" key=(null)

...
  • 查看一下UDev的存储设备规则,可以看到块设备文件的UUID是根据UDev$env{ID_FS_UUID_ENC}环境变量而来:
$ cat /usr/lib/udev/rules.d/60-persistent-storage.rules
...

# by-label/by-uuid links (filesystem metadata)
ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}"
ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}"

# by-id (World Wide Name)
ENV{DEVTYPE}=="disk", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}"
ENV{DEVTYPE}=="partition", ENV{ID_WWN_WITH_EXTENSION}=="?*", SYMLINK+="disk/by-id/wwn-$env{ID_WWN_WITH_EXTENSION}-part%n"

# by-partlabel/by-partuuid links (partition metadata)
ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_ENTRY_UUID}=="?*", SYMLINK+="disk/by-partuuid/$env{ID_PART_ENTRY_UUID}"
ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_ENTRY_NAME}=="?*", SYMLINK+="disk/by-partlabel/$env{ID_PART_ENTRY_NAME}"

# add symlink to GPT root disk
ENV{ID_PART_ENTRY_SCHEME}=="gpt", ENV{ID_PART_GPT_AUTO_ROOT}=="1", SYMLINK+="gpt-auto-root"

...

UDev是如何获取磁盘的UUID的

  • 查看一下块设备的UDev环境变量:
$ udevadm info -n /dev/sda3
P: /devices/pci0000:00/0000:00:10.0/host0/target0:0:0/0:0:0:0/block/sda/sda3
N: sda3
S: disk/by-path/pci-0000:00:10.0-scsi-0:0:0:0-part3
S: disk/by-uuid/8b980779-48e3-4012-b0d0-e08a939965ec
E: DEVLINKS=/dev/disk/by-path/pci-0000:00:10.0-scsi-0:0:0:0-part3 /dev/disk/by-uuid/8b980779-48e3-4012-b0d0-e08a939965ec
E: DEVNAME=/dev/sda3
E: DEVPATH=/devices/pci0000:00/0000:00:10.0/host0/target0:0:0/0:0:0:0/block/sda/sda3
E: DEVTYPE=partition
E: ID_BUS=scsi
E: ID_FS_TYPE=xfs
E: ID_FS_USAGE=filesystem
E: ID_FS_UUID=8b980779-48e3-4012-b0d0-e08a939965ec
E: ID_FS_UUID_ENC=8b980779-48e3-4012-b0d0-e08a939965ec
E: ID_MODEL=VMware_Virtual_S
E: ID_MODEL_ENC=VMware\x20Virtual\x20S
E: ID_PART_ENTRY_DISK=8:0
E: ID_PART_ENTRY_NUMBER=3
E: ID_PART_ENTRY_OFFSET=117440512
E: ID_PART_ENTRY_SCHEME=dos
E: ID_PART_ENTRY_SIZE=41943040
E: ID_PART_ENTRY_TYPE=0x83
E: ID_PART_TABLE_TYPE=dos
E: ID_PATH=pci-0000:00:10.0-scsi-0:0:0:0
E: ID_PATH_TAG=pci-0000_00_10_0-scsi-0_0_0_0
E: ID_REVISION=1.0
E: ID_SCSI=1
E: ID_TYPE=disk
E: ID_VENDOR=VMware_
E: ID_VENDOR_ENC=VMware\x2c\x20
E: MAJOR=8
E: MINOR=3
E: SUBSYSTEM=block
E: TAGS=:systemd:
E: USEC_INITIALIZED=376987010725
  • 查看在执行格式化时的UEvent事件,的确和前面看到的是匹配的:
$ mkfs.xfs -f /dev/sda3
meta-data=/dev/sda3              isize=512    agcount=4, agsize=1310720 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=0, sparse=0
data     =                       bsize=4096   blocks=5242880, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0


$ lsblk -f                                                                        
NAME   FSTYPE LABEL UUID                                 MOUNTPOINT
sda                                                      
├─sda1 xfs          b2f2dcbb-03c4-472f-b79c-942895cec1a9 /
├─sda2 swap         2305f62c-86dd-4f32-9f32-c736957996c4 [SWAP]
└─sda3 xfs          be01f436-56ea-4198-8ed1-9646b2860fc5 
sr0


$ udevadm monitor -kup 
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[394211.609898] change   /devices/pci0000:00/0000:00:10.0/host0/target0:0:0/0:0:0:0/block/sda/sda3 (block)
ACTION=change
DEVNAME=/dev/sda3
DEVPATH=/devices/pci0000:00/0000:00:10.0/host0/target0:0:0/0:0:0:0/block/sda/sda3
DEVTYPE=partition
MAJOR=8
MINOR=3
SEQNUM=4892
SUBSYSTEM=block

UDEV  [394211.622459] change   /devices/pci0000:00/0000:00:10.0/host0/target0:0:0/0:0:0:0/block/sda/sda3 (block)
ACTION=change
DEVLINKS=/dev/disk/by-path/pci-0000:00:10.0-scsi-0:0:0:0-part3 /dev/disk/by-uuid/be01f436-56ea-4198-8ed1-9646b2860fc5
DEVNAME=/dev/sda3
DEVPATH=/devices/pci0000:00/0000:00:10.0/host0/target0:0:0/0:0:0:0/block/sda/sda3
DEVTYPE=partition
ID_BUS=scsi
ID_FS_TYPE=xfs
ID_FS_USAGE=filesystem
ID_FS_UUID=be01f436-56ea-4198-8ed1-9646b2860fc5
ID_FS_UUID_ENC=be01f436-56ea-4198-8ed1-9646b2860fc5
ID_MODEL=VMware_Virtual_S
ID_MODEL_ENC=VMware\x20Virtual\x20S
ID_PART_ENTRY_DISK=8:0
ID_PART_ENTRY_NUMBER=3
ID_PART_ENTRY_OFFSET=117440512
ID_PART_ENTRY_SCHEME=dos
ID_PART_ENTRY_SIZE=41943040
ID_PART_ENTRY_TYPE=0x83
ID_PART_TABLE_TYPE=dos
ID_PATH=pci-0000:00:10.0-scsi-0:0:0:0
ID_PATH_TAG=pci-0000_00_10_0-scsi-0_0_0_0
ID_REVISION=1.0
ID_SCSI=1
ID_TYPE=disk
ID_VENDOR=VMware_
ID_VENDOR_ENC=VMware\x2c\x20
MAJOR=8
MINOR=3
SEQNUM=4892
SUBSYSTEM=block
TAGS=:systemd:
USEC_INITIALIZED=6987010725
  • 再看看UDev的源码,可以看到ID_FS_UUID_ENC环境变量是根据块设备UEvent事件中的UUID变量值获得的:
$ cat src/udev/udev-builtin-blkid.c
...

static void print_property(struct udev_device *dev, bool test, const char *name, const char *value) {
        char s[256];

        s[0] = '\0';

        if (streq(name, "TYPE")) {
                udev_builtin_add_property(dev, test, "ID_FS_TYPE", value);

        } else if (streq(name, "USAGE")) {
                udev_builtin_add_property(dev, test, "ID_FS_USAGE", value);

        } else if (streq(name, "VERSION")) {
                udev_builtin_add_property(dev, test, "ID_FS_VERSION", value);

        } else if (streq(name, "UUID")) {
                blkid_safe_string(value, s, sizeof(s));
                udev_builtin_add_property(dev, test, "ID_FS_UUID", s);
                blkid_encode_string(value, s, sizeof(s));
                udev_builtin_add_property(dev, test, "ID_FS_UUID_ENC", s);

        } else if (streq(name, "UUID_SUB")) {
                blkid_safe_string(value, s, sizeof(s));
                udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB", s);
                blkid_encode_string(value, s, sizeof(s));
                udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB_ENC", s);

        } else if (streq(name, "LABEL")) {
                blkid_safe_string(value, s, sizeof(s));
                udev_builtin_add_property(dev, test, "ID_FS_LABEL", s);
                blkid_encode_string(value, s, sizeof(s));
                udev_builtin_add_property(dev, test, "ID_FS_LABEL_ENC", s);


...
}

...

EXT文件系统中的UUID

EXT系列的EXT2EXT3EXT4的超级块等主要格式差不多,在这里不做区分。

  • 把块设备格式化成ext3文件系统:
$ mkfs.ext3 /dev/sda3 
mke2fs 1.42.9 (28-Dec-2013)
文件系统标签=
OS type: Linux
块大小=4096 (log=2)
分块大小=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
1310720 inodes, 5242880 blocks
262144 blocks (5.00%) reserved for the super user
第一个数据块=0
Maximum filesystem blocks=4294967296
160 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
	4096000

Allocating group tables: 完成                            
正在写入inode表: 完成                            
Creating journal (32768 blocks): 完成
Writing superblocks and filesystem accounting information: 完成


$ lsblk -f           
NAME   FSTYPE LABEL UUID                                 MOUNTPOINT
sda                                                      
├─sda1 xfs          b2f2dcbb-03c4-472f-b79c-942895cec1a9 /
├─sda2 swap         2305f62c-86dd-4f32-9f32-c736957996c4 [SWAP]
└─sda3 ext3         00dfb75c-f5e9-4907-8a4c-34858f2d98db 
sr0                                                    
  • 看一下块设备的ext3文件系统信息,其中有Filesystem UUID一项和块设备的UUID一致:
$ dumpe2fs /dev/sda3
dumpe2fs 1.42.9 (28-Dec-2013)
Filesystem volume name:   <none>
Last mounted on:          <not available>
Filesystem UUID:          00dfb75c-f5e9-4907-8a4c-34858f2d98db
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype sparse_super large_file
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              1310720
Block count:              5242880
Reserved block count:     262144
Free blocks:              5116558
Free inodes:              1310709
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      1022
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8192
Inode blocks per group:   512
Filesystem created:       Thu Aug 16 16:35:55 2018
Last mount time:          n/a
Last write time:          Thu Aug 16 16:35:57 2018
Mount count:              0
Maximum mount count:      -1
Last checked:             Thu Aug 16 16:35:55 2018
Check interval:           0 (<none>)
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:	          256
Required extra isize:     28
Desired extra isize:      28
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      0d887782-32e2-454b-b6b5-54260a188439
Journal backup:           inode blocks
Journal features:         (none)
日志大小:             128M
Journal length:           32768
Journal sequence:         0x00000001
Journal start:            0
  • 在内核ext2文件系统源码的超级块定义中可以看到s_uuid这个成员(其实还有个label成员),就是保存UUID的位置,有16字节,刚好3216进制数:
$ vi fs/ext2/ext2.h
...

/*
 * Structure of the super block
 */
struct ext2_super_block {
	__le32	s_inodes_count;		/* Inodes count */
	__le32	s_blocks_count;		/* Blocks count */
	__le32	s_r_blocks_count;	/* Reserved blocks count */

...
    
	__u8	s_uuid[16];		/* 128-bit uuid for volume */

...
};

...

FAT文件系统中的UUID

  • 再看看FAT文件系统的数据,这个UUID首次出现在第67字节的位置:
$ lsblk -f
NAME   FSTYPE LABEL UUID                                 MOUNTPOINT
sda                                                      
├─sda1 xfs          b2f2dcbb-03c4-472f-b79c-942895cec1a9 /
├─sda2 swap         2305f62c-86dd-4f32-9f32-c736957996c4 [SWAP]
└─sda3 vfat         2E9C-E424                            
sr0

$ hexdump -C /dev/sda3 -n 5120 | grep -i "24 E4 9C 2e"
00000040  00 00 29 24 e4 9c 2e 4e  4f 20 4e 41 4d 45 20 20  |..)$...NO NAME  |
00000c40  00 00 29 24 e4 9c 2e 4e  4f 20 4e 41 4d 45 20 20  |..)$...NO NAME  |
  • 查看mkdosfs工具中fat32文件系统的结构定义,可以发现,如果使用的是fat32,则正好是使用偏移为67字节处的volume_id,而且只有4字节,顶多存放8位的UUID
$ vi dosfstools-3.0.20/src/mkfs.fat.c

/* __attribute__ ((packed)) is used on all structures to make gcc ignore any
 * alignments */

struct msdos_volume_info {
    __u8 drive_number;		/* BIOS drive number */
    __u8 RESERVED;		/* Unused */
    __u8 ext_boot_sign;		/* 0x29 if fields below exist (DOS 3.3+) */
    __u8 volume_id[4];		/* Volume ID number */
    __u8 volume_label[11];	/* Volume label */
    __u8 fs_type[8];		/* Typically FAT12 or FAT16 */
} __attribute__ ((packed));

struct msdos_boot_sector {
    __u8 boot_jump[3];		/* Boot strap short or near jump */
    __u8 system_id[8];		/* Name - can be used to special case
				   partition manager volumes */
    __u8 sector_size[2];	/* bytes per logical sector */
    __u8 cluster_size;		/* sectors/cluster */
    __u16 reserved;		/* reserved sectors */
    __u8 fats;			/* number of FATs */
    __u8 dir_entries[2];	/* root directory entries */
    __u8 sectors[2];		/* number of sectors */
    __u8 media;			/* media code (unused) */
    __u16 fat_length;		/* sectors/FAT */
    __u16 secs_track;		/* sectors per track */
    __u16 heads;		/* number of heads */
    __u32 hidden;		/* hidden sectors (unused) */
    __u32 total_sect;		/* number of sectors (if sectors == 0) */
    union {
	struct {
	    struct msdos_volume_info vi;
	    __u8 boot_code[BOOTCODE_SIZE];
	} __attribute__ ((packed)) _oldfat;
	struct {
	    __u32 fat32_length;	/* sectors/FAT */
	    __u16 flags;	/* bit 8: fat mirroring, low 4: active fat */
	    __u8 version[2];	/* major, minor filesystem version */
	    __u32 root_cluster;	/* first cluster in root directory */
	    __u16 info_sector;	/* filesystem info sector */
	    __u16 backup_boot;	/* backup boot sector */
	    __u16 reserved2[6];	/* Unused */
	    struct msdos_volume_info vi;
	    __u8 boot_code[BOOTCODE_FAT32_SIZE];
	} __attribute__ ((packed)) _fat32;
    } __attribute__ ((packed)) fstype;
    __u16 boot_sign;
} __attribute__ ((packed));


int main(int argc, char **argv)
{
...
    
    volume_id = (u_int32_t) ((create_timeval.tv_sec << 20) | create_timeval.tv_usec);	/* Default volume ID = creation time, fudged for more uniqueness */
    
...
	case 'i':		/* i : specify volume ID */
	    volume_id = strtoul(optarg, &tmp, 16);
	    if (*tmp) {
		printf("Volume ID must be a hexadecimal number\n");
		usage();
	    }
	    break;

...
}

...

/* Create the filesystem data tables */

static void setup_tables(void)
{
    unsigned num_sectors;
    unsigned cluster_count = 0, fat_length;
    struct tm *ctime;
    struct msdos_volume_info *vi =
	(size_fat == 32 ? &bs.fat32.vi : &bs.oldfat.vi);

    if (atari_format) {
	/* On Atari, the first few bytes of the boot sector are assigned
	 * differently: The jump code is only 2 bytes (and m68k machine code
	 * :-), then 6 bytes filler (ignored), then 3 byte serial number. */
	bs.boot_jump[2] = 'm';
	memcpy((char *)bs.system_id, "kdosf", strlen("kdosf"));
    } else
	memcpy((char *)bs.system_id, "mkfs.fat", strlen("mkfs.fat"));
    if (sectors_per_cluster)
	bs.cluster_size = (char)sectors_per_cluster;
    if (size_fat == 32) {
	/* Under FAT32, the root dir is in a cluster chain, and this is
	 * signalled by bs.dir_entries being 0. */
	root_dir_entries = 0;
    }

    if (atari_format) {
	bs.system_id[5] = (unsigned char)(volume_id & 0x000000ff);
	bs.system_id[6] = (unsigned char)((volume_id & 0x0000ff00) >> 8);
	bs.system_id[7] = (unsigned char)((volume_id & 0x00ff0000) >> 16);
    } else {
	vi->volume_id[0] = (unsigned char)(volume_id & 0x000000ff);
	vi->volume_id[1] = (unsigned char)((volume_id & 0x0000ff00) >> 8);
	vi->volume_id[2] = (unsigned char)((volume_id & 0x00ff0000) >> 16);
	vi->volume_id[3] = (unsigned char)(volume_id >> 24);
    }

...
}

...

总结

  • Linux根据不同类型的文件系统,把UUID或者卷ID(还有LABEL)保存在文件系统的超级块中;
  • 在为磁盘创建文件系统时,通过UDev消息传递给用户态的UDev守护进程;
  • 用户态的UDev守护进程根据其中的UUID消息生成ID_FS_UUID_ENC或者ID_FS_UUID_ENC变量;
  • 用户态的UDev守护进程根据相应的规则生成/dev/disk/目录下的设备文件符号链接。

作者:LastRitter