信号量
1.所谓信号量也是资源共享条件下保护资源的一种手段,当定义一个信号量时,这个信号量就相当于一个互斥锁,只能属于一个进程,我们把之前同一设备同一时刻只能由一个进程打开的原子变量操作改成信号量。
代码如下:
static DECLARE_MUTEX(button_lock); //定义互斥锁 ,该宏默认定义一个信号量
static int s3c24xx_open(struct inode *inode, struct file *file)
{
/* 获取信号量 */
down(&button_lock);
request_irq(IRQ_EINT0, key_handle, IRQT_BOTHEDGE,"s0", &key_arr[0]);
request_irq(IRQ_EINT2, key_handle, IRQT_BOTHEDGE,"s1", &key_arr[1]);
request_irq(IRQ_EINT11, key_handle, IRQT_BOTHEDGE,"s2", &key_arr[2]);
request_irq(IRQ_EINT19, key_handle, IRQT_BOTHEDGE,"s3", &key_arr[3]);
return 0;
}
int s3c24xx_close(struct inode *inode, struct file *file)
{
free_irq(IRQ_EINT0, &key_arr[0]);
free_irq(IRQ_EINT2, &key_arr[1]);
free_irq(IRQ_EINT11, &key_arr[2]);
free_irq(IRQ_EINT19, &key_arr[3]);
up(&button_lock); //释放信号量
return 0;
}
两次打开同一设备文件,可以看到758是活动进程,759睡眠着
杀死758进程,会释放信号量,从而唤醒759进程
总结:所以,信号量其实就代表着互斥锁,当某个进程获取到这个信号量时,其他进程就只能进入休眠状态,只有当该信号量被之前占用的进程释放后,当前进程才能被唤醒获取到信号量,所以这就很好对共享资源进行了保护。
阻塞和非阻塞
所谓阻塞就是当调用某个函数或进行某种操作时,如果没有结果就会一直等着,直到有结果返回。非阻塞则没有结果就会立即返回,不会一直等结果。对于上面的程序进行非阻塞操作。
代码如下:
首先在应用程序的open函数里加上O_NONBLOCK非阻塞标志
int main(int argc, char **argv) {
int fd;
int ret;
int val;
fd = open("/dev/key", O_RDWR | O_NONBLOCK);
if (fd < 0)
{
printf("can't open!\n");
}
while (1)
{
ret = read(fd, &val, 1);
printf("key_val: 0x%x, ret = %d\n", val, ret);
sleep(5);
}
return 0;
}
其次,需要在open和read函数里根据O_NONBLOCK标志进行判断,open函数里,如果是非阻塞的,则调用down_trylock获取信号量,down_trylock获取不到就会直接返回,不会一直等待。
read函数里,如果是非阻塞并且没有按键时,就立即返回。
```c
static int s3c24xx_open(struct inode *inode, struct file *file)
{
if (file->f_flags & O_NONBLOCK)
{
if (down_trylock(&button_lock))
return -1;
}
else
{
/* 获取信号量 */
down(&button_lock);
}
request_irq(IRQ_EINT0, key_handle, IRQT_BOTHEDGE,"s0", &key_arr[0]);
request_irq(IRQ_EINT2, key_handle, IRQT_BOTHEDGE,"s1", &key_arr[1]);
request_irq(IRQ_EINT11, key_handle, IRQT_BOTHEDGE,"s2", &key_arr[2]);
request_irq(IRQ_EINT19, key_handle, IRQT_BOTHEDGE,"s3", &key_arr[3]);
return 0;
}
static ssize_t s3c24xx_read(struct file *file, char __user *buf, size_t len, loff_t *ps){
if(len != 1){
printk("s3c24xx_read param err!");
return -1;
}
if (file->f_flags & O_NONBLOCK)
{
if (!ev_press)
return -EAGAIN;
}
else
{
/* 如果没有按键动作, 休眠 */
wait_event_interruptible(button_waitq, ev_press);
}
copy_to_user(buf, &key_val, 1);
ev_press = 0;
return 1;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/50475ebec87d49f188183107ff093ee6.png)
当执行应用程序时,此时没有按键值时也会立即返回,打印ret。