PAGE_MASK判定addr是否是4096倍数

本文详细解释了如何使用宏定义实现内存地址到页边界的对齐,并提供了具体的例子。通过位运算来确保地址总是对齐到4KB的整数倍。

将物理地址addr修整为页边界地址(页的上边界)

#define PAGE_ALIGN(addr)    (((addr)+PAGE_SIZE-1)&PAGE_MASK)

|------------|<-- PAGE_ALGN(addr)
|            |
|            |
|            |
|            |<-- addr
|            |
|            |
|            |
|            |
|------------|
one page(4K)
#define PAGE_SHIFT 12
#define PAGE_SIZE   (1UL << PAGE_SHIFT)
#define PAGE_MASK   (~(PAGE_SIZE-1))


PAGE_MASK = ~(1 0000 0000 0000 - 1) = ~(1111 1111 1111) = 0000 0000 0000 
PAGE_SIZE = 1 0000 0000 0000        = 2^12              = 4K

如addr为0x22000001 。。PAGE_ALIGN(addr)=(0x22000001+4096-1)&0xfffff000
=(0x22000001+0xfff)&0xfffff000=0x22001000&0xfffff000
=0x22001000;
同样,比如addr为0x22000003,PAGE_ALIGN(addr)后仍然是0x22001000;

就是和下一个页对齐,一个页为4k。起始地址为0x xxxxx 000;

只要把addr & ~PAGE_MASK就可判定addr是否是4096倍数,如果结果是1,则不是4096倍数

在这段代码中,`int class_mask = classful_mask_length(addr);` 的主要功能是根据传入的 IPv4 地址 `addr` 计算其对应的 **分类网络(Classful Network)的默认子网掩码长度**(即前缀长度),也就是确定该 IP 地址属于 A 类、B 类还是 C 类网络,并返回相应的默认掩码位数(如 8、16 或 24)。 ### 功能和作用详细分析: #### 1. **上下文背景** - 这段代码用于遍历一个 LC-Trie 结构(一种用于路由表查找的高效数据结构),并按顺序输出路由条目。 - 目标之一是在打印明细路由之前,**智能地汇总输出主类网络信息头**(例如:“192.168.1.0/24 is subnetted, 3 subnets”),避免重复打印。 - `class_mask` 是判断当前地址所属“主类网络”范围的关键依据。 #### 2. **函数解析:`classful_mask_length(addr)`** - 该函数根据传统 IP 地址分类规则(Classful Addressing)判断: - 如果地址以 `0xxxxxxx` 开头(即首位为0) → A类网络 → 返回 `8` - 如果以 `10xxxxxx` 开头 → B类网络 → 返回 `16` - 如果以 `110xxxxx` 开头 → C类网络 → 返回 `24` - (可能还处理 D/E 类但通常不参与掩码计算) - 它不依赖路由中的实际前缀长度(`prefixlen`),而是仅基于 IP 地址本身进行分类。 #### 3. **在当前逻辑中的关键作用** ```c if (prefixlen <= class_mask) { // 处理超网或主网条目 } ``` - 利用 `class_mask` 来判断当前路由是否是一个 **主类网络或更粗的聚合(超网)**。 - 若当前路由的前缀长度小于等于其主类掩码长度(如 `/8` 对于 A 类),说明它不是子网,而是主网或更大聚合,应直接输出,不触发子网汇总标题。 - 否则(`prefixlen > class_mask`),说明这是一个子网,需要考虑是否打印所属主类网络的汇总头信息(比如 “172.16.0.0/16 is subnetted...”)。 #### 4. **配合状态管理实现智能汇总头打印** - 使用 `state->dest` 和 `class_net_addr` 比较来检测是否进入新的主类网络。 - 只有当进入一个新的主类网络时,才查询预存的统计信息(`find_class_net_entry`)并打印汇总头。 - 而这一切的前提就是正确获取 `class_mask` —— 因此这行代码是决定是否打印汇总头、如何分组子网的核心依据。 --- ### 总结 `int class_mask = classful_mask_length(addr);` 这一行的作用是:**根据 IPv4 地址的类别(A/B/C类)确定其默认网络掩码长度,用于后续判断该地址所在的主类网络边界,从而支持子网汇总信息头的条件性打印。** 它是实现类似路由器 CLI 中 `"is subnetted"` 提示功能的关键步骤,使得输出更加结构化、可读性强,符合传统网络设备显示风格。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值