字符设备驱动第八课----互斥锁
2016-12-08 21:35
302 查看
概念
1.定义:
<include/linux/mutex.h>
struct mutex lock;//定义互斥锁
2.初始化:
mutex_init(mutex)
3.上锁:
/* * 功能:阻塞式上互斥锁,抢不到就一直阻塞 */ mutex_lock(struct mutex *lock)
/* * 功能:非阻塞式上互斥锁,抢不到也会返回往下走 * 返回值;成功抢到锁:1 没抢到锁:0 */ int mutex_trylock(struct mutex *lock);
/* * 功能:阻塞,可被中断 */ mutex_lock_interruptible(lock)
4.解锁:
void mutex_unlock(struct mutex *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/mutex.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 atomic_t tv; static struct mutex lock;//定义互斥锁 //打开设备 static int demo_open(struct inode *inode, struct file *filp) { //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(!atomic_dec_and_test(&tv)){ atomic_inc(&tv); return -EBUSY; } memset(kbuf, 0, KMAX); counter = 0; return 0; } //关闭设备 static int demo_release(struct inode *inode, struct file *filp) { //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__); atomic_inc(&tv); 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; int ret; //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=%dspinlock_t), %s : %s : %d\n", imajor(inode), iminor(inode), __FILE__, __func__, __LINE__); ret = mutex_lock_interruptible(&lock);//上互斥锁(可被中断打断) if(ret){ return ret; } if(counter < size){ size = counter; } if(copy_to_user(buf, kbuf, size)){ mutex_unlock(&lock);//解开互斥锁 return -EAGAIN; } mutex_unlock(&lock);//解开互斥锁 return size; } //写设备 static ssize_t demo_write(struct file *filp, const char __user *buf, size_t size, loff_t *offset) { int ret; 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__); ret = mutex_lock_interruptible(&lock);//上互斥锁(可被中断打断) if(ret){ return ret; } ssleep(30); if(size > KMAX){ mutex_unlock(&lock);//解开互斥锁 return -ENOMEM; } if(copy_from_user(kbuf, buf, size)){ mutex_unlock(&lock);//解开互斥锁 return -EAGAIN; } counter = size; mutex_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 mutex mutex_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");
相关文章推荐
- 字符设备驱动第八课---运用程序与驱动程序同步与互斥机制的对比
- linux字符设备驱动-同步互斥阻塞笔记
- 字符设备驱动--异步通知、同步互斥阻塞
- 字符设备驱动第八课----异步通知(信号驱动IO)
- Linux驱动学习5(详细分析字符设备驱动信号量实现互斥)
- 字符设备驱动-同步互斥阻塞
- arm 驱动基础:字符设备驱动程序之同步互斥阻塞
- 字符设备驱动第八课----自旋锁
- 07-S3C2440驱动学习(一)嵌入式linux字符设备驱动-按键驱动程序之异步通知机制+原子操作+互斥信号量+阻塞与非阻塞+定时器去抖
- 字符设备驱动第八课----信号量
- Linux字符设备驱动之同步互斥阻塞
- 字符设备驱动同步之互斥阻塞
- 字符设备驱动第八课------读写锁
- linux 设备驱动笔记 - 字符设备驱动
- 字符设备驱动之Buttons-等待队列
- 《LINUX设备驱动程序》学习之字符设备驱动实例
- 字符设备驱动之LED-平台设备驱动(platform设备驱动)
- linux字符设备驱动框架(一)
- 字符设备驱动之/proc/devices和/dev的关系
- linux字符设备驱动驱动流程