The usual view is "don't handle strings in the kernel"! Indeed, it should be so!
The Linux kernel's block device driver has the ability to read the disk's serial number, which is stored in the disk's control chip ROM. In what form should the kernel render this sequence number to the caller? We do ls this directory:
/dev/disk/by-id
Ll/dev/disk/by-id/. lrwxrwxrwx 1 Root 9 10:11 scsi-sata_st3500413as_z2a2agqa->, October. /.. /sdb can see, a disk can be indexed by traditional/DEV/SDX, can also by-yy to index, By-id is to be indexed by serial number, above output, underline is the serial number. Again, we can read with the Hdparm tool program, and we can read the same result. In the Hdparm code implementation, we can see the following code snippet:
Static Char *strip (char *s)
{
char *e;
while (*s = = ") ++s;
if (*s) for
(E = s + strlen (s); *--e = = "; *e = '");
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]);
Char *fwrev = Strip (Strndup ((char *) &idw[23], 8));
Char *serno = strip (Strndup (char *) &idw[10]);
__u8 Tpio;
printf ("\ n model=%.40s, fwrev=%.8s, serialno=%.20s", Model, Fwrev, Serno);
...
}
Obviously, when the serial number is displayed, the strip removes the trailing space, because it is meaningless to show the space. This is perfectly normal. However... However, in the 2.6 old version of the kernel such as the 2.6.8 version, we saw the following call in the Do_identify: ide_fixstring (id->serial_no, sizeof (ID->SERIAL_NO), Bswap) ; So what is this ide_fixstring for? It's implemented as follows, and detailed comments have been given the answer:
void Ide_fixstring (U8 *s, const int bytecount, const int byteswap)
{
U8 *p = s, *end = &s[bytecount & ~] ; /* ByteCount must be even *
/if (Byteswap) {/
* Convert from Big-endian to host byte order
(p = end; p != s;) {
unsigned short *pp = (unsigned short *) (P-= 2);
*PP = Ntohs (*PP);
}
}
/* Strip Leading blanks * *
(s!= end && *s = = ")
++s;
/* Compress internal blanks and strip trailing blanks *
(s!= end && *s) {
if (*s++!= ' | | (s!= end && *s && *s!= "))
*p++ = * (s-1);
}
/* Wipe out trailing garbage *
(P!= end)
*p++ = ';
Almost the hdparm of the strip more strictly in the sense of the replica! What's wrong with that? It's a big problem. This kernel has no way to present a user with an original disk serial number, which is the serial number itself. Why not leave the processing to the application?
The Linux kernel should quickly return to the original binary information, leaving the parsing task to the application, not just efficiency considerations, but the kernel simply does not know how to interpret the information! Fortunately, the high version of the kernel no longer processes the disk serial number, only returned the original information, unfortunately, it caused the problem! If I hadn't had a problem in my work, I wouldn't have been idle to toss up any piece of device drivers. The system only upgraded the kernel, however, before and after the upgrade will need to read the disk serial number and save the serial number, the old version of the kernel and the new version of the kernel of the disk serial number read behavior of different results, the kernel is no longer transparent to the application! Then what? Have to modify the high version of the kernel drive to meet the old version of the wrong way! Compatible is a big million people pit, buried unknown how many elite!
See more highlights of this column: http://www.bianceng.cnhttp://www.bianceng.cn/OS/Linux/