1.spinlock可通过配置选项CONFIG_DEBUG_SPINLOCK来打开内核编译选项,进行自旋锁调试,作用有(多选):(参考:Linux内核设计与实现,第二版,第9章,9.2节)
A. 内核会检查是否使用了为初始化的锁
B. 内核会检测潜在的死锁
C. 检测是否在没有加锁的情况下对锁执行开锁操作
答案:A、C
试题解析:
spinlock自检只能做单一检查,而不能做动态交互式检查。参见 linux\lib\spinlock_debug.c
2.如果中断和进程上下文共享数据,且需要保存获取锁之前的中断状态,需要使用以下哪种自旋锁(单选):(参考:Linux内核设计与实现,第二版,第9章,9.2节)
A. spin_lock/spin_unlock
B. spin_lock_irqsave/spin_unlock_irqrestore
C. spin_lock_irq/spin_unlock_irq
D. spin_lock_bh/spin_unlock_bh
答案:B
试题解析:
spin_lock: 获取指定的自旋锁
spin_unlock:释放指定的锁
spin_lock_irqsave:保存本地中断的当前状态,禁止本地中断,并获取指定的锁
spin_lock_irqrestore:释放指定的锁,让本地中断恢复到以前状态
spin_lock_irq:禁止本地中断并获取指定的锁
spin_unlock_irq: 释放本地的锁,并激活本地中断
spin_lock_bh:禁止所有的下半部的执行,获取指定的锁
spin_unlock_bh: 释放指定的锁,并运行下半部执行
3.目前内核使用的自旋锁,描述错误的是(单选):(参考:http://www.ibm.com/developerworks/cn/linux/l-cn-spinlock/index.html)
A. 目前内核使用FIFO Ticket spinlock
B. 通过保存执行线程申请锁的顺序信息来解决“不公平”问题
C. 解决了线程优先级问题,即获取锁的高优先级线程会得到优先执行
D. 是在共享变量上自旋,变量改变时会导致缓存同步,从而加重系统总线流量,导致系统整体性能的降低
答案:C
试题解析:
在2.6.25之前,使用传统自旋锁:
传统自旋锁本质上为一个int型整数slock ,slock值为1代表锁未被占用;
typedef struct {
unsigned int slock;
} raw_spinlock_t;
获取自旋锁时,则将slock减1(原子操作),再检查EFLAGS寄存器的符号位,为0则获取自旋锁,为负则忙等待,测试slock与0的大小关系。
释放时,只需将slock置为1即可。
在2.6.25之后,使用FIFO ticket spinlock ,排队自旋锁,解决了不公平的问题:
通过保存执行线程申请锁的顺序信息来解决“不公平”问题。
排队自旋锁仍使用下面的数据结构:
typedef struct {
unsigned int slock;
} raw_spinlock_t;
但赋予 slock 域新的含义。为了保存顺序信息,slock 域被分成两部分,owner和next,分别保存锁持有者和未来锁申请者的票据序号(Ticket Number) 。
只有 Next 域与 Owner 域相等时,才表明锁处于未使用状态(类似于银行叫号系统)。
上面两种锁都未保存任务优先级的信息,FIFO ticket spinlock中,所有的任务都按时间先后顺序获取锁,先到先服务。
4.对于读写锁(rwlock),描述错误的是(单选):(参考:Linux内核设计与实现,第二版,第9章,9.3节)
A. 读写锁适合于对数据的访问由大量的读和少量的写操作来完成
B. 如果一个执行读操作的线程持有此锁,那么多个读线程都可以进入临界段
C. 允许多个线程同时访问相同数据,但同一时刻只允许一个线程写入数据
D. 如果执行写操作的线程持有此锁,则临界段可以由其他线程读取
答案:D
试题解析:
首先介绍下读写锁概念:
读锁:用于保护读取的锁;例如:对于一个链表需要检索时,可以通过读锁进行数据保护,防止读取过程中链表被修改。读锁的特点是支持并发,允许多个任务并发持有读锁;
写锁:用于保护写入的锁;例如:对于一个链表需要更新时,通过获取写锁,保证数据不被访问或读取。写锁的特点是独占性,写锁最多只能被一个写任务持有,而且不能由并发的读操作;
临界段是指代码中收到锁保护的代码段,例如:
lock_读
临界段(只读)
unlock_读
因此根据写锁的特性,得出答案为:D
5.对于内核互斥锁(mutex),对其使用方法,错误的是(单选):(参考:内核代码2.6.32 mutex.h)
A. 同一时间只能有一个任务持有互斥锁,而且只有这个任务可以对互斥锁进行解锁
B. 互斥锁不能进行递归锁定或解锁
C. mutex可以通过直接赋值的方式对其count进行初始化
D. 互斥锁可能不能用于硬中断或者软中断上下文中,如tasklet
答案:C.
试题解析:
mutex的行为和使用计数为1的信号量类似,但它不同与信号量,mutex的使用场景相对而言更严格、更定向:
1. 任何时刻中只有一个任务可以持有mutex,也就是mutex的使用计数永远是1。
2. 给mutex上锁者必须负责给其解锁。
3. 不允许递归的上锁和解锁。
4. mutex不能在中断或者下半部中使用,即使使用mutex_trylock()也不行。
5. mutex只能通过官方API管理:不可被拷贝、手动初始化或者重复初始化。其count是定义为automic_t原子型变量,因此只能通过原子操作来对其count进行初始化,因此C错误。