歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux驅動:用戶空間,內核空間內存交互測試

Linux驅動:用戶空間,內核空間內存交互測試

日期:2017/3/1 10:38:58   编辑:Linux編程

環境:

主機:Fedora 12

目標板:MINI6410

目標板LINUX內核版本:2.6.38

實現功能:

使用read函數讀取內核空間開辟的數組,使用write函數從用戶空間寫入數據到內核空間開辟的數組

說明:

Linux中內核空間和用戶空間有不同的內存定義,只能通過交互函數來互相訪問.

//檢測用戶空間地址是否合法,type選項:VERIFY_READ,VERIFY_WRITE

int access_ok(int type,const void *addr,unsigned long size);

//從用戶空間讀取內存

unsigned long copy_from_user(void *to,const void *from,unsigned long n);

//向用戶空間內存寫入

unsigned long copy_to_user(void *to,void *from,unsigned long len);

//寫入單值

int put_user(數據,ptr);

//讀取單值

int get_user(數據,ptr);


驅動源代碼:

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. #define DEVICE_NAME "test_driver"
  39. #define T_MAJORS 800
  40. //設備結構
  41. static struct _Test_Driver_Device
  42. {
  43. struct cdev fun_cdev;
  44. };
  45. struct _Test_Driver_Device *Test_Driver_Device;
  46. static dev_t dev;
  47. static struct class *test_class;
  48. //開辟緩存,用來讀寫
  49. #define LEN_BUF 256
  50. static unsigned char Buffer[LEN_BUF];
  51. //初始化互斥鎖
  52. static DEFINE_MUTEX(sem);
  53. //功能:初始化緩存
  54. static void init_buf(void)
  55. {
  56. memset(Buffer,0,LEN_BUF);
  57. }
  58. //功能:讀取緩存
  59. //返回:讀取的字節數
  60. ssize_t test_driver_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)
  61. {
  62. //判斷文件當前位置是否越界
  63. if (*f_pos >= LEN_BUF)
  64. {
  65. return 0;
  66. }
  67. //判斷讀取的字節總數是否越界
  68. if (count > (LEN_BUF - *f_pos))
  69. {
  70. count = 256 - *f_pos;
  71. }
  72. //拷貝數據到用戶空間
  73. if (copy_to_user(buf,Buffer + *f_pos,count))
  74. {
  75. return -EFAULT;
  76. }
  77. //改變文件的當前位置
  78. *f_pos += count;
  79. return count;
  80. }
  81. //功能:寫入緩存
  82. //返回:寫入的字節數
  83. ssize_t test_driver_write(struct file *filp,const char __user *buf,size_t count,loff_t *f_pos)
  84. {
  85. ssize_t err = -ENOMEM;
  86. //判斷文件當前位置是否越界
  87. if (*f_pos >= LEN_BUF)
  88. {
  89. goto ERR;
  90. }
  91. //判斷寫入的字節總數是否越界
  92. if (count > (LEN_BUF - *f_pos))
  93. {
  94. count = 256 - *f_pos;
  95. }
  96. //從用戶空間拷貝數據
  97. if (copy_from_user(Buffer + *f_pos,buf,count))
  98. {
  99. err = -EFAULT;
  100. goto ERR;
  101. }
  102. //改變文件的當前位置
  103. *f_pos += count;
  104. return count;
  105. ERR:
  106. return err;
  107. }
  108. //功能:偏移指針
  109. //返回:當前指針
  110. //off是偏移量,whence是偏移開始處
  111. ssize_t test_driver_llseek(struct file *filp,size_t count,loff_t off,int whence)
  112. {
  113. loff_t pos;
  114. //獲取當前指針
  115. pos = filp->f_pos;
  116. switch (whence)
  117. {
  118. //從0開始
  119. case 0:
  120. {
  121. pos = off;
  122. break;
  123. }
  124. //從當前位置開始
  125. case 1:
  126. {
  127. pos += off;
  128. break;
  129. }
  130. case 2:
  131. default:
  132. {
  133. return -EINVAL;
  134. }
  135. }
  136. //判斷是否超出范圍
  137. if (pos > LEN_BUF || pos < 0)
  138. {
  139. return -EINVAL;
  140. }
  141. //更改當前偏移量
  142. filp->f_pos = pos;
  143. return filp->f_pos;
  144. }
  145. static struct file_operations io_dev_fops = {
  146. .owner = THIS_MODULE,
  147. .llseek = test_driver_llseek,
  148. .write = test_driver_write,
  149. .read = test_driver_read,
  150. };
  151. static int __init dev_init(void)
  152. {
  153. int ret;
  154. unsigned temp;
  155. init_buf();
  156. //分配結構體
  157. Test_Driver_Device = kmalloc(sizeof(struct _Test_Driver_Device),GFP_KERNEL);
  158. if (!Test_Driver_Device)
  159. {
  160. unregister_chrdev_region(dev,1);
  161. device_destroy(test_class, dev);
  162. class_destroy(test_class);
  163. return -ENOMEM;
  164. }
  165. dev = MKDEV(T_MAJORS,0);
  166. cdev_init(&Test_Driver_Device->fun_cdev,&io_dev_fops);
  167. ret = register_chrdev_region(dev,1,DEVICE_NAME);
  168. if (ret < 0) return 0;
  169. ret = cdev_add(&Test_Driver_Device->fun_cdev,dev,1);
  170. if (ret < 0) return 0;
  171. printk (DEVICE_NAME"\tjdh:test_driver initialized!!\n");
  172. test_class = class_create(THIS_MODULE, "test_class1");
  173. if (IS_ERR(test_class))
  174. {
  175. printk(KERN_INFO "create class error\n");
  176. return -1;
  177. }
  178. device_create(test_class, NULL, dev, NULL, "test_driver");
  179. return ret;
  180. }
  181. static void __exit dev_exit(void)
  182. {
  183. unregister_chrdev_region(dev,1);
  184. device_destroy(test_class, dev);
  185. class_destroy(test_class);
  186. }
  187. module_init(dev_init);
  188. module_exit(dev_exit);
  189. MODULE_LICENSE("GPL");
  190. MODULE_AUTHOR("JDH");
Copyright © Linux教程網 All Rights Reserved