union {
/* Remap range. */
struct {
unsigned long start;
unsigned long start_pfn;
unsigned long size;
pgprot_t pgprot;
} remap;
};
Linux 内核中一个非常典型的用法:用 union 包裹一个匿名结构体,用于表示不同的映射类型共享同一片内存区域。
1. 为扩展预留空间(最常见原因)
虽然现在 union 里只有一个 struct,但这是为了方便未来添加其他映射类型:
union {
struct {
unsigned long start;
unsigned long start_pfn;
unsigned long size;
pgprot_t pgprot;
} remap; // 内存重映射类型
struct {
unsigned long pfn;
unsigned long size;
pgprot_t pgprot;
int flags;
} direct; // 直接映射类型(未来扩展)
struct {
unsigned long vaddr;
unsigned long size;
int cache_flags;
} iomap; // IO 映射类型(未来扩展)
};
这样,不同的映射方式可以共用同一块内存,节省空间。
2. 确保结构体满足对齐要求
union 的对齐要求是其最大成员的对齐要求。虽然现在只有一个成员,但这种写法:
* 为将来扩展做好了准备
* 保证 start 等字段按 unsigned long 对齐(通常是 8 字节)
* 如果后续添加一个需要更大对齐的类型(如 long long 或 __int128),union 会自动适配
3. 代码组织与语义清晰
在内核代码中,这种写法通常出现在描述虚拟内存区域(VMA) 或 页表项 的结构体中:
struct vm_area_struct {
// ... 其他字段
union {
struct {
unsigned long start;
unsigned long start_pfn;
unsigned long size;
pgprot_t pgprot;
} remap;
// 其他映射类型...
};
// ... 更多字段
};
* remap 这个名字清晰地表明:这块内存用于 remap(重新映射) 操作
* 当内核需要处理 remap_pfn_range() 这类函数时,使用 remap 字段
* 代码可读性大大提升
4. 避免命名空间污染
因为是匿名 union(C11 特性),使用时可以直接访问:
// 假设 vma 是这个结构体的指针
vma->remap.start = addr; // 清晰
vma->remap.size = len; // 直观
而不是:
vma->map_info.remap.start // 多了一层
vma->map_info.direct.pfn // 需要区分
内核例子
在 Linux 内核的 linux/mm.h 或 linux/io.h 相关代码中,这种模式真实存在:
// 简化的真实内核代码片段
struct remap_pfn_data {
struct vm_area_struct *vma;
unsigned long addr;
unsigned long pfn;
unsigned long size;
pgprot_t prot;
};
// 在某个结构体中...
union map_info {
struct {
unsigned long start;
unsigned long start_pfn;
unsigned long size;
pgprot_t pgprot;
} remap;
struct {
unsigned long pfn;
unsigned long size;
unsigned long offset;
} linear;
};
即使只有一个成员,这种写法也有价值:
* 面向未来的扩展:代码可能很快就会增加新的映射类型
* 统一的访问模式:所有映射类型都通过 remap、direct 等字段名访问
* 满足对齐要求:确保后面的字段(如果有)不会破坏 union 成员的对齐
这段代码总结:
* 当前功能:包含一个 remap 结构体,存储内存重映射需要的参数
* 设计意图:为未来添加其他映射类型(直接映射、IO 映射等)预留空间
* 技术价值:
# 内存复用(不同映射类型不共存)
# 对齐一致性(按最大成员对齐)
# 代码可扩展性(添加新类型不影响现有代码)
# 语义清晰(remap 名称明确表达用途)
这是 Linux 内核中非常优雅的 C 语言设计模式,体现了面向接口编程和预留扩展性的思想。
1451

被折叠的 条评论
为什么被折叠?



