一向的观点就是“别在内核里面处理字符串”!事实上,确实应该如此!
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内核应该迅速返回最原始的二进制信息,将解析任务留给应用程序,不光是效率考虑,更多的是内核根本不知道如何去解读这些信息!幸运的是,高版本的内核不再处理磁盘序列号了,仅仅返回了原始信息,不幸的是,它带来了问题!
要不是工作中遇到了问题,我也不会闲到去折腾什么块设备驱动。系统仅仅升级了内核,然而升级前后都需要读取磁盘序列号和保存的序列号比对,老版本的内核和新版本内核对磁盘序列号读取行为的不同导致出现了不同的结果,内核也就不再对应用程序透明了!那怎么办?只好修改高版本内核驱动去迎合老版本的错误方式了!
兼容就是一大万人坑,埋葬了不知多少精英!
分享到:
相关推荐
linux内核编译2.6.39linux内核编译2.6.39linux内核编译2.6.39linux内核编译2.6.39linux内核编译2.6.39linux内核编译2.6.39linux内核编译2.6.39linux内核编译2.6.39linux内核编译2.6.39linux内核编译2.6.39linux内核...
鉴于此,《Linux内核精髓:精通Linux内核必会的75个绝技》选取了资源管理(CPU、内存、进程等)、文件系统、网络、虚拟化、省电、调试、概要分析、追踪、内核调整等Linux内核的核心主题进行了深入剖析和讲解,总结出...
理解Linux内核最好预备的知识点:懂C语言懂一点操作系统的知识熟悉少量相关算法懂计算机体系结构Linux内核的特点:结合了unix操作系统的一些基础概念Linux内核的任务:1.从技术层面讲,内核是硬件与软
linux内核源代码深度解析linux内核源代码深度解析linux内核源代码深度解析linux内核源代码深度解析linux内核源代码深度解析linux内核源代码深度解析linux内核源代码深度解析linux内核源代码深度解析linux内核源代码...
深入理解Linux内核 + Linux内核设计与实现,绝对完整,我最近也在学,建议先学Linux内核设计与实现,对Linux内核有一个大体的认识,在看深入理解Linux内核,要舍得花时间。
linux内核设计说明,Linux内核设计与实现(第三版中文高清带目录)
LINUX内核经典面试题 ,20) 如何加载、卸载一个模块? 21) 模块和应用程序分别运行在什么空间? 22) Linux中的浮点运算由应用程序实现还是内核实现? 23) 模块程序能否使用可链接的库函数? 24) TLB中缓存的是什么...
Linux内核分析及常见问题解答
linux内核源代码情景分析,对于深入学习者有很大帮助
ARM Linux内核源码剖析.pdfARM Linux内核源码剖析.pdfARM Linux内核源码剖析.pdfARM Linux内核源码剖析.pdf 完整书签
Linux内核HWMP序列号机制的研究与改进.pdf
linux内核管理linux内核管理linux内核管理linux内核管理linux内核管理
linux内核图解linux内核图解linux内核图解linux内核图解linux内核图解
Linux内核中磁盘配额的实现及其应用研究.pdf
如何编译你自己的linux内核.txt如何编译你自己的linux内核.txt如何编译你自己的linux内核.txt如何编译你自己的linux内核.txt如何编译你自己的linux内核.txt如何编译你自己的linux内核.txt如何编译你自己的linux内核....
Linux内核完全注释V3.0,很详细很不错,希望喜欢
linux内核解释 linux内核解释 详解
深入Linux内核.pdf
Linux早期内核代码的入门书籍,配合内核代码更好的入门Linux内核,比起Linux2.6之后版本来说,可以更好的理解Linux内核框架
Linux内核的分析,通过本书学习可以了解到Linux的内核机制。