Linux磁盘与块设备名的对应问题

本文讨论了Linux下磁盘设备文件变化导致的启动顺序与设备号对应不符问题,并提供了采用UUID和标签方法来解决该问题的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



扩展文件系统的时候由于挂载了多个磁盘阵列,出现了启动顺序与设备号对应不上等问题,搜索后解决方法如下,通过方法1来实现的。

在Linux下往往会碰到这样的问题,磁盘的设备文件,比如/dev/sda, sdb, sdc等等在某些情况下会混乱掉,比如sda变成了sdb或者sdc变成了sdb等等,这样无形中会导致磁盘设备管理的混乱,最常见的比如Linux文件系统的启动问题。很多人在遇到这种问题的时候都去找磁盘、阵列厂家,怀疑是他们的问题,其实这种底层的磁盘(单个磁盘或者RAID阵列)和Linux下磁盘设备文件的映射并不是磁盘、阵列厂家来决定的,而是Linux内核自身的原因。

目前Linux内核对于这种磁盘设备的映射基本上取决于三个顺序,
1)、磁盘驱动程序的加载;
2)、是主机PCI插槽的监测;
3)、磁盘本身的监测,先来的当然是a,以此类推。所以,在出现热插拔了某些设备、重启等特殊情况下,实际磁盘在Linux下映射的设备文件可能由于这种“排队”的原因而发生改变,而这种底层“偷偷的”变化有时候会让管理员犯一些低级错误。

这是Linux Kernel的限制,所以目前还没办法来正面的克服应对,但有两个“迂回战术”的办法来减少可能出现的问题,一个是采用UUID设备唯一识别的方法,另一个是采用对设备卷做Label标识的办法。

一、UUID (globally unique identifier),唯一的身份识别,是采用SCSI Inquiry命令的Page 83信息来映射磁盘设备的。例如我们可以在Linux下查询一些磁盘设备的UUID标识代码。
bash# ls -la /dev/disk/by-id
total 0
drwxr-xr-x 2 root root 280 Mar 11 12:29 .
drwxr-xr-x 5 root root 100 Mar 11 12:28 ..
lrwxrwxrwx 1 root root 9 Mar 11 12:29 edd-int13_dev80 -> ../../sda
lrwxrwxrwx 1 root root 10 Mar 11 12:29 edd-int13_dev80-part1 -> ../../sda1
lrwxrwxrwx 1 root root 10 Mar 11 12:29 edd-int13_dev80-part3 -> ../../sda3
lrwxrwxrwx 1 root root 10 Mar 11 12:29 edd-int13_dev80-part4 -> ../../sda4
lrwxrwxrwx 1 root root 10 Mar 11 12:29 edd-int13_dev80-part5 -> ../../sda5
lrwxrwxrwx 1 root root 10 Mar 11 12:29 edd-int13_dev80-part6 -> ../../sda6
lrwxrwxrwx 1 root root 9 Mar 11 12:28 scsi-3600050e03d7c67007bf400009f890000 -
> ../../sda
lrwxrwxrwx 1 root root 10 Mar 11 12:28 scsi-3600050e03d7c67007bf400009f890000-p
art1 -> ../../sda1
lrwxrwxrwx 1 root root 10 Mar 11 12:28 scsi-3600050e03d7c67007bf400009f890000-p
art3 -> ../../sda3
lrwxrwxrwx 1 root root 10 Mar 11 12:28 scsi-3600050e03d7c67007bf400009f890000-p
art4 -> ../../sda4
lrwxrwxrwx 1 root root 10 Mar 11 12:28 scsi-3600050e03d7c67007bf400009f890000-p
art5 -> ../../sda5
lrwxrwxrwx 1 root root 10 Mar 11 12:28 scsi-3600050e03d7c67007bf400009f890000-p
art6 -> ../../sda6
找到了磁盘设备唯一的UUID代码后,就可以加到/etc/grub.conf和/etc/fstab中,这样即使初始的系统盘sda变成了sdb,但Linux和文件系统的启动加载都是按照UUID来的,所以上层也不会受到影响,例如,
在 /etc/grub.conf系统启动入口中做以下更改:
kernel /boot/vmlinuz-2.6.27.7 root=/dev/disk/by-id/scsi-3600050e03d7c67007bf400009f890000-part1

在 /etc/fstab文件系统启动入口中做以下更改:
/dev/disk/by-id/scsi-3600050e03d7c67007bf400009f890000-part1 / ext3 1 1
/dev/disk/by-id/scsi-234892819987c8f828473829becf38289-part2 /home ext3 1 1

二、 第二种算是比较老式的解决方法,即对磁盘卷设置Label标签,同样的道理,系统启动的时候只看标签,不看底层的sda/sdb等设备号,所以也不会影响到系统、文件系统的启动。例如,
使用e2label命令对sda1和sdb1设置标签:
/sbin/e2label /dev/sda1 myroot
/sbin/e2label /dev/sdb1 myhome

之后在 /etc/grub.conf 系统启动入口中做以下更改:
kernel /boot/vmlinuz-2.6.29 ro root=LABEL=myroot
在 /etc/fstab文件系统启动入口中做以下更改:
LABEL=myroot / ext3 defaults 1 1
LABEL=myhome /home ext3 defaults 1 1

备注:以上两种都是为了不影响系统和文件系统的启动采用的变通方法,在实际的系统管理时还是要密切注意底层设备的变化,否则如果出现了磁盘分区误删除的事情罪过可就大了。

转载自 linux磁盘设备文件(sda,sdb,sdc….)变化的的问题

<think>好的,我现在需要回答用户关于如何在Linux驱动中获取块设备字的问题。首先,我得回想一下Linux内核中块设备相关的知识。块设备通常对应硬盘、SSD等存储设备,驱动中可能需要获取它们的名称,比如sda、sdb这样的标识。 用户提到的是在驱动层面获取字,所以应该是在内核模块的代码中操作。我记得块设备Linux内核中由struct block_device结构体表示。这个结构体里应该包含设备的相关信息,但直接找字的话可能需要通过其他方式。 接下来,可能需要用到dev_t来获取设备号,然后通过设备号找到对应设备名称。或者,struct gendisk结构体可能存储了设备字,因为每个块设备都有一个gendisk结构。block_device结构里有一个指向gendisk的指针,可以通过bdev->bd_disk来访问。 然后,在gendisk结构体中,有一个字段叫disk_name,这应该就是设备字,比如“sda”。过需要确认内核版本的差异,因为同版本的内核结构可能会有变化。比如,在较新的内核中,可能需要使用disk_name()函数来安全地获取名称,而是直接访问结构体成员。 另外,还可以通过设备号调用dev_to_disk()或者通过其他函数如bdget_disk()来获取相关的结构体,进而提取名称。还有一种方法是使用sysfs路径,通过设备号生成sysfs路径,然后读取其中的某些文件来获取名称,但这种方法可能比较复杂,如直接访问结构体直接。 需要注意的是,在内核模块中直接访问结构体成员可能存在兼容性问题,特别是同内核版本之间结构体的定义可能变化。因此,最好使用内核提供的API函数来获取这些信息,比如使用disk_name()函数来安全地获取磁盘名称。 总结步骤可能是: 1. 在驱动代码中获取到struct block_device的指针。 2. 通过block_device的bd_disk成员获取对应的struct gendisk指针。 3. 使用gendisk的disk_name字段或者调用disk_name()函数来获取设备名称。 4. 注意内核版本的差异,确保代码的兼容性。 另外,可能需要包含相关的头文件,比如<linux/blkdev.h>。同时,在编写代码时,需要处理可能出现的空指针错误情况,确保模块的稳定性。 最后,用户可能需要一个代码示例,所以需要提供一个简单的例子,展示如何在内核模块中实现这一过程,并提醒用户注意内核版本代码的测试。</think>在Linux内核驱动中获取块设备名称主要涉及对块设备结构的操作。以下是分步说明: $$block_device \rightarrow gendisk \rightarrow disk\_name$$ 1. **获取block_device结构** ```c struct block_device *bdev = blkdev_get_by_path("/dev/sda", FMODE_READ, NULL); ``` 2. **访问关联的gendisk结构** ```c struct gendisk *disk = bdev->bd_disk; ``` 3. **提取设备名称** ```c const char *name = disk->disk_name; // 直接访问成员(注意内核版本差异) // 或 const char *name = dev_name(disk->parent); // 通过父设备获取 ``` **关键注意事项**: 1. 内核API变化:同版本内核中结构体成员名称可能同(例如5.10+内核推荐使用`disk_name()`函数) 2. 引用计数管理:使用`blkdev_put()`释放资源 3. 头文件依赖: ```c #include <linux/fs.h> #include <linux/blkdev.h> ``` **完整示例**: ```c static void print_block_name(const char *path) { struct block_device *bdev = blkdev_get_by_path(path, FMODE_READ, NULL); if (IS_ERR(bdev)) return; pr_info("Device name: %s\n", bdev->bd_disk->disk_name); blkdev_put(bdev, FMODE_READ); } ``` **替代方案**: 通过设备号逆向查找: ```c dev_t devt = MKDEV(8, 0); // 主设备号8,次设备号0 → /dev/sda struct gendisk *disk = get_gendisk(devt, &partno); if (disk) printk(KERN_INFO "Name: %s\n", disk->disk_name); ``` 建议优先使用内核提供的标准API,并参考当前内核版本的`Documentation/block`目录下的文档获取最新实现细节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值