+ -
当前位置:首页 → 问答吧 → 一个简单字符驱动例子的问题

一个简单字符驱动例子的问题

时间:2010-11-20

来源:互联网

我写了一个简单的字符驱动,代码如下:
  1. /*一、功能:
  2. *测试自旋锁
  3. *这里,在open中使用了最简单的自旋锁。
  4. *添加自旋锁之后,对临界资源xxx_count的访问就只限一个进程
  5. *如果没有spinlock/spin_unlock那么,可能多个进程同时访问xxx_count.
  6. *例如这个例子中,a访问xxx_count确认是否进入if(xxx_count),确认是不进入,在修改xxx_count前被b打断;
  7. *然后b也访问此时a还没修改的xxx_count,所以b也不进入,而这里本意是b要进入if分支的。
  8. *关于spinlock文档,参考内核源代码:Documentation/spinlocks.txt
  9. *在spinlock持有期间,进程一直占用cpu并不切换出去,这一点和信号不同。
  10.        

  11. *二、一般驱动简易使用说明:
  12. *1)编译
  13. *$make
  14. *2)插入模块
  15. *insmod simplespinlock.ko
  16. *可以通过"cat /proc/devices"得知设备的主从号码
  17. *3)创建设备文件
  18. *#mknod mytest c <主设备号> 0
  19. *4)卸载模块
  20. *rmmod simplespinlock

  21. *查看驱动信息:
  22. $modinfo simplespinlock.ko
  23. *
  24. *问题:
  25. *不知道为什么,使用echo good>/dev/mytest会循环打印write没有结束。
  26. */

  27. #include <linux/module.h>
  28. #include <linux/types.h>
  29. #include <linux/fs.h>
  30. #include <linux/errno.h>
  31. #include <linux/mm.h>
  32. #include <linux/sched.h>
  33. #include <linux/init.h>
  34. #include <linux/cdev.h>
  35. #include <asm/io.h>
  36. #include <asm/system.h>
  37. #include <asm/uaccess.h>

  38. /*+++使用自旋锁,必须包含这个头文件*/
  39. #include <linux/spinlock.h>


  40. #define simpledrv_SIZE 0x1000
  41. #define simpledrv_MAJOR 1025

  42. /*module info*/
  43. MODULE_LICENSE("Dual BSD/GPL");
  44. MODULE_AUTHOR("Quiet Heart");
  45. MODULE_DESCRIPTION("This is a simple spinlock module.");
  46. MODULE_ALIAS("spinlock module");

  47. /*simpledrv*/
  48. struct simpledrv_dev
  49. {
  50.         struct cdev cdev;
  51. };

  52. /*function*/
  53. int simpledrv_open(struct inode *inode, struct file *filp);
  54. int simpledrv_release(struct inode *inode, struct file *filp);
  55. static ssize_t simpledrv_read(struct file *filp, char __user *buf,
  56.                                                         size_t count, loff_t *ppos);
  57. static ssize_t simpledrv_write(struct file *filp, const char __user *buf,
  58.                                                         size_t count, loff_t *ppos);
  59. static loff_t simpledrv_llseek(struct file *filp, loff_t offset, int orig);
  60. static int simpledrv_ioctl(struct inode *inodep, struct file *filp,
  61.                                         unsigned int cmd, unsigned long arg);

  62. /*variable*/
  63. static int simpledrv_major = simpledrv_MAJOR;
  64. struct simpledrv_dev *devp;

  65. int xxx_count = 0;/*record the count of open*/
  66. spinlock_t count_lock;

  67. static const struct file_operations simpledrv_fops =
  68. {
  69.         .owner = THIS_MODULE,

  70.         .llseek = simpledrv_llseek,
  71.         .read = simpledrv_read,
  72.         .write = simpledrv_write,
  73.         .ioctl = simpledrv_ioctl,
  74.         .open = simpledrv_open,
  75.         .release = simpledrv_release,
  76. };


  77. /*impl*/
  78. int simpledrv_open(struct inode *inode, struct file *filp)
  79. {
  80.        
  81.         /*+++加锁,访问临界资源,释放锁*/
  82.         spin_lock(&count_lock);
  83.         if(xxx_count)
  84.         {
  85.                 spin_unlock(&count_lock);
  86.                 printk(KERN_ALERT "device is busy!\n");
  87.                 return - EBUSY;
  88.         }
  89.         ++xxx_count;
  90.         spin_unlock(&count_lock);
  91.         printk(KERN_ALERT "device open!\n");
  92.         filp->private_data = devp;
  93.         return 0;
  94. }

  95. int simpledrv_release(struct inode *inode, struct file *filp)
  96. {
  97.         /*+++加锁,访问临界资源,释放锁*/
  98.         spin_lock(&count_lock);
  99.         --xxx_count;
  100.         spin_unlock(&count_lock);
  101.         printk(KERN_ALERT "device close!\n");
  102.         return 0;
  103. }

  104. static ssize_t simpledrv_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
  105. {
  106.         printk(KERN_ALERT "read\n");

  107.         return 1;
  108. }

  109. static ssize_t simpledrv_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
  110. {
  111.         struct simpledrv_dev *dev;
  112.         dev = filp->private_data;
  113.         printk(KERN_ALERT "write!\n");

  114.         return 1;
  115. }

  116. static loff_t simpledrv_llseek(struct file *filp, loff_t offset, int orig)
  117. {
  118.         printk(KERN_ALERT "llseek!\n");
  119.         return 0;
  120. }

  121. static int simpledrv_ioctl(struct inode *inodep, struct file *filp, unsigned int cmd, unsigned long arg)
  122. {
  123.         struct simpledrv_dev *dev;
  124.         dev = filp->private_data;
  125.         printk(KERN_ALERT "ioctl!\n");

  126.         return 0;
  127. }

  128. int simpledrv_init(void)
  129. {
  130.         int result;
  131.         int err;
  132.         dev_t devno = MKDEV(simpledrv_major,0);

  133.         result = alloc_chrdev_region(&devno, 0,1, "simplespinlock");
  134.         simpledrv_major = MAJOR(devno);
  135.         if(result < 0)
  136.         {
  137.                 printk(KERN_ALERT "Error register simpledrv result:%d\n", result);
  138.                 return result;
  139.         }

  140.         devp = kmalloc(sizeof(struct simpledrv_dev),GFP_KERNEL);
  141.         if(!devp)
  142.         {
  143.                 result = -ENOMEM;
  144.                 unregister_chrdev_region(devno,1);
  145.                 return 0;
  146.         }
  147.         memset(devp, 0, sizeof(struct simpledrv_dev));

  148.         cdev_init(&devp->cdev, &simpledrv_fops);
  149.         devp->cdev.owner = THIS_MODULE;
  150.         err = cdev_add(&devp->cdev, devno, 1);
  151.         if(err)
  152.         {
  153.                 printk(KERN_ALERT "Error %d adding simpledrv", err);
  154.         }

  155.         /*other initialize*/
  156.         /*+++初始化自旋锁*/
  157.         spin_lock_init(&count_lock);
  158.         printk(KERN_ALERT "driver initialize!\n");
  159.         return 0;
  160. }

  161. void simpledrv_exit(void)
  162. {
  163.         cdev_del(&devp->cdev);

  164.         kfree(devp);
  165.         unregister_chrdev_region(MKDEV(simpledrv_major, 0), 1);
  166.         printk(KERN_ALERT "driver exit!\n");
  167. }

  168. module_init(simpledrv_init);
  169. module_exit(simpledrv_exit);
复制代码
但是,这个驱动有个严重的问题:
当我使用
mknod /dev/mytest c <major> <minor>
echo test /dev/mytest
的时候,查看dmesg发现,
1)没有open地方的log
2)总是不断的打印write!好象进入了死循环。
请问,这到底是怎么回事呢?
谢谢好心朋友的解答以及回复。^_^

作者: vaqeteart   发布时间: 2010-11-20

好长,看着太累了

作者: EZWORD   发布时间: 2010-11-20

只是测试了下,结果如下:
# insmod spin.ko
driver initialize!

# echo good >/dev/simplespinlock
device open!
write!
write!
write!
write!
write!
device close!

作者: EZWORD   发布时间: 2010-11-20