【问题标题】:Red black node's struct alignment in linux kernellinux内核中红黑节点的结构对齐
【发布时间】:2013-06-21 17:50:12
【问题描述】:

linux内核中rb_node的定义如下:

struct rb_node {
    unsigned long  __rb_parent_color;
    struct rb_node *rb_right;
    struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));

#define rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r)   ((r)->rb_parent_color & 1)
#define rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)

我的问题是关于__rb_parent_color,其中最后一位是颜色,其余的是指向其父级的指针。

我了解到有人说 __rb_parent_color 的最后 2 位因为 aligned(sizeof(long)) 而没有用,但为什么呢?

不是sizeof(struct rb_node *) 4 还是不是sizeof(unsigned long) 4?即使它们不相等,aligned 是否应该在 Byte 中,如果不对齐,至少会有一个完整的 Byte 是无用的?

【问题讨论】:

    标签: c struct linux-kernel binary-tree red-black-tree


    【解决方案1】:

    __attribute__((aligned(sizeof(long)))) 告诉编译器确保struct rb_node 的大小始终至少是sizeof(long) 的倍数。见GCC docs

    尽管这点有点无关紧要(因为指针至少是sizeof(long)。在查看源代码时,您遗漏了最重要的部分:

    /* The alignment might seem pointless, but allegedly CRIS needs it */
    

    此实现工作的关键在于,struct rb_nodes 将始终分配在至少 4 字节对齐的地址上。这是guaranteed

    在 32 位 CPU 上保证 4 字节对齐,在 64 位 CPU 上保证 8 字节对齐。

    例如,一个节点指针可能类似于0xF724315C,在二进制中以...1100结尾。

    这意味着指向struct rb_nodeany 指针的最后两位将为零。因此,开发人员决定将这两个位用于其他用途(这里是颜色。)

    我们在以下macro 中看到了这一点:

    #define rb_parent(r)   ((struct rb_node *)((r)->__rb_parent_color & ~3))
    

    要获得父节点,可以使用与低两位相加的宏。

    【讨论】:

    • 我想我明白了:指针保存了一个节点的地址,由于 4 对齐,它是 4(100) 的倍数,所以指针的值总是像 100、1000、1100, 10100100。总是以 00 结尾。非常感谢!
    • 是的,听起来你已经明白了。请记住 aligned(sizeof(long)) 在这里并不重要 - 这实际上是 kmalloc 对齐分配的函数。
    猜你喜欢
    • 2011-02-10
    • 2012-06-03
    • 1970-01-01
    • 2017-03-02
    • 1970-01-01
    • 2014-01-13
    • 1970-01-01
    • 1970-01-01
    • 2015-11-17
    相关资源
    最近更新 更多