《深入理解linux内核》边读边说-内存寻址(一)

内存地址

内存地址有三种类型:逻辑地址,线性地址,物理地址。
逻辑地址:常见程序所表示的地址就是逻辑地址。比如MS-DOS程序设计时使用DS:EAX,CS:IP等地址都是逻辑地址。此类地址把地址分为段偏移的模式来把程序分为若干段。在逻辑地址层面上可以把内存看为若干个段来分开的空间。
线性地址:线性地址是32位整数。是逻辑地址通过分段单元转换后的结果。在线性地址上可以把内存看为0×00000000到0xfffffff的线性空间。
物理地址:芯片级寻址用的地址。与地址总线上的电信号对应。

刚开始突然接触三种地址有点晕,可以这么理解:
比如把内存比喻成几本书落在一起。
逻辑地址的模式是,第X本书的第Y页的内容。
线性地址的模式是:从头数,第XX页的内容。
物理地址的模式是:从头开始测量第N毫米的页的内容。
虽然这种比喻在后面的说实际工作模式的时候会发现不太正确。但是现在对于理解三种地址还是有些帮助的。
CPU和内存真正进行数据交换的时候需要使用物理地址,而一般程序所使用的是逻辑地址。可能会有疑问为什么会进行两次转换,而不是一次转换搞定的策略,这个问题在接下来的分析中会浮出水面。

[阅读全文] »

LDD读书笔记第十章-中断处理

当硬件需要处理器关注时(如硬盘读取完成,通知可以继续读取其他内容。),产生某个事件通知处理器。这种机制叫做中断。一个中断仅仅是个信号。

准备并口

在没有设定产生中断之前,设备不会产生中断。
对于并口标准来说设置端口2(0x37a:0×378+2,0x27a:0×278+2或者其他)的第四位来启用中断报告,初始化的时候用outb莱斯设置这个位。
中断启用时,每当引脚10(ACK)位的电平发生从底到高改变时,并口就会产生一个中断。

[阅读全文] »

LDD读书笔记第七章-时间、延迟及延缓操作

度量时间差

在linux/param.h中定义HZ值,表示每秒发生时钟中断的频率。
内核时钟计数器:jiffies_64。
内核使用jiffies变量是unsigned log类型。
可能是jiffies_64的值也可能是其底32位。

使用jiffies计数器

头文件:linux/jiffies.h
jiffies变量被声明为volatile防止编译时优化。
[阅读全文] »

LDD读书笔记第五章-并发和竞态(二)

锁陷阱

不明确的规则:每个线程不能第二次尝试获得该锁。
锁的顺序规则:保证每个线程都以相同的顺序获得锁。
锁的粒度对比:粗粒度锁会导致竞争严重,细粒度锁会导致额外的开销和给维造成副作用

除了锁之外的方法

免锁算法

大量的读取者,只有一个写入者可以使用免锁算法。
免锁算法类似于循环队列(个人理解)。

原子变量

原子变量执行速度非常块。
只要有可能编译器会把对原子变量的操作编译成单条指令。
[阅读全文] »

LDD读书笔记第五章-并发和竞态(一)

linux信号量的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <asm /semaphore.h>  /*信号量相关头文件*/
struct semaphore		/*信号量相关结构体*/
/*初始化相关函数*/
void  sema_init(struct semaphore *sem,int val); 
/*初始化信号量函数*/
DECLARE_MUTEX(name);	/*创建互斥体并初始化为1*/
DECLARE_MUTEX_LOCKED(name);	/*创建互斥体并初始化为0*/
void init_MUTEX(struct semaphore *sem); /*初始化互斥体为1*/
void init_MUTEX_LOCKED(struct semaphore *sem); /*初始化互斥体为0*/
/*down&up 相关函数*/
void down(struct semaphore *sem); /*不可中断*/
int down_interruptible(struct semaphore *sem); /*可中断*/
int down_trylock(struct semaphore *sem); /*立即退出*/
void up(struct semaphore *sem); /*释放信号量*/
</asm>

down_trylock函数在获取信号量失败时立即退出而不会等待。成功返回0,失败返回非零值。

读取者/写入者信号量

读取者/写入者信号量允许有一个写入者和无穷多个读取者。
当只需要读取数据时使用读取者信号量,仅当需要写入数据时获得写入者信号量。
[阅读全文] »