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(结构体, 成员) 驱动灵魂!不掌握这个写不了任何现代驱动 "从零件找到整车"
相关推荐
艾莉丝努力练剑2 小时前
【Linux:文件 + 进程】进程间通信进阶(1)
linux·运维·服务器·网络·c++·人工智能·进程
IMPYLH2 小时前
Linux 的 cat 命令
linux·运维·服务器
夜阑卧听风吹雨c2 小时前
Linux 基础操作命令笔记(Ubuntu 常用版)
linux
疋瓞2 小时前
C\C++\python对比_概览(1)
c语言·c++·python
虾..2 小时前
Linux HTTP协议
linux·运维·http
海盗猫鸥2 小时前
「Linux工具」gcc/g++
linux·c语言·c++
波特率1152002 小时前
bash命令进阶学习(Shell 元字符)
linux·bash·shell
Lsir10110_2 小时前
【Linux】网络编程基础—套接字
linux·运维·服务器·网络·c++
Java小白笔记2 小时前
Linux中使用systemd服务单元定时任务
linux·服务器·网络