分析案例:要求LED设备同一时刻只能被一个应用软件打开(open)访问操作;
实施:
1.不管有多少个应用程序,只要访问LED设备,必须先open,最终都会调用到底层驱动的open函数;只需再底层驱动的open做相关的代码限定即可;
static int open_cnt = 1; //全局
static int led_open(struct inode *inode,
struct file *file)
{
if (--open_cnt != 0)
{
printk("设备已被打开!\n");
open_cnt++;
return -EBUSY; //出错,设备忙
}
printk("设备打开成功\n");
return 0;
}
static int led_close(struct inode *inode,
struct file *file)
{
open_cnt++;
return 0;
}
以上代码存在的漏洞:
研究的运算:"--open_cnt",对应汇编阶段,经过三步骤(读取,修改,写回);
正常的情况:
A进程先执行--open_cnt:
读取:open_cnt = 1;
修改,写回:open_cnt=0;
结果:打开设备成功
B进程再执行--open_cnt:
读取:open_cnt = 0;
修改,写回:open_cnt = -1;
结果:打开设备失败;
异常的情况:
A进程先执行--open_cnt:
读取:open_cnt = 1; //已经执行完毕
此时此刻,由于linux内核支持进程的抢占,发生了B进程抢占A进程的CPU资源,此时B进程开始执行
B进程开始执行--open_cnt:
读取:open_cnt = 1;
修改,写回:open_cnt = 0;
结果:打开设备成功;
B进程执行完毕,B进程释放CPU资源,A进程继续执行:
A进程接着执行:
修改,写回:open_cnt = 0;
结果:打开设备成功;
总结:发生以上异常的根本原因在于linux内核支持进程的抢占;