Linux驱动开发理解指针与结构体

第一部分:指针到底是什么?

指针 = 一张"地址小纸条"

  • 普通变量:家里放了一把钥匙(值)。
  • 指针变量:手里拿着一张写着"钥匙放在哪"的纸条(地址)。

看下面这张图(最经典的指针解释):

图里关键点

  • var 变量放在地址 0x7ffa0757dd4,里面存着 10
  • ptr 是指针,它自己存的不是 10,而是 var 的地址 0x7ffa0757dd4
  • *ptr(解引用) = 顺着纸条找到钥匙,拿到 10

一句话总结

指针变量里存的是别人的内存地址 ,用 * 才能拿到真正的值。

第二部分:结构体是什么?

结构体 = 一个"文件袋",里面可以放不同类型的东西。

看下面这张图(结构体在内存里的真实样子):

图里说明

  • struct example 里有 char aint bchar c
  • 因为CPU喜欢"对齐"(一次读4字节),编译器会自动在中间加padding(填充)
  • 所以整个结构体占12字节,而不是6字节(这在内核驱动里非常重要!)

第三部分:指针 + 结构体 = Linux驱动里的"王炸"

最常用的是指向结构体的指针

看这张超级清晰的图:

图里解释

  • ptr 存的是整个结构体的起始地址(1080)
  • 通过 ptr->nameptr->roll 就能直接访问里面的字段
  • 这就是驱动里 struct my_device *dev = ... 的真实样子!

再看一张更直观的(指针指向结构体):

驱动里的实际例子

c 复制代码
struct my_device {
    int id;              // 设备编号
    char name[32];       // 设备名字
};

struct my_device dev;           // 普通结构体变量
struct my_device *p = &dev;     // 指针指向它(驱动里99%都用这种)

p->id = 1;                      // 等价于 (*p).id = 1

实例练习

Ubuntu 新建 understand_lab.c,复制下面代码运行:

c 复制代码
#include <stdio.h>

struct student {
    int id;
    char name[20];
};

int main() {
    struct student s = { .id = 100, .name = "Tesha" };
    struct student *p = &s;          // 指针指向结构体

    printf("直接访问:id=%d, name=%s\n", s.id, s.name);
    printf("通过指针访问:id=%d, name=%s\n", p->id, p->name);

    printf("结构体地址:%p\n", (void*)&s);
    printf("指针存的地址:%p\n", (void*)p);
    return 0;
}

编译运行:

bash 复制代码
gcc -Wall -g understand_lab.c -o understand_lab
./understand_lab

输出如下:

第四部分:C语言指针与结构体核心符号对比表(驱动开发专用版)

概念/符号 含义(白话解释) 适用对象 示例代码 内存本质(地址视角) 驱动开发注意点(避免Panic) 等价写法 / 口诀
普通变量 直接存放"值"(钥匙) 变量本体 int a = 42; 地址里存的是值本身 几乎不用(驱动里全是指针) -
指针变量 存放"地址纸条"(指向别人的地址) 任何类型 int *p = &a; 地址里存的是另一个变量的地址 必须先判断 if (!p),否则空指针Panic "纸条"
& (取地址) "给我这个变量的地址" 变量本体 p = &a;struct student *sp = &s; 返回变量的起始地址 只用于赋值给指针变量 "拿纸条"
*** ** (星号) ①声明指针 ②解引用(打开纸条看内容) ①声明时 ②使用时 int *p; *p = 100; ①声明类型 ②顺着地址取值/改值 忘记解引用或多解引用会导致野指针 "*声明=指针,*使用=打开看"
. (点) 访问结构体本体的成员 结构体变量(非指针) struct student s; s.id = 100; 结构体起始地址 + 成员偏移 驱动里几乎不用(指针太多) "本体用点"
-> (箭头) 访问指向结构体的指针的成员 结构体指针 struct student *p; p->id = 100; 先解引用指针得到结构体地址,再加偏移 驱动里90% 用这个(filp->private_data 等) "指针用箭头"
结构体 把多个不同类型数据打包成一个"文件袋" 自定义类型 struct my_dev { int id; char name[32]; }; 连续内存块(可能有padding对齐) 必须用 container_of 从成员反推整个结构体 "文件袋"
container_of 从成员指针反推出整个结构体指针 内核链表/嵌入式结构体 dev = container_of(pos, struct my_dev, list); ptr - offsetof(结构体, 成员) 驱动灵魂!不掌握这个写不了任何现代驱动 "从零件找到整车"
相关推荐
小肝一下6 分钟前
3. 单链表
c语言·数据结构·c++·算法·leetcode·链表·dijkstra
不会就选b30 分钟前
linux之进程管理(二)--替换
linux·运维·服务器
倔强的石头10636 分钟前
【Linux指南】动静态库系列(二):从源码复用到目标文件复用:为什么需要把 .o 打包成库
linux·运维·服务器
炸膛坦客9 小时前
单片机/C/C++八股:(二十六)IIC 专题(I²C)---- 上集
c语言·c++·单片机
HLC++13 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室14 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
程序员Rock16 小时前
上位机开发-MODBUS面试常见问题
c语言·c++·面试·职场和发展·上位机
groundhappy17 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕17 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu