linux驅動程式中的互斥體
阿新 • • 發佈:2019-02-20
/* * g_mtex.c * * Created on: 2016年11月21日 * Author: chy */ #include <linux/types.h> #include <linux/stat.h> #include <linux/unistd.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/device.h> #include <linux/cdev.h> #include <linux/fcntl.h> #include <linux/io.h> #include <linux/slab.h> #include <linux/uaccess.h> #include <linux/mutex.h> #define Buff_size 1024 #define dev_num 2 struct g_mutex{ struct mutex mutex; char *buff; }; struct g_mutex *g_buf = NULL; static int open_file(struct inode *node,struct file *g_file) { int ret = 1; int minor = MINOR(node->i_rdev); if(minor < dev_num){ g_file->private_data = &g_buf[minor]; ret = 0; } printk(KERN_INFO"開啟檔案\n"); return ret; } static int close_file(struct inode *node,struct file *g_file) { return 0; } static ssize_t read_file(struct file *g_file,char __user *buf,size_t size,loff_t *offt) { int ret; loff_t ops = *offt; struct g_mutex *mutex = g_file->private_data; size_t count = size; if(ops >= strlen(mutex->buff) || ops >= Buff_size) return -1; if(ops + count > strlen(mutex->buff)) count = strlen(mutex->buff) - ops; mutex_lock(&mutex->mutex); //獲得互斥鎖 if(copy_to_user(buf,mutex->buff + ops,count)) ret = -EFAULT; else{ *offt += count; ret = count; } mutex_unlock(&mutex->mutex); //釋放互斥鎖 return ret; } static ssize_t write_file(struct file *g_file,const char __user *buf,size_t size,loff_t* offt) { int ret; loff_t ops = *offt; struct g_mutex *mutex = g_file->private_data; size_t count = size; if(ops >= Buff_size) return -1; if(Buff_size - ops > strlen(buf)) count = strlen(buf); else count = Buff_size - ops; mutex_lock(&mutex->mutex); //獲得互斥鎖 if(copy_from_user(mutex->buff + ops,buf,count)) //複製到使用者區 ret = -EFAULT; else{ *offt += count; ret = count; } mutex_unlock(&mutex->mutex); //釋放互斥鎖 return ret; } static long g_ioctl(struct file *g_file,unsigned cmd,unsigned long ctl) { struct g_mutex *mutex = g_file->private_data; switch(cmd){ case 0: mutex_lock(&mutex->mutex); //獲取互斥鎖 memset(mutex->buff, 0,sizeof(char) * Buff_size); mutex_unlock(&mutex->mutex); //釋放互斥鎖 break; default: return -EINVAL; } return 0; } struct file_operations file_ops = { .owner = THIS_MODULE, .open = open_file, .release = close_file, .read = read_file, .write = write_file, .unlocked_ioctl = g_ioctl, }; struct cdev dev = { .owner = THIS_MODULE, }; dev_t dev_no; struct class *dev_class = NULL; static int g_mutex_init(void) { int ret = 0; int i; ret = alloc_chrdev_region(&dev_no,0,dev_num,"g_mutex"); //申請裝置號 if(ret < 0) return ret; cdev_init(&dev,&file_ops); //初始化裝置 cdev_add(&dev,dev_no,dev_num); //向核心註冊裝置 g_buf = (struct g_mutex *)kmalloc(sizeof(struct g_mutex) * dev_num,GFP_KERNEL); //為虛擬裝置分配記憶體 if(!g_buf){ printk(KERN_INFO "記憶體分配失敗\n"); unregister_chrdev_region(dev_no,dev_num); return -ENOMEM; } for(i = 0; i < dev_num; i++){ g_buf[i].buff = (char *)kmalloc(sizeof(char) * Buff_size,GFP_KERNEL); memset(g_buf[i].buff,0,sizeof(char) * Buff_size); mutex_init(&(g_buf[i].mutex)); //初始化互斥變數 } /*建立裝置檔案*/ dev_class = class_create(THIS_MODULE,"mutex_device"); device_create(dev_class,0,MKDEV(MAJOR(dev_no),0),0,"mutex_dev_0"); device_create(dev_class,0,MKDEV(MAJOR(dev_no),1),0,"mutex_dev_1"); printk(KERN_INFO"載入\n"); return ret; } static void g_mutex_exit(void) { int i; cdev_del(&dev); //刪除cdev for(i = 0; i < dev_num; i++) kfree(g_buf[i].buff); kfree(g_buf); //釋放記憶體 /*刪除裝置檔案*/ device_destroy(dev_class, MKDEV(MAJOR(dev_no),0)); device_destroy(dev_class, MKDEV(MAJOR(dev_no),1)); class_destroy(dev_class); unregister_chrdev_region(dev_no,dev_num); //釋放裝置號 printk(KERN_INFO"解除安裝\n"); return; } MODULE_LICENSE("GPL v2"); module_init(g_mutex_init); module_exit(g_mutex_exit);//解除安裝