linux驱动程序之同步、互斥、阻塞

目的:同一时刻,只能有一个应用程序打开/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、方法三:

驱动源代码:点击打开链接

测试程序源代码:点击打开链接






你可能感兴趣的:(嵌入式系统)