随笔分类 -  liunx设备驱动程序

上一页 1 ··· 3 4 5 6 7 8 9 10 11 下一页
个人学习使用,所有收集仅供参考。
摘要:在驱动硬件请求了在它的活动中需要使用的 I/O 端口范围之后, 它必须读且/或写到这些 端口. 为此, 大部分硬件区别 8-位, 16-位, 和 32-位端口. 常常你无法混合它们, 象你 正常使用系统内存存取一样.[33]33 一个 C 程序, 因此, 必须调用不同的函数来存取不同大小的端口. 如 阅读全文
posted @ 2019-07-06 11:48 樊伟胜 阅读(548) 评论(0) 推荐(0) 编辑
摘要:如同你可能希望的, 你不应当离开并开始抨击 I/O 端口而没有首先确认你对这些端口有 唯一的权限. 内核提供了一个注册接口以允许你的驱动来声明它需要的端口. 这个接口中 的核心的函数是 request_region: #include <linux/ioport.h> struct resource 阅读全文
posted @ 2019-07-06 11:43 樊伟胜 阅读(762) 评论(0) 推荐(0) 编辑
摘要:不管硬件寄存器和内存之间的强相似性, 存取 I/O 寄存器的程序员必须小心避免被 CPU(或者编译器)优化所戏弄, 它可能修改希望的 I/O 行为. I/O 寄存器和 RAM 的主要不同是 I/O 操作有边际效果, 而内存操作没有: 一个内存写的 唯一效果是存储一个值到一个位置, 并且一个内存读返回 阅读全文
posted @ 2019-07-06 11:30 樊伟胜 阅读(864) 评论(0) 推荐(0) 编辑
摘要:每个外设都是通过读写它的寄存器来控制. 大部分时间一个设备有几个寄存器, 并且在连 续地址存取它们, 或者在内存地址空间或者在 I/O 地址空间. 在硬件级别上, 内存区和 I/O 区域没有概念上的区别: 它们都是通过在地址总线和控制 总线上发出电信号来存取(即, 读写信号)[32]32并且读自或者 阅读全文
posted @ 2019-07-06 11:29 樊伟胜 阅读(283) 评论(0) 推荐(0) 编辑
摘要:如果你真的需要一个大的物理上连续的缓冲, 最好的方法是在启动时请求内存来分配它. 在启动时分配是获得连续内存页而避开 get_free_pages 施加的对缓冲大小限制的唯一 方法, 不但最大允许大小还有限制的大小选择. 在启动时分配内存是一个"脏"技术, 因为 它绕开了所有的内存管理策略通过保留一 阅读全文
posted @ 2019-07-06 11:28 樊伟胜 阅读(155) 评论(0) 推荐(0) 编辑
摘要:每-CPU 变量是一个有趣的 2.6 内核的特性. 当你创建一个每-CPU 变量, 系统中每个处理 器获得它自己的这个变量拷贝. 这个可能象一个想做的奇怪的事情, 但是它有自己的优点. 存取每-CPU 变量不需要(几乎)加锁, 因为每个处理器使用它自己的拷贝. 每-CPU 变量也 可存在于它们各自的 阅读全文
posted @ 2019-07-06 11:27 樊伟胜 阅读(336) 评论(0) 推荐(0) 编辑
摘要:我们展示给你的下一个内存分配函数是 vmlloc, 它在虚拟内存空间分配一块连续的内存 区. 尽管这些页在物理内存中不连续 (使用一个单独的对 alloc_page 的调用来获得每个 页), 内核看它们作为一个一个连续的地址范围. vmalloc 返回 0 ( NULL 地址 ) 如果发 生一个错误 阅读全文
posted @ 2019-07-06 11:26 樊伟胜 阅读(390) 评论(0) 推荐(0) 编辑
摘要:为完整起见, 我们介绍另一个内存分配的接口, 尽管我们不会准备使用它直到 15 章. 现 在, 能够说 struct page 是一个描述一个内存页的内部内核结构. 如同我们将见到的, 在内核中有许多地方有必要使用页结构; 它们是特别有用的, 在任何你可能处理高端内存 的情况下, 高端内存在内核空间 阅读全文
posted @ 2019-07-06 11:25 樊伟胜 阅读(1037) 评论(0) 推荐(0) 编辑
摘要:为了真实地测试页分配, 我们已随其他例子代码发布了 scullp 模块. 它是一个简化的 scull, 就像前面介绍过的 scullc. scullp 分配的内存量子是整页或者页集合: scullp_order 变量缺省是 0, 但是可以在编 译或加载时改变. 下列代码行显示了它如何分配内存: /* 阅读全文
posted @ 2019-07-06 11:24 樊伟胜 阅读(260) 评论(0) 推荐(0) 编辑
摘要:如果一个模块需要分配大块的内存, 它常常最好是使用一个面向页的技术. 请求整个页也 有其他的优点, 这个在 15 章介绍. 为分配页, 下列函数可用: get_zeroed_page(unsigned int flags); 返回一个指向新页的指针并且用零填充了该页. get_free_page(u 阅读全文
posted @ 2019-07-06 11:23 樊伟胜 阅读(540) 评论(0) 推荐(0) 编辑
摘要:在内核中有不少地方内存分配不允许失败. 作为一个在这些情况下确保分配的方式, 内核 开发者创建了一个已知为内存池(或者是 "mempool" )的抽象. 一个内存池真实地只是一 类后备缓存, 它尽力一直保持一个空闲内存列表给紧急时使用. 一个内存池有一个类型 mempool_t ( 在 <linux 阅读全文
posted @ 2019-07-06 11:22 樊伟胜 阅读(847) 评论(0) 推荐(0) 编辑
摘要:是时候给个例子了. scullc 是一个简化的 scull 模块的版本, 它只实现空设备 -- 永久 的内存区. 不象 scull, 它使用 kmalloc, scullc 使用内存缓存. 量子的大小可在编译 时和加载时修改, 但是不是在运行时 -- 这可能需要创建一个新内存区, 并且我们不想处 理 阅读全文
posted @ 2019-07-06 11:21 樊伟胜 阅读(251) 评论(0) 推荐(0) 编辑
摘要:一个设备驱动常常以反复分配许多相同大小的对象而结束. 如果内核已经维护了一套相同 大小对象的内存池, 为什么不增加一些特殊的内存池给这些高容量的对象? 实际上, 内核 确实实现了一个设施来创建这类内存池, 它常常被称为一个后备缓存. 设备驱动常常不展 示这类的内存行为, 它们证明使用一个后备缓存是对 阅读全文
posted @ 2019-07-06 11:19 樊伟胜 阅读(226) 评论(0) 推荐(0) 编辑
摘要:GFP_DMA 和 GFP_HIGHMEM 都有一个平台相关的角色, 尽管对所有平台它们的使用都 有效. Linux 内核知道最少 3 个内存区: DMA-能够 内存, 普通内存, 和高端内存. 尽管通常地 分配都发生于普通区, 设置这些刚刚提及的位的任一个请求从不同的区来分配内存. 这个 想法是, 阅读全文
posted @ 2019-07-06 11:17 樊伟胜 阅读(221) 评论(0) 推荐(0) 编辑
摘要:记住 kmalloc 原型是: #include <linux/slab.h> void *kmalloc(size_t size, int flags); 给 kmalloc 的第一个参数是要分配的块的大小. 第 2 个参数, 分配标志, 非常有趣, 因 为它以几个方式控制 kmalloc 的行为 阅读全文
posted @ 2019-07-06 11:15 樊伟胜 阅读(1169) 评论(0) 推荐(0) 编辑
摘要:#include <linux/wait.h> long wait_event_interruptible_timeout(wait_queue_head_t *q, condition, signed long timeout); 使当前进程在等待队列进入睡眠, 安装一个以 jiffies 表达的 阅读全文
posted @ 2019-07-06 11:14 樊伟胜 阅读(496) 评论(0) 推荐(0) 编辑
摘要:#include <linux/param.h> HZ HZ 符号指定了每秒产生的时钟嘀哒的数目. #include <linux/jiffies.h> volatile unsigned long jiffies; u64 jiffies_64; jiffies_64 变量每个时钟嘀哒时被递增; 阅读全文
posted @ 2019-07-06 11:13 樊伟胜 阅读(129) 评论(0) 推荐(0) 编辑
摘要:工作队列是, 表面上看, 类似于 taskets; 它们允许内核代码来请求在将来某个时间调用 一个函数. 但是, 有几个显著的不同在这 2 个之间, 包括: tasklet 在软件中断上下文中运行的结果是所有的 tasklet 代码必须是原子的. 相反, 工作队列函数在一个特殊内核进程上下文运行; 阅读全文
posted @ 2019-07-06 11:11 樊伟胜 阅读(303) 评论(0) 推荐(0) 编辑
摘要:tasklet 类似内核定时器在某些方面. 它们一直在中断时间运行, 它们一直运行在调度它 们的同一个 CPU 上, 并且它们接收一个 unsigned long 参数. 不象内核定时器, 但是, 你无法请求在一个指定的时间执行函数. 通过调度一个 tasklet, 你简单地请求它在以后 的一个由内 阅读全文
posted @ 2019-07-06 11:10 樊伟胜 阅读(321) 评论(0) 推荐(0) 编辑
摘要:内核提供给驱动许多函数来声明, 注册, 以及去除内核定时器. 下列的引用展示了基本的 代码块: #include <linux/timer.h> struct timer_list { /* ... */ unsigned long expires; void (*function)(unsigne 阅读全文
posted @ 2019-07-06 11:09 樊伟胜 阅读(776) 评论(0) 推荐(0) 编辑

上一页 1 ··· 3 4 5 6 7 8 9 10 11 下一页