歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Linux驅動:阻塞式讀寫測試

環境:

主機:Fedora 12

目標板:MINI6410

目標板LINUX內核版本:2.6.38

實現功能:

開辟一個256字節的循環緩沖,可以同時讀寫,如果數據量不足,則讀進程會被阻塞,直到有數據寫入

驅動源代碼:

test_driver.c:

[cpp]
  1. #include <linux/miscdevice.h>   
  2. #include <linux/delay.h>   
  3. #include <asm/irq.h>   
  4. //#include <mach/regs-gpio.h>   
  5. #include <mach/hardware.h>   
  6. #include <linux/kernel.h>   
  7. #include <linux/module.h>   
  8. #include <linux/init.h>   
  9. #include <linux/mm.h>   
  10. #include <linux/fs.h>   
  11. #include <linux/types.h>   
  12. #include <linux/delay.h>   
  13. #include <linux/moduleparam.h>   
  14. #include <linux/slab.h>   
  15. #include <linux/errno.h>   
  16. #include <linux/ioctl.h>   
  17. #include <linux/cdev.h>   
  18. #include <linux/string.h>   
  19. #include <linux/list.h>   
  20. #include <linux/pci.h>   
  21. #include <asm/uaccess.h>   
  22. #include <asm/atomic.h>   
  23. #include <asm/unistd.h>   
  24. #include <linux/major.h>   
  25.   
  26. #include <mach/map.h>   
  27. #include <mach/regs-clock.h>   
  28. #include <mach/regs-gpio.h>   
  29.   
  30. #include <plat/gpio-cfg.h>   
  31. #include <mach/gpio-bank-e.h>   
  32. #include <mach/gpio-bank-k.h>   
  33. #include <mach/gpio-bank-h.h>   
  34. #include <mach/gpio-bank-n.h>   
  35. #include <mach/gpio-bank-l.h>   
  36. #include <mach/gpio-bank-p.h>   
  37.   
  38. #include <linux/device.h>   
  39.   
  40. #include <linux/jiffies.h>   
  41. #include <linux/string.h>   
  42.   
  43. #include <linux/semaphore.h>   
  44. #include <linux/sched.h>    
  45. #include <linux/wait.h>   
  46.   
  47. #define DEVICE_NAME "test_driver"   
  48. #define T_MAJORS    800   
  49.   
  50. //設備結構   
  51. static struct _Test_Driver_Device  
  52. {  
  53.     struct cdev fun_cdev;  
  54.     //定義緩沖   
  55.     unsigned char *buffer,*end;  
  56.     //讀寫指針   
  57.     unsigned char *rp,*wp;  
  58.     //讀信號量   
  59.     struct semaphore sem_r;  
  60.     //寫信號量   
  61.     struct semaphore sem_w;  
  62.     //等待隊列頭   
  63.     struct wait_queue_head_t *wq;  
  64. };  
  65. struct _Test_Driver_Device *Test_Driver_Device;  
  66.   
  67. static dev_t dev;  
  68. static struct class    *test_class;  
  69.   
  70. //開辟緩存,用來讀寫   
  71. #define LEN_BUF 256   
  72. static unsigned char Buffer[LEN_BUF];  
  73.   
  74. //功能:初始化緩存   
  75. static void init_buf(void)  
  76. {  
  77.     memset(Buffer,0,LEN_BUF);  
  78. }  
  79.   
  80. //功能:讀取緩存   
  81. //返回:讀取的字節數   
  82. ssize_t test_driver_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)  
  83. {  
  84.     int temp1 = 0,temp2 = 0,temp3 = 0;  
  85.   
  86.     //獲取信號量   
  87.     if (down_interruptible(&Test_Driver_Device->sem_r))  
  88.     {  
  89.         return -ERESTARTSYS;  
  90.     }  
  91.       
  92.     //循環防止解除阻塞時的競爭   
  93.     while (Test_Driver_Device->wp == Test_Driver_Device->rp)  
  94.     {  
  95.         //讀不到數據   
  96.         //釋放信號量   
  97.         up(&Test_Driver_Device->sem_r);  
  98.   
  99.         //判斷是否是非阻塞讀   
  100.         if (filp->f_flags & O_NONBLOCK)  
  101.         {  
  102.             return -EAGAIN;  
  103.         }  
  104.           
  105.         //如果是阻塞式讀,則阻塞   
  106.         if (wait_event_interruptible(Test_Driver_Device->wq,Test_Driver_Device->wp != Test_Driver_Device->rp))  
  107.         {  
  108.             return -ERESTARTSYS;  
  109.         }  
  110.   
  111.         //獲取信號量   
  112.         if (down_interruptible(&Test_Driver_Device->sem_r))  
  113.         {  
  114.             return -ERESTARTSYS;  
  115.         }  
  116.     }  
  117.   
  118.     if (Test_Driver_Device->wp > Test_Driver_Device->rp)  
  119.     {  
  120.         count = min(count,(size_t)(Test_Driver_Device->wp - Test_Driver_Device->rp));  
  121.         //拷貝數據到用戶空間   
  122.         if (copy_to_user(buf,Test_Driver_Device->rp,count))  
  123.         {  
  124.             return -EFAULT;  
  125.         }  
  126.         Test_Driver_Device->rp += count;  
  127.     }  
  128.     else  
  129.     {  
  130.         temp1 = Test_Driver_Device->end - Test_Driver_Device->rp + 1;  
  131.         temp2 = Test_Driver_Device->wp - Test_Driver_Device->buffer;  
  132.         if (count <= temp1)  
  133.         {  
  134.             //拷貝數據到用戶空間   
  135.             if (copy_to_user(buf,Test_Driver_Device->rp,count))  
  136.             {  
  137.                 return -EFAULT;  
  138.             }  
  139.             Test_Driver_Device->rp += count;  
  140.         }  
  141.         else  
  142.         {  
  143.             //拷貝數據到用戶空間   
  144.             if (copy_to_user(buf,Test_Driver_Device->rp,temp1))  
  145.             {  
  146.                 return -EFAULT;  
  147.             }  
  148.             Test_Driver_Device->rp = Test_Driver_Device->buffer;  
  149.             temp3 = min(count - temp1,temp2);  
  150.             count = temp1 + temp3;  
  151.             if (copy_to_user(buf + temp1,Test_Driver_Device->rp,temp3))  
  152.             {  
  153.                 return -EFAULT;  
  154.             }  
  155.             Test_Driver_Device->rp += temp3;  
  156.         }  
  157.     }  
  158.   
  159.     if (Test_Driver_Device->rp == Test_Driver_Device->end + 1)  
  160.     {  
  161.         Test_Driver_Device->rp = Test_Driver_Device->buffer;  
  162.     }  
  163.     //釋放信號量   
  164.     up(&Test_Driver_Device->sem_r);  
  165.     printk (DEVICE_NAME"\tjdh:rp zhi zhen = %d\n",Test_Driver_Device->rp - Test_Driver_Device->buffer);  
  166.   
  167.     return count;  
  168. }  
  169.   
  170. //功能:寫入緩存   
  171. //返回:寫入的字節數   
  172. ssize_t test_driver_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_pos)  
  173. {  
  174.     int temp1 = 0,temp2 = 0;;  
  175.   
  176.     //判斷需要寫入的字節數是否大於緩存   
  177.     if (count > LEN_BUF)  
  178.     {  
  179.         return -ENOMEM;  
  180.     }  
  181.   
  182.     //獲取信號量   
  183.     if (down_interruptible(&Test_Driver_Device->sem_w))  
  184.     {  
  185.         return -ERESTARTSYS;  
  186.     }  
  187.   
  188.     //寫入緩存   
  189.     if (count <= (Test_Driver_Device->end - Test_Driver_Device->wp + 1))  
  190.     {  
  191.         //從用戶空間拷貝數據   
  192.         if (copy_from_user(Test_Driver_Device->wp,buf,count))  
  193.         {  
  194.             return -EFAULT;  
  195.         }  
  196.         Test_Driver_Device->wp += count;  
  197.     }  
  198.     else  
  199.     {  
  200.         temp1 = Test_Driver_Device->end - Test_Driver_Device->wp + 1;  
  201.         temp2 = count - temp1;  
  202.         //從用戶空間拷貝數據   
  203.         if (copy_from_user(Test_Driver_Device->wp,buf,temp1))  
  204.         {  
  205.             return -EFAULT;  
  206.         }  
  207.         Test_Driver_Device->wp = Test_Driver_Device->buffer;  
  208.         //從用戶空間拷貝數據   
  209.         if (copy_from_user(Test_Driver_Device->wp,buf + temp1,temp2))  
  210.         {  
  211.             return -EFAULT;  
  212.         }  
  213.         Test_Driver_Device->wp += temp2;  
  214.     }  
  215.   
  216.     if (Test_Driver_Device->wp == Test_Driver_Device->end + 1)  
  217.     {  
  218.         Test_Driver_Device->wp = Test_Driver_Device->buffer;  
  219.     }  
  220.     //喚醒阻塞進程   
  221.     wake_up_interruptible(&Test_Driver_Device->wq);  
  222.     //釋放信號量   
  223.     up(&Test_Driver_Device->sem_w);  
  224.     printk (DEVICE_NAME"\tjdh:wp zhi zhen = %d\n",Test_Driver_Device->wp - Test_Driver_Device->buffer);  
  225.   
  226.     return count;  
  227. }  
  228.   
  229. static struct file_operations io_dev_fops = {  
  230.     .owner = THIS_MODULE,  
  231.     .write = test_driver_write,  
  232.     .read = test_driver_read,  
  233. };  
  234.   
  235. static int __init dev_init(void)  
  236. {  
  237.     int ret;  
  238.     unsigned temp;  
  239.   
  240.     init_buf();  
  241.   
  242.     //分配結構體   
  243.     Test_Driver_Device = kmalloc(sizeof(struct _Test_Driver_Device),GFP_KERNEL);  
  244.     if (!Test_Driver_Device)  
  245.     {  
  246.         unregister_chrdev_region(dev,1);  
  247.             device_destroy(test_class, dev);   
  248.             class_destroy(test_class);  
  249.   
  250.         return -ENOMEM;  
  251.     }  
  252.       
  253.     //定義緩沖的開始和結束的指針   
  254.     Test_Driver_Device->buffer = Buffer;  
  255.     Test_Driver_Device->end = Buffer + LEN_BUF - 1;  
  256.     Test_Driver_Device->rp = Test_Driver_Device->buffer;  
  257.     Test_Driver_Device->wp = Test_Driver_Device->buffer;  
  258.     //初始化讀信號量   
  259.     sema_init(&Test_Driver_Device->sem_r,1);  
  260.     //初始化寫信號量   
  261.     sema_init(&Test_Driver_Device->sem_w,1);  
  262.     //初始化等待隊列頭   
  263.     init_waitqueue_head(&Test_Driver_Device->wq);  
  264.   
  265.     dev = MKDEV(T_MAJORS,0);  
  266.     cdev_init(&Test_Driver_Device->fun_cdev,&io_dev_fops);  
  267.     ret = register_chrdev_region(dev,1,DEVICE_NAME);  
  268.     if (ret < 0) return 0;  
  269.     ret = cdev_add(&Test_Driver_Device->fun_cdev,dev,1);  
  270.     if (ret < 0) return 0;  
  271.   
  272.     printk (DEVICE_NAME"\tjdh:test_driver initialized!!\n");  
  273.   
  274.     test_class = class_create(THIS_MODULE, "test_class1");   
  275.     if (IS_ERR(test_class))   
  276.     {   
  277.         printk(KERN_INFO "create class error\n");   
  278.         return -1;   
  279.     }   
  280.     device_create(test_class, NULL, dev, NULL, "test_driver");   
  281.   
  282.     return ret;  
  283. }  
  284.   
  285. static void __exit dev_exit(void)  
  286. {  
  287.     unregister_chrdev_region(dev,1);  
  288.   
  289.         device_destroy(test_class, dev);   
  290.         class_destroy(test_class);  
  291. }  
  292.   
  293. module_init(dev_init);  
  294. module_exit(dev_exit);  
  295. MODULE_LICENSE("GPL");  
  296. MODULE_AUTHOR("JDH");  
Copyright © Linux教程網 All Rights Reserved