第三章:字符设备驱动-11:scull’s Memory Usage-1

In continuation of the previous text第三章:字符设备驱动-10:open and release--release let's GO ahead.

scull’s Memory Usage

Before introducing the read and write operations, we’d better look at how and why scull performs memory allocation. “How” is needed to thoroughly understand the code, and “why” demonstrates the kind of choices a driver writer needs to make, although scull is definitely not typical as a device.

This section deals only with the memory allocation policy in scull and doesn’t show the hardware management skills you need to write real drivers. These skills are introduced in Chapters 9 and 10. Therefore, you can skip this section if you’re not interested in understanding the inner workings of the memory-oriented scull driver.

The region of memory used by scull, also called a device, is variable in length. The more you write, the more it grows; trimming is performed by overwriting the device with a shorter file.

The scull driver introduces two core functions used to manage memory in the Linux
kernel. These functions, defined in <linux/slab.h>, are:

在介绍 read 和 write 操作之前,我们最好先了解 scull 是如何以及为何进行内存分配的。"如何" 是理解代码的基础,而 "为何" 则展示了驱动开发者需要做出的选择(尽管 scull 作为设备并不典型)。

本节仅讨论 scull 中的内存分配策略,不涉及编写真实驱动所需的硬件管理技巧(这些技巧将在第 9 章和第 10 章介绍)。因此,如果你对这个面向内存的 scull 驱动的内部工作原理不感兴趣,可以跳过本节。

scull 使用的内存区域(也称为设备)长度是可变的:写入的数据越多,它就越大;用较短的文件覆盖设备时,会触发截断操作。

scull 驱动引入了两个 Linux 内核中用于内存管理的核心函数,这些函数定义在 <linux/slab.h> 中:

void *kmalloc(size_t size, int flags);
void kfree(void *ptr);

A call to kmalloc attempts to allocate size bytes of memory; the return value is a pointer to that memory or NULL if the allocation fails. The flags argument is used to describe how the memory should be allocated; we examine those flags in detail in Chapter 8. For now, we always use GFP_KERNEL. Allocated memory should be freed with kfree. You should never pass anything to kfree that was not obtained from kmalloc. It is, however, legal to pass a NULL pointer to kfree.

kmalloc is not the most efficient way to allocate large areas of memory (see Chapter 8), so the implementation chosen for scull is not a particularly smart one. The source code for a smart implementation would be more difficult to read, and the aim of this section is to show read and write, not memory management. That’s why the code just uses kmalloc and kfree without resorting to allocation of whole pages, although that approach would be more efficient.

调用 kmalloc 会尝试分配 size 字节的内存,返回值是指向该内存的指针;若分配失败,则返回 NULLflags 参数用于描述内存分配的方式(我们将在第 8 章详细讨论这些标志),目前我们始终使用 GFP_KERNEL。分配的内存应使用 kfree 释放,绝不能将非 kmalloc 分配的内存传给 kfree,但向 kfree 传递 NULL 指针是合法的。

kmalloc 并不是分配大块内存最高效的方式(见第 8 章),因此 scull 选择的实现方式并不是特别智能。更高效的实现代码会更难读懂,而本节的目的是展示 read 和 write 操作,而非内存管理。这就是为什么代码仅使用 kmalloc 和 kfree,而没有采用更高效的整页分配方式。

补充说明

  1. GFP_KERNEL 标志的含义

    这是内核内存分配最常用的标志,其核心特性是:

    1. scull 作为内存设备,其操作均在可睡眠上下文中执行,因此适合使用该标志。

    2. 只能在可睡眠的上下文中使用(如 openread 等系统调用处理过程),不能在中断处理程序等禁止睡眠的场景中使用;

    3. 允许分配过程在内存不足时进入睡眠状态,等待系统释放足够内存;

  2. kmalloc 与用户态 malloc 的区别

    特性kmalloc(内核态)malloc(用户态)
    分配粒度最小 32 字节(依架构而定),最大通常为 128KB字节级灵活分配
    内存区域从内核堆(slab 分配器)分配从用户堆分配
    失败处理返回 NULL,需显式检查失败时可能触发异常(如 bad_alloc
    物理连续性保证分配的内存物理地址连续仅保证虚拟地址连续,物理地址可能离散
  3. scull 选择 kmalloc 的原因

    尽管 kmalloc 不适合大块内存,但对 scull 而言有明显优势:

    1. 释放操作简单(单 kfree 调用即可),降低示例代码复杂度。

    2. 分配的内存可直接访问(无需映射),简化 read/write 中的数据拷贝;

    3. 简单直观,适合作为示例驱动展示基本内存操作;

  4. scull 的内存组织方式预告

    ​​​​​​​scull 通过 “量子(quantum)” 和 “量子集(qset)” 两级结构管理内存:

    1. 这种结构平衡了内存利用率和管理复杂度,后续 read/write 方法会基于此实现数据读写。

    2. 量子集:包含多个量子的数组(如 100 个量子),形成更大的内存区域;

    3. 量子:最小分配单位(如 4KB),对应 kmalloc 分配的单个内存块;


技术交流,欢迎加入社区:GPUers

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeeplyMind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值