22:30-23:15 -p248
per-CPU 变量
当你创建一个per-CPU变量, 系统中每个处理器获得这个变量的副本。因而访问它不需要锁定。
对 get_cpu_var 的调用返回一个 lvalue 。因为是 lvalue,所以 它可被赋值给或者直接操作. 例如, 一个网络代码中的计数器时使用这 2 个语句来递增的:
get_cpu_var(sockets_in_use)++;
【什么是 lvalue?】
获取大的缓冲区
在引导式或的专用缓冲区
如果你真的需要一个大的物理上连续的缓冲, 最好的方法是在启动时请求内存来分配它.
一个设备驱动使用这种分配方法可以被安装或者替换只能通过重新编译内核并且重启计算机.
如果你必须使用启动时分配, 你需要直接连接你的驱动到内核
第九章 与硬件通信
驱动是软件概念和硬件电路之间的抽象层
I/O 端口和 I/O 内存
每个外设都是通过读写它的寄存器来控制. 大部分设备都有几个寄存器, 要么在内存地址空间,要么在 I/O 地址空间.
【什么是 内存地址空间,什么是 I/O 地址空间】
在硬件级别上, 内存区和 I/O 区域没有概念上的区别: 它们都是通过在地址总线和控制总线上发出电信号来存取(即, 读写信号)[32]并且读自或者写到数据总线.
I/O 寄存器和常规内存
程序员在访问 I/O 寄存器时必须小心避免被 CPU(或者编译器)优化所戏弄。
【怎样避免?】
由硬件自身缓存引起的问题,很好解决: 只要把底层硬件配置成,在访问I/O区域禁止任何硬件缓存即可.
由编译器优化导致的问题的解决办法是,使用下面的宏。
#include <linux/kernel.h>
void barrier(void)
使用 I/O 端口
I/O 端口分配
在尚未取得这些端口的独占访问之前,不应该操作他们。
内核提供了一个注册接口以允许你的驱动来声明它需要的端口. 这个接口中的核心的函数是 request_region:
#include <linux/ioport.h>
struct resource *request_region(unsigned long first, unsigned long n, const char *name);
不赞成使用 check_region, 因为它不是原子的。
操作 I/O 端口
在用户空间访问 I/O 端口
串操作
暂停式 I/O 端口
I/O 端口示例
04-06