在介绍读写操作前, 我们最好看看如何以及为什么 scull 进行内存分配. "如何"是需要全 面理解代码, "为什么"演示了驱动编写者需要做的选择, 尽管 scull 明确地不是典型设备.

本节只处理 scull 中的内存分配策略, 不展示给你编写真正驱动需要的硬件管理技能.

其他风味的设备由不同的函数关闭, 因为 scull_open 为每个设备替换了不同的 filp->f_op. 我们在介绍每种风

味时再讨论它们.

scull 使用的内存区, 也称为一个设备, 长度可变. 你写的越多, 它增长越多; 通过使用 一个短文件覆盖设备来进行修整.

scull 驱动引入 2 个核心函数来管理 Linux 内核中的内存. 这些函数,
定义在

<linux/slab.h>, 是:

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

对 kmalloc 的调用试图分配 size 字节的内存; 返回值是指向那个内存的指针或者如果分 配失败为 NULL. flags 参数用来描述内存应当如何分配; 我们在第 8 章详细查看这些标 志. 对于现在,
我们一直使用 GFP_KERNEL. 分配的内存应当用
kfree 来释放. 你应当从 不传递任何不是从
kmalloc 获得的东西给 kfree. 但是, 传递一个 NULL 指针给 kfree 是合法的.

kmalloc 不是最有效的分配大内存区的方法(见第 8 章), 所以挑选给 scull 的实现不是 一个特别巧妙的. 一个巧妙的源码实现可能更难阅读, 而本节的目标是展示读和写, 不是 内存管理. 这是为什么代码只是使用 kmalloc 和 kfree 而不依靠整页的分配, 尽管这个 方法会更有效.

在 flip 一边, 我们不想限制"设备"区的大小, 由于理论上的和实践上的理由. 理论上,
给在被管理的数据项施加武断的限制总是个坏想法. 实践上,
scull 可用来暂时地吃光你 系统中的内存, 以便运行在低内存条件下的测试. 运行这样的测试可能会帮助你理解系统 的内部. 你可以使用命令 cp /dev/zero /dev/scull0 来用 scull 吃掉所有的真实 RAM, 并且你可以使用 dd 工具来选择贝多少数据给 scull 设备.

在 scull, 每个设备是一个指针链表, 每个都指向一个 scull_dev 结构. 每个这样的结构, 缺省地, 指向最多 4 兆字节, 通过一个中间指针数组. 发行代码使用一个 1000 个指针的 数组指向每个 4000 字节的区域. 我们称每个内存区域为一个量子, 数组(或者它的长度) 为一个量子集. 一个 scull 设备和它的内存区如图一个 scull 设备的布局所示.

选定的数字是这样, 在 scull 中写单个一个字节消耗 8000 或 12,000 KB 内存:
4000 是 量子, 4000 或者 8000 是量子集(根据指针在目标平台上是用 32 位还是
64 位表示). 相 反, 如果你写入大量数据, 链表的开销不是太坏. 每 4 MB 数据只有一个链表元素, 设备 的最大尺寸受限于计算机的内存大小.

为量子和量子集选择合适的值是一个策略问题, 而不是机制, 并且优化的值依赖于设备如 何使用. 因此, scull 驱动不应当强制给量子和量子集使用任何特别的值. 在 scull 中, 用户可以掌管改变这些值, 有几个途径:编译时间通过改变
scull.h 中的宏

SCULL_QUANTUM 和 SCULL_QSET, 在模块加载时设定整数值 scull_quantum 和 scull_qset, 或者使用 ioctl 在运行时改变当前值和缺省值.

使用宏定义和一个整数值来进行编译时和加载时配置, 是对于如何选择主编号的回忆. 我 们在驱动中任何与策略相关或专断的值上运用这个技术.

余下的唯一问题是如果选择缺省值. 在这个特殊情况下, 问题是找到最好的平衡, 由填充 了一半的量子和量子集导致内存浪费, 如果量子和量子集小的情况下分配释放和指针连接 引起开销. 另外, kmalloc 的内部设计应当考虑进去. (现在我们不追求这点, 不过; kmalloc 的内部在第
8 章探索.) 缺省值的选择来自假设测试时可能有大量数据写进
scull, 尽管设备的正常使用最可能只传送几 KB 数据.

我们已经见过内部代表我们设备的
scull_dev 结构. 结构的 quantum 和 qset 分别代表 设备的量子和量子集大小. 实际数据, 但是, 是由一个不同的结构跟踪, 我们称为
struct scull_qset:

struct scull_qset { void **data;

struct
scull_qset *next;

};

下一个代码片段展示了实际中 struct
scull_dev 和 struct scull_qset 是如何被用来持 有数据的. sucll_trim 函数负责释放整个数据区, 由
scull_open 在文件为写而打开时调 用. 它简单地遍历列表并且释放它发现的任何量子和量子集.

int
scull_trim(struct scull_dev *dev)

{

struct
scull_qset *next, *dptr;

int
qset = dev->qset; /* "dev" is not-null */ int i;

for
(dptr = dev->data; dptr; dptr = next)

{
/* all the list items */

if
(dptr->data) {

for
(i = 0; i < qset; i++)

kfree(dptr->data[i]); kfree(dptr->data);

dptr->data
= NULL;

}

next
= dptr->next; kfree(dptr);

}

dev->size = 0;

dev->quantum
= scull_quantum; dev->qset = scull_qset;

dev->data = NULL; return 0;

}

scull_trim 也用在模块清理函数中, 来归还 scull 使用的内存给系统.

linux scull 的内存使用的更多相关文章

  1. Linux内核笔记--内存管理之用户态进程内存分配

    内核版本:linux-2.6.11 Linux在加载一个可执行程序的时候做了种种复杂的工作,内存分配是其中非常重要的一环,作为一个linux程序员必然会想要知道这个过程到底是怎么样的,内核源码会告诉你 ...

  2. Linux内核笔记——内存管理之slab分配器

    内核版本:linux-2.6.11 内存区和内存对象 伙伴系统是linux用于满足对不同大小块内存分配和释放请求的解决方案,它为slab分配器提供页框分配请求的实现. 如果我们需要请求具有连续物理地址 ...

  3. Linux下清理内存和Cache方法 /proc/sys/vm/drop_caches

    Linux下清理内存和Cache方法 /proc/sys/vm/drop_caches 频繁的文件访问会导致系统的Cache使用量大增 $ free -m total used free shared ...

  4. Linux安装时内存如何分区的相关问题

    Linux系统安装时内存如何分区:Linux系统必须的分区是根分区(/)和swap交换分区.普通用户一般分三个区,一个根分区(/),一个家目录(home分区),一个交换分区(swap分区),以80G的 ...

  5. Linux C程序内存空间

    linux下内存空间布置: 一个典型的Linux C程序内存空间由如下几部分组成: 代码段(.text).这里存放的是CPU要执行的指令.代码段是可共享的,相同的代码在内存中只会有一个拷贝,同时这个段 ...

  6. Linux驱动之内存映射

    本文参考了http://www.cnblogs.com/geneil/archive/2011/12/08/2281222.html.本文作为学习总结,将主要过程简要描述. 很多驱动实现某些功能都要通 ...

  7. 全面了解 Linux 服务器 - 2. 查看 Linux 服务器的内存使用情况

    2. 查看 Linux 服务器的内存使用情况 liuqian@ubuntu:~$ free -m total used free shared buffers cached Mem: 1983 186 ...

  8. Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式

    Linux就这个范儿 第15章 七种武器  linux 同步IO: sync.fsync与fdatasync   Linux中的内存大页面huge page/large page  David Cut ...

  9. linux下共享内存mmap和DMA(直接访问内存)的使用 【转】

    转自:http://blog.chinaunix.net/uid-7374279-id-4413316.html 介绍Linux内存管理和内存映射的奥秘.同时讲述设备驱动程序是如何使用“直接内存访问” ...

随机推荐

  1. python ndarray相关操作:切分

  2. LeetCode136 Single Number, LeetCode137 Single Number II, LeetCode260 Single Number III

    136. Single Number Given an array of integers, every element appears twice except for one. Find that ...

  3. kubernetes1.5新特性跟踪

    Kubernetes发布历史回顾 Kubernetes 1.0 - 2015年7月发布 Kubernetes 1.1 - 2015年11月发布 Kubernetes 1.2 - 2016年3月发布 K ...

  4. Spring CommonsMultipartResolver上传文件小结

    自从业至今,文件上传与IO流之类的调用,一直是理解比较模糊的地方,大多就这网上搜到的资料抄抄改改草草了事,内部原理一直不甚了解,今日我们通过Spring的CommonsMultipartResolve ...

  5. php的模板原理

    下载了开源论坛phpbb的代码,突然对php模板初步了解了一下: php与Html在一起编写真的是很烦人,所以必须要把数据计算以及显示格式分离,这就需要模板来实现了. http://baike.bai ...

  6. VBA 生成带时间戳的随机数字

    Function GenPasswd(length, level) Dim allstr, substr, passwd As String allstr = "0123456789abcd ...

  7. rsa加解密的内容超长的问题解决

    一. 现象:      有一段老代码用来加密的,但是在使用key A的时候,抛出了异常:javax.crypto.IllegalBlockSizeException: Data must not be ...

  8. Objectarx之分批存储相连实体

    void CCommonFuntion::BatchStorageEnt(AcDbObjectIdArray& inputId, std::vector<std::vector<A ...

  9. Zabbix清理历史数据库,缩减表大小

    zabbix 由于历史数据过大, 因此导致磁盘空间暴涨,  下面是解决方法步骤: 一.分析数据库: 1. 统计数据库中每个表所占的空间: mysql> SELECT table_name AS ...

  10. 2019-7-4-win10-uwp-处理用户点击关闭按钮

    title author date CreateTime categories win10 uwp 处理用户点击关闭按钮 lindexi 2019-07-04 09:28:57 +0800 2019- ...