驱动中的同步互斥阻塞之原子量

原创 2017年03月01日 18:46:21

目的:只能有一个app打开驱动程序


1.原子操作

原子操作指的是在执行过程中不会被别的代码路径所中断的操作

常用原子操作函数举例

atomic_v  v=ATOMIC_INIT(0);  //定义原子变量v并初始化为0

atomic_read(atomic_t *v); //返回原子变量的值

void atomic_inc(atomic_t *v);//原子变量增加1

void atomic_dec(atomic_t *v);//原子变量减少1

int atomic_dec_and_test(atomic_t *v);//自减操作后测试其是否为0,为0返回true,否则返回false


范例代码如下

#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <mach/gpio.h>
#include<linux/cdev.h>
#include <linux/poll.h>
int key_id;
struct cdev cdev;
dev_t devno;


static atomic_t canopen=ATOMIC_INIT(1); //定义原子变量,并初始化为1
static DECLARE_WAIT_QUEUE_HEAD(key_qaq);
/*等待队列头*/
/*中断事件标志,中断服务程序将它置为1,read函数将它置为0*/
unsigned int wait_val=0;
struct class *my_class;




static irqreturn_t key_func(int irq,void *dev_id)
{
key_id=(int)dev_id;


/*唤醒*/
wait_val=1;
wake_up_interruptible(&key_qaq);



return 0;
}


static int key_open(struct inode *inode,struct file *file)
{




if(!atomic_dec_and_test(&canopen))
{
atomic_inc(&canopen);
return -EBUSY;
}


request_irq(IRQ_EINT(16),key_func,IRQF_TRIGGER_FALLING,"k1",1);
request_irq(IRQ_EINT(17),key_func,IRQF_TRIGGER_FALLING,"k2",2);
request_irq(IRQ_EINT(18),key_func,IRQF_TRIGGER_FALLING,"k3",3);
request_irq(IRQ_EINT(19),key_func,IRQF_TRIGGER_FALLING,"k4",4);
request_irq(IRQ_EINT(24),key_func,IRQF_TRIGGER_FALLING,"k5",5);
request_irq(IRQ_EINT(25),key_func,IRQF_TRIGGER_FALLING,"k6",6);
request_irq(IRQ_EINT(26),key_func,IRQF_TRIGGER_FALLING,"k7",7);
request_irq(IRQ_EINT(27),key_func,IRQF_TRIGGER_FALLING,"k8",8);


return 0;
}


static int key_close(struct inode *inode,struct file *file)
{


atomic_inc(&canopen);
free_irq(IRQ_EINT(16),1);
free_irq(IRQ_EINT(17),2);
free_irq(IRQ_EINT(18),3);
free_irq(IRQ_EINT(19),4);
free_irq(IRQ_EINT(24),5);
free_irq(IRQ_EINT(25),6);
free_irq(IRQ_EINT(26),7);
free_irq(IRQ_EINT(27),8);


return 0;
}


ssize_t key_read(struct file *filp, char __user *buf, size_t size,loff_t *pos)
{
/*如果没有按键按下,休眠,让出CPU*/
wait_event_interruptible(key_qaq,wait_val);
/*如果有按键按下*/
copy_to_user(buf,&key_id,sizeof(key_id)); 
wait_val=0;


return 0;
}




static unsigned key_poll(struct file *file, poll_table *wait)
{
unsigned int mask=0;
poll_wait(file,&key_qaq,wait);/*不会立即休眠,只是挂在那个队列上面去*/
if(wait_val)
mask |= POLLIN | POLLRDNORM;


return mask;
}


static struct file_operations key_fops =
{
.owner = THIS_MODULE,
.open = key_open,
.release = key_close,
.read = key_read,
.poll = key_poll,
};




static int __init key_atomic_init(void)
{
cdev_init(&cdev,&key_fops);
alloc_chrdev_region(&devno, 0 , 1 , "mykey_atomic");
cdev_add(&cdev, devno, 1);
my_class = class_create(THIS_MODULE, "key_atomic_class");
if(IS_ERR(my_class))
{
printk("Err: failed in creating class.\n");
return -1;
}
device_create(my_class, NULL, devno,NULL,"key_atomic_driver");
return 0;
}


static void key_atomic_exit(void)
{
device_destroy(my_class,devno);
class_destroy(my_class);
cdev_del(&cdev);
unregister_chrdev_region(devno,1);
}


module_init(key_atomic_init);
module_exit(key_atomic_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("EIGHT_FIVE");






测试程序如下

#include<stdio.h>
#include<sys/ioctl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>


int main(int argv,char **argc)
{
int fd,buf;
fd=open("/dev/key_atomic_driver",0x666);
if(fd<0)
{
printf("can't open\n");
return -1;
}
while(1)
{


read(fd,&buf,4);
printf("key_val =%d\n",buf);
}


close(fd);
return 0;


}





linux字符驱动之同步互斥阻塞按键驱动

转自:http://www.cnblogs.com/liulipeng/p/3335533.html与http://blog.csdn.net/lwj103862095/article/details...
  • xishuang_gongzi
  • xishuang_gongzi
  • 2016年02月23日 16:21
  • 521

同步互斥阻塞

1. 原子操作 原子操作指的是在执行过程中不会被别的代码路径所中断的操作。 常用原子操作函数举例: atomic_t v = ATOMIC_INIT(0);     //定义原子变量v并初始化为...
  • ling459903347
  • ling459903347
  • 2014年05月13日 14:40
  • 439

6410之同步互斥阻塞

同步互斥: 目的:在同一时间只有一个应用程序打开设备节点/dev/buttons。linux是一个多任务系统,在读写同一个节点的时候,可能会有多个应用程序。这就需要进行同步操作,保证应用程序的完整执...
  • longshan_2009
  • longshan_2009
  • 2013年08月19日 11:46
  • 525

linux中原子量的学习和理解

原子量的理解 我们知道晶体管有两种状态,通电和不通电,对应着二进制存储中的1和0,这和开关的原理是一样的,不过开关可以由人来控制,而晶体管的状态是由电来控制的;我们可以利用一种特殊的门电路组合控制一...
  • ifired
  • ifired
  • 2016年09月25日 19:43
  • 329

linux设备驱动中的阻塞与非阻塞(一)

这两天在搞linux驱动的阻塞和非阻塞,困扰了两天,看了不少博客,有了点自己的想法,也不知是否对错,但还是写写吧,让各位大神给我指点指点。         首先说说什么是阻塞和非阻塞的概念:阻塞操作就...
  • u011756766
  • u011756766
  • 2015年11月23日 10:53
  • 1243

字符设备驱动程序之同步互斥阻塞

这一节要达到的目的---同一时刻,只能要一个app 打开 /dev/keys 设备文件。
  • ymangu
  • ymangu
  • 2014年09月22日 21:10
  • 513

Linux字符设备驱动之同步互斥阻塞

为了实现同一时绝对的只能有一个进程使用某个设备需要互斥机制,linux互斥机制有多种,如原子变量、互斥锁、信号量、自旋锁、读写锁等等。...
  • Lyanzh
  • Lyanzh
  • 2017年08月10日 10:07
  • 251

Linux中的同步问题(Linux驱动1)

操作系统中存在竞态问题,就是同时访问共享资源(包括程序,数据),引起竞态的原因有:smp,抢占式内核,中断(硬中断,软中断等). 抢占式内核竞态问题的图示: 假如代码如下: write(reso...
  • mmhhj
  • mmhhj
  • 2017年03月12日 11:29
  • 211

字符设备驱动-同步互斥阻塞

我们想来达到一个目的:同一时刻,只能有一个应用程序打开/dev/buttons 一般的,我们想达到目的会想到下面这种方法:static int canopen = 1; static int sixt...
  • czg13548930186
  • czg13548930186
  • 2017年09月04日 22:52
  • 263

字符设备驱动--异步通知、同步互斥阻塞

异步通知前面的字符设备驱动中,介绍了读取按键驱动程序的方法,存在一些不足之处: ①直接查询:耗资源 ②中断 :read()函数一直等待,无返回 ③poll: 指定超时时间 这三者都是应用程序主...
  • hello__xs
  • hello__xs
  • 2017年08月08日 23:32
  • 179
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:驱动中的同步互斥阻塞之原子量
举报原因:
原因补充:

(最多只允许输入30个字)