尽管信号量已经可以实现互斥的功能,而且包含DECLARE_MUTEX()、init_MUTEX ()等定义信号量的宏或函数,从名字上看就体现出了互斥体的概念,但是mutex在Linux内核中还是真实地存在的。 下面代码定义名为my_mutex的互斥体并初始化它。 - struct mutex my_mutex;
- mutex_init(&my_mutex);
复制代码下面的两个函数用于获取互斥体。 - void fastcall mutex_lock(struct mutex *lock);
- int fastcall mutex_lock_interruptible(struct mutex *lock);
- int fastcall mutex _trylock(struct mutex *lock);
复制代码mutex_lock()与mutex_lock_interruptible()的区别和down()与down_interruptible()的区别完全一致,前者引起的睡眠不能被信号打断,而后者可以。mutex_trylock()用于尝试获得mutex,获取不到mutex时不会引起进程睡眠。 下列函数用于释放互斥体。 - void fastcall mutex_unlock(struct mutex *lock);
复制代码mutex的使用方法和信号量用于互斥的场合完全一样,如下所示: - struct mutex my _ mutex; //定义 mutex
- mutex _ init(&my _ mutex); //初始化 mutex
- mutex _ lock(&my _ mutex); //获取 mutex
- ...//临界资源
- mutex _ unlock(&my _ mutex); //释放 mutex
复制代码 将globalmem驱动中添加互斥体,对应驱动源码如下: - #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/fs.h>
- #include <linux/errno.h>
- #include <linux/cdev.h>
- #include <linux/slab.h>
- #include <linux/device.h>
- #include <asm/uaccess.h>
- #define GLOBALMEM_SIZE 0x1000 /*全局内存最大4KB*/
- #define MEM_CLEAR 0x1 /*清零全局内存*/
- static int globalmem_major;
- static struct class *cdev_class;
- /*globalmem 设备结构体*/
- struct globalmem_dev
- {
- struct cdev cdev; /*cdev 结构体*/
- unsigned char mem[GLOBALMEM_SIZE]; /*全局内存*/
- struct mutex x4412_mutex;
- };
- struct globalmem_dev *globalmem_devp; /*设备结构体指针*/
- /*文件打开函数*/
- int globalmem_open(struct inode *inode, struct file *filp)
- {
- /*将设备结构体指针赋值给文件私有数据指针*/
- filp->private_data = globalmem_devp;
- return 0;
- }
- /*文件释放函数*/
- int globalmem_release(struct inode *inode, struct file *filp)
- {
- return 0;
- }
- /* ioctl 设备控制函数 */
- static long globalmem_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
- {
- struct globalmem_dev *dev = filp->private_data;/*获得设备结构体指针*/
- switch(cmd)
- {
- case MEM_CLEAR:
- if(mutex_lock_interruptible(&dev->x4412_mutex))
- {
- return -ERESTARTSYS;
- }
- memset(dev->mem, 0, GLOBALMEM_SIZE);
- mutex_unlock(&dev->x4412_mutex);
- printk(KERN_INFO "globalmem is set to zero\n");
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- /*读函数*/
- static ssize_t globalmem_read(struct file *filp, char __user *buf,size_t size,loff_t *ppos)
- {
- unsigned long p = *ppos;
- unsigned int count = size;
- int ret = 0;
- struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/
- /*分析和获取有效的写长度*/
- if (p >= GLOBALMEM_SIZE)
- return count ? -ENXIO: 0;
- if (count > GLOBALMEM_SIZE - p)
- count = GLOBALMEM_SIZE - p;
- if(mutex_lock_interruptible(&dev->x4412_mutex))
- {
- return -ERESTARTSYS;
- }
- /*内核空间→用户空间*/
- if (copy_to_user(buf, (void*)(dev->mem + p), count))
- {
- ret = - EFAULT;
- }
- else
- {
- ret = count;
- }
- mutex_unlock(&dev->x4412_mutex);
- return ret;
- }
- /*写函数*/
- static ssize_t globalmem_write(struct file *filp, const char __user *buf,size_t size, loff_t *ppos)
- {
- unsigned long p = *ppos;
- unsigned int count = size;
- int ret = 0;
- struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/
- /*分析和获取有效的写长度*/
- if (p >= GLOBALMEM_SIZE)
- return count ? - ENXIO: 0;
- if (count > GLOBALMEM_SIZE - p)
- count = GLOBALMEM_SIZE - p;
- if(mutex_lock_interruptible(&dev->x4412_mutex))
- {
- return -ERESTARTSYS;
- }
- /*用户空间→内核空间*/
- if (copy_from_user(dev->mem + p, buf, count))
- ret = - EFAULT;
- else
- {
- ret = count;
- }
- mutex_unlock(&dev->x4412_mutex);
- return ret;
- }
- /*文件操作结构体*/
- static const struct file_operations globalmem_fops =
- {
- .owner = THIS_MODULE,
- .read = globalmem_read,
- .write = globalmem_write,
- .unlocked_ioctl = globalmem_ioctl,
- .open = globalmem_open,
- .release = globalmem_release,
- };
- /*初始化并注册cdev*/
- static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)
- {
- int err, devno = MKDEV(globalmem_major, index);
- cdev_init(&dev->cdev, &globalmem_fops);
- dev->cdev.owner = THIS_MODULE;
- dev->cdev.ops = &globalmem_fops;
- err = cdev_add(&dev->cdev, devno, 1);
- if (err)
- printk(KERN_NOTICE "Error %d adding cdev%d", err, index);
- }
- /*设备驱动模块加载函数*/
- int globalmem_init(void)
- {
- int result;
- dev_t devno;
- result = alloc_chrdev_region(&devno, 0, 1, "x4412-globalmem");
- if(result < 0)
- return result;
- globalmem_major = MAJOR(devno);
- /* 动态申请设备结构体的内存*/
- globalmem_devp = kmalloc(sizeof(struct globalmem_dev),GFP_KERNEL);
- if (!globalmem_devp)/*申请失败*/
- {
- result = -ENOMEM;
- goto fail_malloc;
- }
- memset(globalmem_devp, 0, sizeof(struct globalmem_dev));
- globalmem_setup_cdev(globalmem_devp, 0);
- cdev_class = class_create(THIS_MODULE,"x4412-globalmem");
- if(IS_ERR(cdev_class))
- goto fail_class;
- device_create(cdev_class,NULL,devno,NULL,"x4412-globalmem");
- mutex_init(&globalmem_devp->x4412_mutex);
- return 0;
- fail_class:
- class_destroy(cdev_class);
- fail_malloc:
- unregister_chrdev_region(devno, 1);
- return result;
- }
- /*模块卸载函数*/
- void globalmem_exit(void)
- {
- device_destroy(cdev_class,MKDEV(globalmem_major,0));
- class_destroy(cdev_class);
- cdev_del(&globalmem_devp->cdev); /*注销 cdev*/
- kfree(globalmem_devp); /*释放设备结构体内存*/
- unregister_chrdev_region(MKDEV(globalmem_major, 0), 1); /*释放设备号*/
- }
- MODULE_AUTHOR("www.9tripod.com");
- MODULE_LICENSE("GPL");
- module_init(globalmem_init);
- module_exit(globalmem_exit);
复制代码 使用echo命令和测试程序测试效果如下: - [root@x4412 mnt]# insmod x4412-globalmem.ko
- [root@x4412 mnt]# mdev -s
- [root@x4412 mnt]# echo 'www.9tripod.com' > /dev/x4412-globalmem
- [root@x4412 mnt]# cat /dev/x4412-globalmem
- www.9tripod.com
- [root@x4412 mnt]# ./x4412-globalmem-app
- read from /dev/x4412-gloalmem:
- hello,x4412!
- [ 9239.410779] globalmem is set to zero
- read from /dev/x4412-gloalmem later:
-
- [root@x4412 mnt]#
复制代码在x4412开发板和ibox卡片电脑上能直接运行的映像:
x4412-globalmem.ko
(4.54 KB, 下载次数: 4)
x4412-globalmem-app
(6.58 KB, 下载次数: 4)
|