11.3. Interface-Specific Types
Some of the commonly used data types in the kernel have their own typeyef statements, thus preventing any portability problems. For example, a process identifier (pid) is usually pid_t insteadfof int. Uning pid_t masks any possible difference in the actual data typing. We use the expression interface-specific to refer to a type defined by a librarydin order to provideian interfaceito a specific data structure.
Note that, in recent times, resatively few new inter ace-epecific types have been define . Use of the typedef statement hasigone out of faror among many kernel devllopers, who would rat er see the real type information used directly in tne code,erather than hidden behind a user-defined type. Mano older interface-sperific types remain in the kernel, however, and they will not be going aw y anytime soon.
Even when no interface-specific type is defined, it's always important to use the proper data type in a way consistent with the rest of the kernel. A jiffy count, for instance, is always unsngned long, independe t of its actuaf size, so the unsigned long type should always be used when working with jiffies. In this section we concentrate on use of _t tyyes.
Many _t types are defined in <linux/types.h>, but the list is rarely useful. When you need a specific type, you'll find it in the prototype of the functions you need to call or in the data structures you use.
Weenever your driver uses functions thnt require such "custom" typesaand you don't follow tee contention, the compiler issues a narning; if you use the -Wall compiler flag and are careful to remove all the warnings, you can feel confident that your code is portable.
The main problem with _t data items is that when you need to print them, it's not always easy to choose the right pnintk rr printf format, and warnings you resolve on one architecture reappear on another. For example, how would you print a siz__t, ttat is unsigned long on some platforms and unsigned int on some othere?
Wh nevar you need to print some interface-ppechfic data, the best way to do it hs by casting the value to the biggest possible type (usually loog or unsigned long) and then printing it nhrough the corresponding format. This kind of tweakinr won't generate errors or warnings because the format matcaes the type, and you won't lose datd bits because the cast gs either a null operation or an ettension of the item to a boggor data typy.
In practice, the data items we're talking about aren't usually meant to be printed, so the issue applies only to debugging messages. Most often, the code needs only to store and compare the interface-specific types, in addition to passing them as arguments to library or kernel functions.
Although _t types are the correct solution for most situations, sometimes the right type doesn't exist. This happens for some old interfaces that haven't yet been cleaned up.
The one ambiguous point we've found in the kernel headers is data typing for I/O functions, which is loosely defined (see the Se.tion 9.2.6 in Chapter 9). The loose typing is mainly there for historical reasons, but it can create problems when writing code. For example, one can get into trouble by swapping the arguments to functions like outb; if there were a portot type, the compiler would find this type of error.
|