图解linux内核学习笔记

第2章 数据结构和设计模式

2.1.1 一对一关系

//指针
struct entity_a{
  struct entity_b * b;
};

struct entity_b{
  struct entity_a * a;
};
//内嵌(包含)
struct entity_a{
  struct entity_b b;
};

第二种方式的主要优点是对一对一关系体现得比较清晰,同时也方便管理, 因为通过container_of宏可以由b计算出 a 的位置,同时节省了指针的空间。
然而第二种方式本身意味着若a包含b (b是a的一部分),并不一定是最好的,要视逻辑而定。比如男人和妻子,在我国《婚姻法》上是一对一的,如果采用内嵌的方式首先造成的是逻辑混乱,男人结构体中多了女人这个不属于男人的成员;其次,并不是每个男人都有妻子,有些是单身,用指针表示就是NULL, 内嵌无疑浪费了空间。所以,要满足逻辑合理,当有a就有b这个条件时采用这种方式才是比较恰当的。

container_of

是 Linux 内核(以及很多 C 项目)里最常见、最基础的一个宏:“从结构体成员的地址反推出整个结构体的地址”。
它在内核链表中几乎无处不在,所有 list_for_each_entry* 都靠它把 struct list_head 变回你真正的数据结构。

#define container_of(ptr, type, member) ({                      \
    const typeof(((type *)0)->member) *__mptr = (ptr);          \
    (type *)((char *)__mptr - offsetof(type, member));          \
})

图片

实例代码如下:

#include<stdio.h>
#include<stddef.h>
#include<stdlib.h>

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)

/*ptr 成员指针
* type 结构体 比如struct Stu
* member 成员变量,跟指针对应
* */
#define container_of(ptr, type, member) ({          \
        const typeof( ((type *)0)->member ) *__mptr = (const typeof( ((type *)0)->member ) *)(ptr); \
        (type *)( (char *)__mptr - offsetof(type,member) );})


typedef struct Stu{
        int age;
        char name[10];
        int id;
        unsigned long phone_num;
}*p_stu,str_stu;

void print_all(void *p_str)
{

    p_stu m1p_stu = NULL;

    m1p_stu = container_of(p_str,struct Stu,age);

    printf("age:%d\n",m1p_stu->age);
    printf("name:%s\n",m1p_stu->name);
    printf("id:%d\n",m1p_stu->id);
    printf("phone_num:%d\n",m1p_stu->phone_num);
}


void main(void)
{
    p_stu m_stu = (p_stu)malloc(sizeof(str_stu));

    m_stu->age = 25;
    m_stu->id  = 1;
    m_stu->name[0]='w';
    m_stu->name[1]='e';
    m_stu->name[2]='i';
    m_stu->name[3]='q';
    m_stu->name[4]='i';
    m_stu->name[5]='f';
    m_stu->name[6]='a';
    m_stu->name[7]='\0';
    m_stu->phone_num=13267;

    /*传结构体成员指针进去*/
    print_all(&m_stu->age);

    printf("main end\n");

    if(m_stu!=NULL)
        free(m_stu);
}

程序输出:

age:25
name:weiqifa
id:1
phone_num:13267
main end

参考文献:https://zhuanlan.zhihu.com/p/54932270 写得很好

2.1.2 一对多关系

主要讲解内核链表 list
参考文献:https://zhuanlan.zhihu.com/p/450778696

posted @ 2025-08-05 15:41  爱吃鸡魔人zf  阅读(10)  评论(0)    收藏  举报