何时在驱动程序代码中使用 stdint.h 的标量

When to use stdint.h's scalars in driver code

我注意到,在使用本机标量类型(整数、短整型、字符)或 stdint 提供的标量类型时似乎没有一致性或最佳实践:uint32_t uint16_t uint8_t.

这让我很烦恼,因为驱动程序是内核的重要组成部分,需要可维护、一致、稳定和良好。

这是 gcc 中的一个说明性示例(用于 raspberry pi 的业余项目):

// using native scalars
struct fbinfo {
        unsigned width, height;
        unsigned vwidth, vheight;
        unsigned pitch, bits;
        int x, y;
        void *ptr;
        unsigned size;
} __attribute__((aligned(16)));

// using stdint scalars
struct fbinfo {
        uint32_t width, height;
        uint32_t vwidth, vheight;
        uint32_t pitch, bits;
        int32_t x, y;
        uint32_t ptr; // convert to void* in order to use it
        uint32_t size;
} __attribute__((aligned(16)));

对我来说,第一个例子似乎更符合逻辑,因为这段代码 仅用于 运行 raspberry pi。 运行 毫无意义 这在其他硬件上。

第二个例子看起来更实用,因为它看起来更 描述性的,因为 C 不能保证整数的大小。 它可能是 16 位或其他。 uint32_t、uint_fast32_t 和变体保证了精确或近似的大小:例如至少或最多 X 字节。

操作系统开发社区倾向于使用 stdint 类型,而 linux 内核使用多种不同的技术:u32、__u32 和字节序特定的东西,如 __le32。

何时选择标量类型以及何时使用 typedef 的标量类型应考虑哪些因素?在提供的示例中使用本机标量类型还是使用 stdint.h 更好?

1。固定与基本类型

固定宽度的字体有时很难使用。例如。 int32_tprintf() 说明符是 PRIi32 并且需要拆分格式字符串:

printk("foo=" PRIi32 ", bar=" PRIi32 "\n", foo, bar);

固定宽度类型should/must直接访问硬件时使用;例如写 DMA 描述符时。但是对于简单的寄存器访问,可以使用 writel()readl() 函数来处理基本类型。

根据经验,当假定某种内存布局时(如示例中的 __attribute__((__aligned__(16))),应使用固定宽度类型。

带符号的固定宽度类型(在您的示例中为 int32_t x,y)可能需要仔细检查它们的表示是否符合硬件预期。

注意在您的示例中,第二个结构依赖于体系结构,因为

    uint32_t ptr; // convert to void* in order to use it

在普通 C 中写这样的东西是 uintptr_t ptr 而在内核中通常写成

    unsigned long ptr;

或者,dma_addr_t 可能是更好的类型。

2。 uint32_t__u32

10 多年前,Linus Torvalds 反对 uint32_t 因为当时非 C99 编译器很普遍,并且在(导出)linux header 中使用此类类型会污染命名空间。

但是现在,uint32_t和类似的类型随处可见(你不能用非C99编译器编译内核)并且内核header导出已得到显着改进,因此这些参数是走了。

使用标准类型还是 typedef 变体(依赖于框架并且它们之间存在差异)是个人喜好问题。

3。 uint_fastX_t 和变体

它们没有在内核中使用,我会避免使用它们。它们结合了 uint32_t(难以使用)和 int(可变宽度)的缺点。

4。 __le32__u32

在规范明确要求时使用字节序类型(例如在网络协议实现中)。这使得检测错误用法变得容易(例如 endian_variable = native_variable 之类的赋值)。

不要使用它们,例如用于填充处理器结构(例如 DMA 描述符);一些处理器可以 运行 小端模式和大端模式,并且本机数据类型通常是编写此类信息的正确方法。