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");  
  • 1
  • 2
  • 下一页

相关内容