字符设备驱动第八课----自旋锁
2016-12-08 21:17
183 查看
概述
1、出处:
源码目录下include/linux/spinlock.h
static spinlock_t lock;//定义一个自旋锁
2.初始化:
spin_lock_init(_lock)
3.锁定:
spin_lock(&lock)
4.解锁:
spin_unlock(&lock)
工程实例
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/errno.h> #include <asm/current.h> #include <linux/sched.h> #include <linux/uaccess.h> #include <asm/atomic.h> #include <linux/spinlock.h> #include <linux/delay.h> #include <linux/device.h> static struct class *cls = NULL; #include "mycmd.h" static int major = 0; static int minor = 0; const int count = 6; #define DEVNAME "demo" static struct cdev *demop = NULL; #define KMAX 1024 static int counter = 0; static char kbuf[KMAX]; static spinlock_t lock;//定义一个自旋锁 //打开设备 static int demo_open(struct inode *inode, struct file *filp) { memset(kbuf, 0, KMAX); counter = 0; return 0; } //关闭设备 static int demo_release(struct inode *inode, struct file *filp) { return 0; } //读设备 //ssize_t read(int fd, void *buf, size_t count) static ssize_t demo_read(struct file *filp, char __user *buf, size_t size, loff_t *offset) { struct inode *inode = filp->f_path.dentry->d_inode; spin_lock(&lock);//上自旋锁,因为buf,kbuf,count都是临界资源,可能造成竞争 if(counter < size){ size = counter; } if(copy_to_user(buf, kbuf, size)){ spin_unlock(&lock); //解开自旋锁 return -EAGAIN; } counter = 0; spin_unlock(&lock);//若拷贝不成功,也得解锁,因为上面加了锁 return size; } //写设备 static ssize_t demo_write(struct file *filp, const char __user *buf, size_t size, loff_t *offset) { struct inode *inode = filp->f_path.dentry->d_inode; //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n", current->comm, current->pid, __FILE__, __func__, __LINE__); //get major and minor from inode printk(KERN_INFO "(major=%d, minor=%d), %s : %s : %d\n", imajor(inode), iminor(inode), __FILE__, __func__, __LINE__); if(size > KMAX){ return -ENOMEM; } spin_lock(&lock);//上自旋锁,因为buf,kbuf,count都是临界资源,可能造成竞争 ssleep(30); if(copy_from_user(kbuf, buf, size)){ spin_unlock(&lock);//解开自旋锁 return -EAGAIN; } counter = size; spin_unlock(&lock);//若拷贝不成功,也得解锁,因为上面加了锁 return counter; } /* * read/write param * read status * contrl device */ static long demo_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { static struct karg karg = { .kval = 0, .kbuf = {0}, }; struct karg *usrarg; switch(cmd){ case CMDON: printk(KERN_INFO "CMDON: %s : %s : %d\n", __FILE__, __func__, __LINE__); break; case CMDOFF: printk(KERN_INFO "CMDOFF: %s : %s : %d\n", __FILE__, __func__, __LINE__); break; case CMDR: printk(KERN_INFO "CMDR: %s : %s : %d\n", __FILE__, __func__, __LINE__); if(_IOC_SIZE(cmd) != sizeof(karg)){ return -EINVAL; } usrarg = (struct karg *)arg; if(copy_to_user(usrarg, &karg, sizeof(karg))){ return -EAGAIN; } printk(KERN_INFO "CMDR: %s : %s : %d ---done.\n", __FILE__, __func__, __LINE__); break; case CMDW: printk(KERN_INFO "CMDW: %s : %s : %d\n", __FILE__, __func__, __LINE__); if(_IOC_SIZE(cmd) != sizeof(karg)){ return -EINVAL; } usrarg = (struct karg *)arg; if(copy_from_user(&karg, usrarg, sizeof(karg))){ return -EAGAIN; } printk(KERN_INFO "CMDW: %d : %s\n", karg.kval, karg.kbuf); break; default: ; }; return 0; } static struct file_operations fops = { .owner = THIS_MODULE, .open = demo_open, .release= demo_release, .read = demo_read, .write = demo_write, .unlocked_ioctl = demo_ioctl, }; static int __init demo_init(void) { dev_t devnum; int ret, i; struct device *devp = NULL; //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d\n", current->comm, current->pid, __FILE__, __func__, __LINE__); //1. alloc cdev obj demop = cdev_alloc(); if(NULL == demop){ return -ENOMEM; } //2. init cdev obj cdev_init(demop, &fops); ret = alloc_chrdev_region(&devnum, minor, count, DEVNAME); if(ret){ goto ERR_STEP; } major = MAJOR(devnum); //3. register cdev obj ret = cdev_add(demop, devnum, count); if(ret){ goto ERR_STEP1; } cls = class_create(THIS_MODULE, DEVNAME); if(IS_ERR(cls)){ ret = PTR_ERR(cls); goto ERR_STEP1; } for(i = minor; i < (count+minor); i++){ devp = device_create(cls, NULL, MKDEV(major, i), NULL, "%s%d", DEVNAME, i); if(IS_ERR(devp)){ ret = PTR_ERR(devp); goto ERR_STEP2; } } // init atomic_t atomic_set(&tv, 1); // init spinlock spin_lock_init(&lock); //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - ok.\n", current->comm, current->pid, __FILE__, __func__, __LINE__); return 0; ERR_STEP2: for(--i; i >= minor; i--){ device_destroy(cls, MKDEV(major, i)); } class_destroy(cls); ERR_STEP1: unregister_chrdev_region(devnum, count); ERR_STEP: cdev_del(demop); //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - fail.\n", current->comm, current->pid, __FILE__, __func__, __LINE__); return ret; } static void __exit demo_exit(void) { int i; //get command and pid printk(KERN_INFO "(%s:pid=%d), %s : %s : %d - leave.\n", current->comm, current->pid, __FILE__, __func__, __LINE__); for(i=minor; i < (count+minor); i++){ device_destroy(cls, MKDEV(major, i)); } class_destroy(cls); unregister_chrdev_region(MKDEV(major, minor), count); cdev_del(demop); } module_init(demo_init); module_exit(demo_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Farsight"); MODULE_DESCRIPTION("Demo for kernel module");
相关文章推荐
- 字符设备驱动第八课----异步通知(信号驱动IO)
- 字符设备驱动第八课------读写锁
- 字符设备驱动第八课----互斥锁
- 字符设备驱动第八课----信号量
- 字符设备驱动第八课---运用程序与驱动程序同步与互斥机制的对比
- linux驱动学习之字符设备驱动模板
- Linux高级字符设备驱动 poll方法(select多路监控原理与实现)
- linux驱动开发--字符设备:信号量
- Linux字符设备驱动开发基础
- 字符设备驱动程序开发之基于中断的按键驱动加去抖动
- linux 字符设备驱动写法
- linux内核字符设备驱动之发送命令接口
- Linux字符设备驱动入门(二)——加入ioctl功能
- LINUX字符设备驱动学习
- Linux设备驱动程序设计(三)----Linux的特殊字符设备:混杂设备,依旧让LED闪烁起来
- 字符设备驱动之按键中断——FS2410
- 字符设备驱动编写步骤
- 字符设备驱动框架3:深入探讨—完整的驱动代码工程
- linux设备驱动开发学习之旅--支持多设备的字符设备驱动
- 基于mini6410的linux驱动学习总结(二 字符设备与块设备的区别)