Linux内核读取磁盘序列号的问题

简介:

一向的观点就是“别在内核里面处理字符串”!事实上,确实应该如此!

Linux内核的块设备驱动有能力读取磁盘的序列号,这个数据存储在磁盘的控制芯片ROM里面。内核应该以怎样的形式将这个序列号呈现给调用者呢?我们ls一下这个目录:

/dev/disk/by-id

ll /dev/disk/by-id/
...

lrwxrwxrwx 1 root root 9 10月 17 10:11 scsi-SATA_ST3500413AS_Z2A2AGQA -> ../../sdb
可以看到,一个磁盘可以用传统的/dev/sdX来索引,也可以by-YY来索引,其中by-id就是以序列号来索引,上述输出中,下划线后面的就是序列号。同样,我们可以用hdparm工具程序来读取,可以读到同样的结果。在hdparm的代码实现中,我们可以看到如下的代码段:
static char *strip (char *s)
{
    char *e;

    while (*s == ' ') ++s;
    if (*s)
        for (e = s + strlen(s); *--e == ' '; *e = '\0');
    return s;
}

static void dump_identity (__u16 *idw)
{
    int i;
    char pmodes[64] = {0,}, dmodes[128]={0,}, umodes[128]={0,};
    char *model = strip(strndup((char *)&idw[27], 40));
    char *fwrev = strip(strndup((char *)&idw[23],  8));
    char *serno = strip(strndup((char *)&idw[10], 20));
    __u8 tPIO;

    printf("\n Model=%.40s, FwRev=%.8s, SerialNo=%.20s", model, fwrev, serno);
...
}
很明显,在显示序列号时,strip去掉了首尾的空格,因为空格显示出来是没有意义的。这十分正常。然而...
然而在2.6的老版本的内核比如2.6.8版本中,我们看到了do_identify中有下面的调用:
ide_fixstring(id->serial_no, sizeof(id->serial_no), bswap);
那么这个ide_fixstring是干什么的呢?它的实现如下,详细的注释已经给出了答案:
void ide_fixstring (u8 *s, const int bytecount, const int byteswap)
{
    u8 *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */

    if (byteswap) {
        /* convert from big-endian to host byte order */
        for (p = end ; p != s;) {
            unsigned short *pp = (unsigned short *) (p -= 2);
            *pp = ntohs(*pp);
        }
    }
    /* strip leading blanks */
    while (s != end && *s == ' ')
        ++s;
    /* compress internal blanks and strip trailing blanks */
    while (s != end && *s) {
        if (*s++ != ' ' || (s != end && *s && *s != ' '))
            *p++ = *(s-1);
    }
    /* wipe out trailing garbage */
    while (p != end)
        *p++ = '\0';
}
几乎是hdparm的strip更加严格意义上的翻版!这有什么问题呢?问题大了。这个内核没有办法给用户呈现一个原始的磁盘序列号,也就是序列号本身。为何不把处理留给应用程序呢?
Linux内核应该迅速返回最原始的二进制信息,将解析任务留给应用程序,不光是效率考虑,更多的是内核根本不知道如何去解读这些信息!幸运的是,高版本的内核不再处理磁盘序列号了,仅仅返回了原始信息,不幸的是,它带来了问题!
要不是工作中遇到了问题,我也不会闲到去折腾什么块设备驱动。系统仅仅升级了内核,然而升级前后都需要读取磁盘序列号和保存的序列号比对,老版本的内核和新版本内核对磁盘序列号读取行为的不同导致出现了不同的结果,内核也就不再对应用程序透明了!那怎么办?只好修改高版本内核驱动去迎合老版本的错误方式了!

兼容就是一大万人坑,埋葬了不知多少精英!



 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1325565

相关文章
|
16天前
|
Linux C语言
Linux内核队列queue.h
Linux内核队列queue.h
|
1月前
|
存储 Shell Linux
【Shell 命令集合 系统设置 】Linux 生成并更新内核模块的依赖 depmod命令 使用指南
【Shell 命令集合 系统设置 】Linux 生成并更新内核模块的依赖 depmod命令 使用指南
32 0
|
1月前
|
Shell Linux API
【Shell 命令集合 磁盘维护 】Linux 查找指定目录下的所有符号链接文件 symlinks 命令使用教程
【Shell 命令集合 磁盘维护 】Linux 查找指定目录下的所有符号链接文件 symlinks 命令使用教程
33 1
|
1月前
|
Shell Linux C语言
【Shell 命令集合 系统设置 】⭐Linux 卸载已加载的内核模块rmmod命令 使用指南
【Shell 命令集合 系统设置 】⭐Linux 卸载已加载的内核模块rmmod命令 使用指南
29 1
|
5天前
|
机器学习/深度学习 缓存 监控
linux查看CPU、内存、网络、磁盘IO命令
`Linux`系统中,使用`top`命令查看CPU状态,要查看CPU详细信息,可利用`cat /proc/cpuinfo`相关命令。`free`命令用于查看内存使用情况。网络相关命令包括`ifconfig`(查看网卡状态)、`ifdown/ifup`(禁用/启用网卡)、`netstat`(列出网络连接,如`-tuln`组合)以及`nslookup`、`ping`、`telnet`、`traceroute`等。磁盘IO方面,`iostat`(如`-k -p ALL`)显示磁盘IO统计,`iotop`(如`-o -d 1`)则用于查看磁盘IO瓶颈。
|
17天前
|
Linux
Linux操作系统调优相关工具(三)查看IO运行状态相关工具 查看哪个磁盘或分区最繁忙?
Linux操作系统调优相关工具(三)查看IO运行状态相关工具 查看哪个磁盘或分区最繁忙?
21 0
|
9天前
|
算法 Linux 调度
深入理解Linux内核的进程调度机制
【4月更文挑战第17天】在多任务操作系统中,进程调度是核心功能之一,它决定了处理机资源的分配。本文旨在剖析Linux操作系统内核的进程调度机制,详细讨论其调度策略、调度算法及实现原理,并探讨了其对系统性能的影响。通过分析CFS(完全公平调度器)和实时调度策略,揭示了Linux如何在保证响应速度与公平性之间取得平衡。文章还将评估最新的调度技术趋势,如容器化和云计算环境下的调度优化。
|
14天前
|
算法 Linux 调度
深度解析:Linux内核的进程调度机制
【4月更文挑战第12天】 在多任务操作系统如Linux中,进程调度机制是系统的核心组成部分之一,它决定了处理器资源如何分配给多个竞争的进程。本文深入探讨了Linux内核中的进程调度策略和相关算法,包括其设计哲学、实现原理及对系统性能的影响。通过分析进程调度器的工作原理,我们能够理解操作系统如何平衡效率、公平性和响应性,进而优化系统表现和用户体验。
20 3
|
21天前
|
负载均衡 算法 Linux
深度解析:Linux内核调度器的演变与优化策略
【4月更文挑战第5天】 在本文中,我们将深入探讨Linux操作系统的核心组成部分——内核调度器。文章将首先回顾Linux内核调度器的发展历程,从早期的简单轮转调度(Round Robin)到现代的完全公平调度器(Completely Fair Scheduler, CFS)。接着,分析当前CFS面临的挑战以及社区提出的各种优化方案,最后提出未来可能的发展趋势和研究方向。通过本文,读者将对Linux调度器的原理、实现及其优化有一个全面的认识。
|
21天前
|
Ubuntu Linux
Linux查看内核版本
在Linux系统中查看内核版本有多种方法:1) 使用`uname -r`命令直接显示版本号;2) 通过`cat /proc/version`查看内核详细信息;3) 利用`dmesg | grep Linux`显示内核版本行;4) 如果支持,使用`lsb_release -a`查看发行版及内核版本。
36 6