目的:同一时刻,只能有一个应用程序打开/dev/wq_button
1、方法一:使用设备打开标志(原子操作)
1、在驱动程序的open函数中增加一个标志,如果满足条件,则执行open函数中其余工作,如果不满足,则返回,增加代码如下:
if(!atomic_dec_and_test(&canopen))//自减操作并测试是否为零,如果为零返回 ture
{
atomic_inc(&canopen);//自增操作
return -EBUSY;
}
其中 canopen标志是原子变量,通过以下方式定义:
atomic_t canopen = ATOMIC_INIT(1);//定义原子变量,并初始化为1
atomic_dec_and_test是自减操作,并测试是否为零,如果为零则返回true,否则返回false
2、在驱动程序的close函数中添加如下代码:
atomic_inc(&canopen);//自增操作
将canopen标志加1,以使得这个设备下次还能够打开。
2、方法二:使用信号量
在程序操作之前需要申请这个信号量,如果能申请到这个信号量,则可以继续执行,操作完毕后要释放信号量,如果申请不到这个信号量,则可以返回或者休眠。
1、定义互斥锁
static DECLARE_MUTEX(button_lock);//定义互斥锁
2、在open函数中获得 信号量
static int button_dev_open(struct inode *inode ,struct file* file)
{
/*获取信号量*/
down(&button_lock);
//配置按键的引脚 GPF0,1,2,4为输入引脚
request_irq(IRQ_EINT1,buttons_irq, IRQ_TYPE_EDGE_BOTH,"key1",&pins_desc[0]);
request_irq(IRQ_EINT4,buttons_irq, IRQ_TYPE_EDGE_BOTH,"key2",&pins_desc[1]);
request_irq(IRQ_EINT2,buttons_irq, IRQ_TYPE_EDGE_BOTH,"key3",&pins_desc[2]);
request_irq(IRQ_EINT0,buttons_irq, IRQ_TYPE_EDGE_BOTH,"key4",&pins_desc[3]);
return 0;
}
dowm 函数用于获得信号量。
3、在close函数中释放信号量
int button_dev_close(struct inode* inode ,struct file *file)
{
free_irq(IRQ_EINT1,&pins_desc[0]);
free_irq(IRQ_EINT4,&pins_desc[1]);
free_irq(IRQ_EINT2,&pins_desc[2]);
free_irq(IRQ_EINT0,&pins_desc[3]);
/*释放信号量*/
up(&button_lock);
return 0;
}
up函数用于释放信号量
3、方法三:阻塞操作
1、阻塞操作:
在执行设备操作时如不能获得资源则挂起进程,直到满足可操作的条件后再进行操作;
被括起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足。
a、修改驱动程序代码,在open函数中增加对file中的参数进行判断
if(file->f_flags & O_NONBLOCK)
{
//非阻塞
if(down_trylock(&button_lock))//如果无法获取这个信号量
{
return EBUSY;
}
}
else
{
//阻塞
down(&button_lock);
}
b、在read函数中也增加对阻塞和非阻塞方式的判断
if(file->f_flags & O_NONBLOCK)//阻塞
{
if(!ev_press)
return -EAGAIN;
}
else//阻塞
{
/*如果没有按键动作发生 就休眠*/
wait_event_interruptible(button_wait_q,ev_press);
}
测试程序中默认的open函数是阻塞的。
在while(1)循环中一直read
2、非阻塞操作:
进程在不能进行设备操作时并不挂起,它或者放弃,或者不停的查询,直至可以进行操作为止
a、修改测试程序的open函数的参数
fd = open("/dev/wq_button", O_RDWR| O_NONBLOCK);//以非阻塞方式打开
在while(1)中稍加延时,防止打印的东西太多。
===============================================代码部分=======================================================
1、方法一:
驱动源代码:点击打开链接
测试程序源代码:点击打开链接
2、方法二:
驱动源代码:点击打开链接
测试程序源代码:点击打开链接
3、方法三:
驱动源代码:点击打开链接
测试程序源代码:点击打开链接