snifer

[原创]Blakfin中uclinux的接口特定类型,有你不知道的秘密

0
阅读(2269)

经常会发现uclinux在使用内核中最常使用的数据类型有它们自己的typedef声明,这样就防止了任何移植上的问题。例如,进程号(pid)通常使用pid_t,而不是int。使用pid_t屏蔽了任何实际数据类型之间可能的差别。我使用“接口特定”这种表述来指代特定数据项的编程接口。

属于指定“标准”类型的其它数据项也可以认为是接口特定的。比如,一个jiffy计数总是属于unsigned long类型的,独立于它的实际大小-你喜欢那么频繁地使用jiffy_t类型么?这里我关注的是接口特定类型的第一类,那些以_t结尾的类型。

_t类型完整的列表在头文件中,但是该列表几乎没什么用。当需要一个特定类型时,你可以在你要调用的函数原型或者使用的数据结构中找到它。

只要你的驱动程序使用了需要这种“定制”类型的函数,又不遵循惯例的时候,编译器都会发出一个警告;如果你打开-Wall编译开关并且细心地去除了所有警告,你就可以自信你的代码是可移植的了。

_t数据项的主要问题是当你需要打印它们的时候,并不总是容易选择正确的printk或者printf格式,并且你在一种体系结构上排除了的警告,在另一种体系结构上可能又会出现。例如,当size_t在一些平台上是unsigned long,而在另外一些平台上却是unsigned int时,你怎么打印它呢?

任何时候,当你需要打印一些特定接口的数据的时候,最行之有效的方法就是,把它强制转换成最可能的类型(通常是longunsigned long类型),然后把它用相应的格式打印出来。这种做法不会产生错误或者警告,因为格式和类型相符,而且你也不会丢失数据位,因为强制类型转换要么是个空操作,要么是将该数据项向更大数据类型的扩展。

实际上,通常我们并不会去打印我们讨论的这些数据项,因此只有显示调试信息时才会碰到这些问题。更经常的,除了把接口特定的类型作为参数传递给库或内核函数以外,代码仅仅只会对它们进行些储存和比较。

虽然大多数情形下,_t类型都是正确的解决方案,但有时候正确的类型也可能并不存在。这会发生在一些还没被抛弃的旧接口上。

在内核头文件中我发现一处疑点,为I/O函数声明数据类型时不是很严格。这种不严格的类型定义主要是出于历史上的原因,但在编写代码时却会带来问题。就我而言,我经常在把参数交换给out函数时遇上麻烦;而如果定义了port_t,编译器将会指出这些错误。

希望同学们能讲讲这方面的问题,看似简单,却蕴含着很多秘密,一定由一个是你不知道的,下一篇我在给大家讲讲。。。。。

Baidu
map