snifer

[原创]Blakfin中uclinux的移植有关的问题,有你不知道的秘密之二

0
阅读(2906)

上一节给大家讲了个秘密,很多朋友比较喜欢,我就趁热打铁,再讲一个,呵呵。。。。。。

在Blakfin中uclinux操作系统的移植时,除了数据类型定义问题之外,如果想让你编写的驱动程序能在不同的平台间移植的话,还必须注意到其它一些软件上的问题:

时间间隔

在处理时间间隔时,不能假定每秒一定有100个jiffy。虽然对当前的Linux-x86而言这是对的,但并不是所有Linux平台都是以100HZ运行。如果你改变了HZ的数值,那么即使对x86,这种假设也是错误的,何况没人知道未来的内核会发生些什么变化。使用jiffy计算时间间隔的时候,应该把时间转换成以HZ为单位。例如,为了检测半秒钟的超时,可以把消逝的时间和HZ/2作比较。更常见的,与msec毫秒对应的jiffy的数目总是msec*HZ/1000。许多的网络驱动程序在移植到Alpha上时都必须修正该细节;有些开始是为PC设计的驱动程序给超时明确定义了一个jiffy值,但是Alpha却有着不同的HZ数值。

 页大小

使用内存时,要记住内存页的大小为PAGE_SIZE字节,而不是4KB。假设页大小就是4KB并硬编码该数值是PC程序员常犯的错误-Alpha页大小是这的两倍。相关的宏有PAGE_SIZEPAGE_SHIFT。后者包含要得到一个地址所在页的页号时需要对该地址右移的位数。对当前的4KB和8KB的页,这个数值通常是12或者13。这些宏在头文件<asm/page.h>中定义。

      让我们来看一种简单的情况。如果驱动程序需要16KB空间来存放临时数据,它不应当指定get_free_pages函数的参数order(“2”的幂)。需要一种可移植的解决办法。此时,可以使用条件编译#ifdef __alpha__,但这只适用于已知的平台,而如果要支持别的平台,它就不能奏效了。我建议使用下面的代码:

               buf = get_free_pages(GFP_KERNEL,14 - PAGE_SHIFT,0 /*dma*/);

        或者,更好一些的代码:

               int order = (14 - PAGE_SHIFT >0) ? 14 - PAGE_SHIFT : 0;

              buf = get_free_pages(GFP_KERNEL,order,0 /*dma*/);

 两种解决办法都利用了16KB等于1<<14这一常识。两个数的商就是它们对数的差(的幂),而14PAGE_SHIFT都是幂。第二种解决办法就更好,因为它可以防止把一个负的order值传递给get_free_pages函数;order值时在编译时就计算好的,没有运行时的额外开销,而且,上面给出的实现方法是不依赖于PAGE_SIZE来分配任何2的幂次大小的内存空间的安全方法。

 字节序

要小心的是不要主观假设字节序。虽然PC是按低字节优先的方式存储多个字节(“小印地安,little endian”),但是大多数更高级的平台是以另一种方式工作的(“大印地安,big endian”)。虽然好的程序不会依赖于字节序,但有时驱动程序需要创建占一个字节以上的整数,或者相反(一个字节以下)。此时,代码中就应该将头文件<asm/byteorder.h>包含进来,并且检测头文件中是否定义了__BIG_ENDIAN__LITTLE_ENDIAN。起始的下划线在ucLinux-1.2之后版本的头文件中却去掉了,在头文件<asm/byteorder.h>后再包含scull示例程序中的头文件sysdep.h就可以修正这个不兼容。

 

当字节序相关问题与网络传输有联系的时候,就应当使用下面各种函数来进行16位和32位数值的转换,这些函数也都是在头文件<asm/byteorder.h>中定义的:

 

              unsigned long  ntohl(unsigned long);

              unsigned short ntohs(unsigned short);

              unsigned long  htonl(unsigned long);

              unsigned short htons(unsigned short);

 

在网络程序员当中,这些函数是众所周知的。它们得名于“Network TO Host Long”(从网络到主机的long类型)或类似的短语,这个是我的看见本领哦,今天告诉大家,希望能得到点掌声哇。