当Linux内核分配像skbuff这样的结构时,分配的数据区域(skbuff->tail - skbuff->head)是否总是一个连续的内存块,或者这可以是不连续的吗?
1 回答
简短的回答:
是的。内存范围 [ skbuff->end - skbuff->head
] 始终是一个连续的内存块。
长答案:
仍然是,但是如果您的 skbuff 是碎片化的(稍后我将解释如何检查它是否碎片化),那么您的数据将不会位于一个连续的内存块上。请注意,范围内的数据[skbuff->end - skbuff->head]
仍然在一个连续的内存块中,但并非分片的 skbuff 的所有数据都在范围内[skbuff->end - skbuff->head]
。
如果您想更深入地了解如何使用fragmented skbuff
,那么我建议您阅读这篇文章(并从本标题开始阅读When SKB is Non Linear)。我认为那里的解释很清楚,也很形象化。
我怎么知道我的 skbuff 是碎片化的?
如果您不是分配 skbuff 的人,并且您想了解您正在使用的 skbuff 的数据是否碎片,您可以检查以下值skb->data_len
:
- 如果它等于 0,那么 skbuff 是线性的(不是分段的 - 数据位于连续的内存块上)并且数据的大小是
skb->len
. - 如果它大于 0,则 skbuff 不是线性的(数据是分段的),
skb->len
仍然是完整帧的长度,并且skb->data_len
是所有数据片段的总长度,不包括第一个片段。
您也可以只调用skb_is_nonlinear()
,如果它返回true
,则 skbuff 是碎片化的(位于物理非连续内存上)。
奖励:
如果你收到了一个碎片化的 skbuff 并且你不能使用碎片化的 skbuff(因为你的硬件不支持它或其他一些原因),那么你可以通过使用函数 skb_copy ()。但请记住,此功能将创建原始 skbuff 的副本,因此此操作将花费您……
嗯……并且不要忘记释放原始 skbuff。