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

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