九鼎创展论坛中文版English
登录 | 立即注册 设为首页收藏本站 切换到宽版
查看: 3954|回复: 0
打印 上一主题 下一主题

x4412&ibox项目实战36-使用互斥体避免并发竞争

[复制链接]
跳转到指定楼层
楼主
发表于 2014-10-8 18:45:11 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
尽管信号量已经可以实现互斥的功能,而且包含DECLARE_MUTEX()、init_MUTEX ()等定义信号量的宏或函数,从名字上看就体现出了互斥体的概念,但是mutex在Linux内核中还是真实地存在的。
下面代码定义名为my_mutex的互斥体并初始化它。
  1. struct mutex my_mutex;
  2. mutex_init(&my_mutex);
复制代码
下面的两个函数用于获取互斥体。
  1. void fastcall mutex_lock(struct mutex *lock);
  2. int fastcall mutex_lock_interruptible(struct mutex *lock);
  3. int fastcall mutex _trylock(struct mutex *lock);
复制代码
mutex_lock()与mutex_lock_interruptible()的区别和down()与down_interruptible()的区别完全一致,前者引起的睡眠不能被信号打断,而后者可以。mutex_trylock()用于尝试获得mutex,获取不到mutex时不会引起进程睡眠。
下列函数用于释放互斥体。
  1. void fastcall mutex_unlock(struct mutex *lock);
复制代码
mutex的使用方法和信号量用于互斥的场合完全一样,如下所示:
  1. struct mutex my _ mutex; //定义 mutex
  2. mutex _ init(&my _ mutex); //初始化 mutex
  3. mutex _ lock(&my _ mutex); //获取 mutex
  4. ...//临界资源
  5. mutex _ unlock(&my _ mutex); //释放 mutex
复制代码
       globalmem驱动中添加互斥体,对应驱动源码如下:
  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/fs.h>
  4. #include <linux/errno.h>
  5. #include <linux/cdev.h>
  6. #include <linux/slab.h>
  7. #include <linux/device.h>
  8. #include <asm/uaccess.h>
  9. #define GLOBALMEM_SIZE 0x1000 /*全局内存最大4KB*/
  10. #define MEM_CLEAR 0x1                    /*清零全局内存*/
  11. static int globalmem_major;
  12. static struct class *cdev_class;
  13. /*globalmem 设备结构体*/
  14. struct globalmem_dev
  15. {
  16.          struct cdev cdev; /*cdev 结构体*/
  17.          unsigned char mem[GLOBALMEM_SIZE]; /*全局内存*/
  18.          struct mutex x4412_mutex;
  19. };
  20. struct globalmem_dev *globalmem_devp; /*设备结构体指针*/
  21. /*文件打开函数*/
  22. int globalmem_open(struct inode *inode, struct file *filp)
  23. {
  24.          /*将设备结构体指针赋值给文件私有数据指针*/
  25.          filp->private_data = globalmem_devp;
  26.          return 0;
  27. }
  28. /*文件释放函数*/
  29. int globalmem_release(struct inode *inode, struct file *filp)
  30. {
  31.          return 0;
  32. }
  33. /* ioctl 设备控制函数 */
  34. static long globalmem_ioctl(struct file *filp,unsigned int cmd, unsigned long arg)
  35. {
  36.          struct globalmem_dev *dev = filp->private_data;/*获得设备结构体指针*/
  37.          switch(cmd)
  38.          {
  39.                    case MEM_CLEAR:
  40.                             if(mutex_lock_interruptible(&dev->x4412_mutex))
  41.                             {
  42.                                      return -ERESTARTSYS;
  43.                             }
  44.                             memset(dev->mem, 0, GLOBALMEM_SIZE);
  45.                             mutex_unlock(&dev->x4412_mutex);
  46.                             printk(KERN_INFO "globalmem is set to zero\n");
  47.                    break;
  48.                    default:
  49.                             return -EINVAL;
  50.          }
  51.          return 0;
  52. }
  53. /*读函数*/
  54. static ssize_t globalmem_read(struct file *filp, char __user *buf,size_t size,loff_t *ppos)
  55. {
  56.          unsigned long p = *ppos;
  57.          unsigned int count = size;
  58.          int ret = 0;
  59.          struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/
  60.          /*分析和获取有效的写长度*/
  61.          if (p >= GLOBALMEM_SIZE)
  62.                    return count ? -ENXIO: 0;
  63.          if (count > GLOBALMEM_SIZE - p)
  64.                    count = GLOBALMEM_SIZE - p;
  65.          if(mutex_lock_interruptible(&dev->x4412_mutex))
  66.          {
  67.                    return -ERESTARTSYS;
  68.          }
  69.          /*内核空间→用户空间*/
  70.          if (copy_to_user(buf, (void*)(dev->mem + p), count))
  71.          {
  72.                    ret = - EFAULT;
  73.          }
  74.          else
  75.          {
  76.                    ret = count;
  77.          }
  78.          mutex_unlock(&dev->x4412_mutex);
  79.          return ret;
  80. }
  81. /*写函数*/
  82. static ssize_t globalmem_write(struct file *filp, const char __user *buf,size_t size, loff_t *ppos)
  83. {
  84.          unsigned long p = *ppos;
  85.          unsigned int count = size;
  86.          int ret = 0;
  87.          struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/
  88.          /*分析和获取有效的写长度*/
  89.          if (p >= GLOBALMEM_SIZE)
  90.                    return count ? - ENXIO: 0;
  91.          if (count > GLOBALMEM_SIZE - p)
  92.                    count = GLOBALMEM_SIZE - p;
  93.          if(mutex_lock_interruptible(&dev->x4412_mutex))
  94.          {
  95.                    return -ERESTARTSYS;
  96.          }
  97.           /*用户空间→内核空间*/
  98.          if (copy_from_user(dev->mem + p, buf, count))
  99.                    ret = - EFAULT;
  100.          else
  101.          {
  102.                    ret = count;
  103.          }
  104.          mutex_unlock(&dev->x4412_mutex);
  105.          return ret;
  106. }
  107. /*文件操作结构体*/
  108. static const struct file_operations globalmem_fops =
  109. {
  110.          .owner = THIS_MODULE,
  111.          .read = globalmem_read,
  112.          .write = globalmem_write,
  113.          .unlocked_ioctl = globalmem_ioctl,
  114.          .open = globalmem_open,
  115.          .release = globalmem_release,
  116. };
  117. /*初始化并注册cdev*/
  118. static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)
  119. {
  120.          int err, devno = MKDEV(globalmem_major, index);
  121.          cdev_init(&dev->cdev, &globalmem_fops);
  122.          dev->cdev.owner = THIS_MODULE;
  123.          dev->cdev.ops = &globalmem_fops;
  124.          err = cdev_add(&dev->cdev, devno, 1);
  125.          if (err)
  126.                    printk(KERN_NOTICE "Error %d adding cdev%d", err, index);
  127. }
  128. /*设备驱动模块加载函数*/
  129. int globalmem_init(void)
  130. {
  131.          int result;
  132.          dev_t devno;
  133.          result = alloc_chrdev_region(&devno, 0, 1, "x4412-globalmem");
  134.          if(result < 0)
  135.                    return result;
  136.          globalmem_major = MAJOR(devno);
  137.          /* 动态申请设备结构体的内存*/
  138.          globalmem_devp = kmalloc(sizeof(struct globalmem_dev),GFP_KERNEL);
  139.          if (!globalmem_devp)/*申请失败*/
  140.          {
  141.                    result = -ENOMEM;
  142.                    goto fail_malloc;
  143.          }
  144.          memset(globalmem_devp, 0, sizeof(struct globalmem_dev));
  145.          globalmem_setup_cdev(globalmem_devp, 0);
  146.          cdev_class = class_create(THIS_MODULE,"x4412-globalmem");
  147.          if(IS_ERR(cdev_class))
  148.                    goto fail_class;
  149.          device_create(cdev_class,NULL,devno,NULL,"x4412-globalmem");
  150.          mutex_init(&globalmem_devp->x4412_mutex);
  151.          return 0;
  152. fail_class:
  153.          class_destroy(cdev_class);
  154. fail_malloc:
  155.          unregister_chrdev_region(devno, 1);
  156.          return result;
  157. }
  158. /*模块卸载函数*/
  159. void globalmem_exit(void)
  160. {
  161.          device_destroy(cdev_class,MKDEV(globalmem_major,0));
  162.          class_destroy(cdev_class);
  163.          cdev_del(&globalmem_devp->cdev); /*注销 cdev*/
  164.          kfree(globalmem_devp); /*释放设备结构体内存*/
  165.          unregister_chrdev_region(MKDEV(globalmem_major, 0), 1); /*释放设备号*/
  166. }
  167. MODULE_AUTHOR("www.9tripod.com");
  168. MODULE_LICENSE("GPL");
  169. module_init(globalmem_init);
  170. module_exit(globalmem_exit);
复制代码
       使用echo命令和测试程序测试效果如下:
  1. [root@x4412 mnt]# insmod x4412-globalmem.ko
  2. [root@x4412 mnt]# mdev -s                                      
  3. [root@x4412 mnt]# echo 'www.9tripod.com' > /dev/x4412-globalmem
  4. [root@x4412 mnt]# cat /dev/x4412-globalmem
  5. www.9tripod.com
  6. [root@x4412 mnt]# ./x4412-globalmem-app
  7. read from /dev/x4412-gloalmem:
  8. hello,x4412!
  9. [ 9239.410779] globalmem is set to zero
  10. read from /dev/x4412-gloalmem later:

  11. [root@x4412 mnt]#
复制代码
在x4412开发板和ibox卡片电脑上能直接运行的映像:
x4412-globalmem.ko (4.54 KB, 下载次数: 4)
x4412-globalmem-app (6.58 KB, 下载次数: 4)


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳市九鼎创展科技官方论坛 ( 粤ICP备11028681号-2  

GMT+8, 2024-6-18 19:56 , Processed in 0.020790 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表