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

先了解几个概念:临界资源:一次只允许一个执行单元使用的资源称为临界资源。比如多台电脑都可以使用同一台打印机,但是,一个时刻只能有一台电脑来控制他进行打印,所以打印机在这里就是临界资源。临界区:访问共享资源的代码区域。就是执行单元访问共享资源的那段代码就对啦。并发:就是几个进程一起执行。竞态:几个进程同时访问共享资源时发生(上面之所以说是执行单元,不说进程是因为还有线程的存在)什么叫进程的同步?百度一下:我们把异步环境下的一组并发进程因直接制约而互相发送消息、进行互相合作、互相等待,使得各进程按一定的速度执行的过程称为进程间的同步。我的理解就是:进程之间步伐一致,他们之间能够有配合的工作。进程之间同步的实现需要一些规则来协调,通常比如:互斥、阻塞。一、互斥:同一时刻只能有一个App打开某个设备或访问某个资源实现互斥的技巧:(1)原子操作驱动程序的任务:①设置原子变量的值atomic_t v = ATOMIC_INIT(1);//定义原子变量v初始化为1②在即将访问临界资源前设定“使用中”标记,通常是:if (!atomic_dec_and_test(&canopen)){atomic_inc(&canopen);printk("Using now!\n");return -EBUSY;}③在不使用资源时要将标记改成“未使用”atomic_inc(&canopen);//释放原子变量代码实现:

atomic.c文件

#include <linux/delay.h>#include <linux/irq.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <linux/module.h>#include <linux/device.h> //class_create#include <mach/regs-gpio.h>//S3C2410_GPF1 #include <mach/hardware.h>#include <linux/interrupt.h> //wait_event_interruptible#include <linux/fs.h>#include <arch/arm/include/asm/atomic.h>/* 定义并初始化等待队列头 */static DECLARE_WAIT_QUEUE_HEAD(button_waitq);////////////////////////////////////////////////////////////////////////static atomic_t canopen = ATOMIC_INIT(1);//定义原子变量并初始化为1////////////////////////////////////////////////////////////////////////static struct class *buttondev_class;static struct device *buttons_device;static struct pin_desc{unsigned int pin;unsigned int key_val;};static struct pin_desc pins_desc[4] = {{S3C2410_GPF1,0x01}, //S3C2410_GPF1是对GPF1引脚这种“设备”的编号dev_id{S3C2410_GPF4,0x02},{S3C2410_GPF2,0x03},{S3C2410_GPF0,0x04},}; static int ev_press = 0;static unsigned char key_val;int major;/* 中断处理函数 */static irqreturn_t handle_irq(int irq, void *dev_id){struct pin_desc *irq_pindesc = (struct pin_desc *)dev_id;//unsigned int pinval;pinval = s3c2410_gpio_getpin(irq_pindesc->pin);//获取按键值:有按键按下返回按键值0/* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 *//* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 */if(pinval){/* 松开 */key_val = 0x80 | (irq_pindesc->key_val);}else{/* 按下 */key_val = irq_pindesc->key_val;}ev_press = 1;/* 表示中断已经发生 */wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */return IRQ_HANDLED;}static int buttons_dev_open(struct inode * inode, struct file * filp){/////////////////////////////////////////////////////////////实现互斥:原子操作if (!atomic_dec_and_test(&canopen)){atomic_inc(&canopen);printk("dev is using now!\n");return -EBUSY;}///////////////////////////////////////////////////////////request_irq(IRQ_EINT1, handle_irq, IRQ_TYPE_EDGE_FALLING, "K1",&pins_desc[0]);request_irq(IRQ_EINT4, handle_irq, IRQ_TYPE_EDGE_FALLING, "K2",&pins_desc[1]);request_irq(IRQ_EINT2, handle_irq, IRQ_TYPE_EDGE_FALLING, "K3",&pins_desc[2]);request_irq(IRQ_EINT0, handle_irq, IRQ_TYPE_EDGE_FALLING, "K4",&pins_desc[3]);return 0;}static int buttons_dev_close(struct inode *inode, struct file *file){//////////////////////////////////////////////////////////////atomic_inc(&canopen);//释放原子变量//////////////////////////////////////////////////////////////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]);return 0;}static ssize_t buttons_dev_read(struct file *file, char __user *user, size_t size,loff_t *ppos){if (size != 1)return -EINVAL;wait_event_interruptible(button_waitq, ev_press);//没有按键就进入休眠copy_to_user(user, &key_val, 1);/* 将ev_press清零 */ev_press = 0;return 1;}/* File operations struct for character device */static const struct file_operations buttons_dev_fops = {.owner= THIS_MODULE,.open= buttons_dev_open,.read= buttons_dev_read,.release = buttons_dev_close,};/* 驱动入口函数 */static int buttons_dev_init(void){/* 主设备号设置为0表示由系统自动分配主设备号 */major = register_chrdev(0, "buttons_dev", &buttons_dev_fops);/* 创建buttondev类 */buttondev_class = class_create(THIS_MODULE, "buttondev");/* 在buttondev类下创建buttons设备,供应用程序打开设备*/buttons_device = device_create(buttondev_class, NULL, MKDEV(major, 0), NULL, "buttons");//return 0;}/* 驱动出口函数 */static void buttons_dev_exit(void){unregister_chrdev(major, "buttons_dev");device_unregister(buttons_device); //卸载类下的设备class_destroy(buttondev_class);//卸载类}/* 模块加载和卸载函数的修饰 */module_init(buttons_dev_init); module_exit(buttons_dev_exit); MODULE_AUTHOR("CLBIAO");MODULE_DESCRIPTION("Just for Demon");MODULE_LICENSE("GPL"); //遵循GPL协议测试程序:

app_atomic.c

诚实是人生绝妙的法宝。虽然对人诚实,

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

相关文章:

你感兴趣的文章:

标签云: