歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux驅動:阻塞式讀寫測試

Linux驅動:阻塞式讀寫測試

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