Linux内核设计与实现——内核同步方法

内核同步

1. 原子操作

内核提供了两组原子操作接口——一组针对整数进行操作,另一组针对单独的位进行操作。有些体系结构缺少简单的原子操作指令,但也为单步执行提供了锁内存总线的指令,确保其他改变内存的操作不能同时发生。

(1) 原子整数操作

  1. 针对整数的原子操作只能对atomic_t类型的数据进行处理。之所以引入一个特殊数据类型,主要是因为:首先,让原子函数只接收atomic_t类型的操作数,确保原子操作只与这种特殊类型数据一起使用,同时也保证了该类型的数据不会被传递给非原子函数;其次,使用atomic_t类型确保编译器不对相应的值进行访问优化——使得原子操作最终接收到正确的内存地址;最后,在不同体系结构上实现原子操作的时候,使用atomic_t可以屏蔽其间的差异。atomic_t类型定义在<linux/types.h>中:
typedef struct {
   
		volatile int counter;
} atomic_t;
  1. 定义一个atomic_t类型的数据,还可以在定义时给它设定初值:
atomic_t v;					  /* 定义v */
atomic_t u = ATOMIC_INIT(0);  /* 定义u并把它初始化为0 */
  1. 使用原子整型操作需要的声明都在<asm/atomic.h>中。表10-1列出了所有的标准原子整数操作。有些体系结构会提供一些只能在该体系结构上使用的额外原子操作方法,也可以在<asm/atomic.h>中找到。
    在这里插入图片描述
  2. 原子操作通常是内联函数,往往是通过内嵌汇编指令来实现的。如果某个函数本来就是原子的,那它往往会被定义成一个宏。例如,在大部分体系结构上,读取一个字本身就是一种原子操作,所以在对一个字进行写入操作期间不可能完成对该字的读取。把atomic_read()定义成一个宏,返回atomic_t类型的整数值:
/**
 * atomic_read - read atomic variable
 * @v: pointer of type atomic_t
 *
 * Atomically reads the value of @v.
 */
static inline int atomic_read(const atomic_t *v)
{
   
		return v->counter;
}

(2) 64位原子操作

  1. atomic_t一样,atomic64_t类型其实是对长整型的一个简单封装类:
typedef struct {
   
		volatile long counter;
} atomic64_t;
  1. 表10-2是所有标准原子操作列表。
    在这里插入图片描述
    (3) 原子位操作

  2. 内核提供了一组针对位这一级数据进行操作的函数,它们是与体系结构相关的操作,定义在<asm/bitops.h> 中。

  3. 位操作函数是对普通的内存地址进行操作的,所以没有特殊的数据类型。它的参数是一个指针和一个位号,第0位是给定地址的最低有效位。在32位机上,第31位是给定地址的最高有效位,而第32位是下一个字的最低有效位。

  4. 在表10-3中给出了标准原子位操作列表。可以把原子位指令与一般的C语句混在一起。
    在这里插入图片描述

  5. 内核还提供了一组与上述操作对应的非原子位函数。非原子位函数与原子位函数的操作完全相同,其名字前缀多两个下划线。例如,与test_bit()对应的非原子形式是__test_bit()。如果不需要原子性操作(比如已经用锁保护了数据),那么这些非原子的位函数相比原子的位函数可能会执行得更快些。

  6. 内核还提供了两个例程用来从指定的地址开始搜索第一个被设置(或未被设置)的位:

int find_first_bit(unsigned long *addr, unsigned int size)
int find_first_zero_bit(unsigned long *addr, unsigned int size)

​ 这两个函数中第一个参数是一个指针,第二个参数是要搜索的总位数,返回值分别是第一个被设置的(或没被设置的)位的位号。如果 搜索范围仅限于一个字,使用_ffs()_ffz()更好,只需要给定一个要搜索的地址做参数。

2. 自旋锁

(1) 自旋锁方法

  1. 自旋锁的实现和体系结构密切相关,代码往往通过汇编实现。与体系结构相关的代码定义在<asm/spinlock.h>中,实际用到的接口定义在<linux/spinlock.h>中。自旋锁的基本使用形式如下:
DEFINE_SPINLOCK(mr_1ock);
spin_lock(&mr_lock);
/*临界区...*/
spin_unlock(&mr_lock);
  1. 自旋锁可以使用在中断处理程序中(此处不能使用信号量,因为它们会导致睡眠)。在中断处理程序中使用自旋锁时,要在获取锁之前先禁止本地中断(在当前处理器上的中断请求)。需

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值