找回密码
 立即注册

QQ登录

只需一步,快速开始

帖子
查看: 2184|回复: 0
打印 上一主题 下一主题
收起左侧

学习笔记-Linux 内存映射应用

[复制链接]
跳转到指定楼层
楼主
ID:140343 发表于 2016-9-24 22:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在实际应用过程中,为了更加高效率的让用户层与底层进行大量数据交换,可以采用内存映射的方式,将物理内存映射到进程空间内,应用程序可以直接对那块内存进行操作从而提高效率。

贴出经过验证的代码,共后续分析原理使用。

驱动程序
  1. /*
  2. *    Copyright (c) 2016, Lovemengx
  3. *    All rights reserved.
  4. *
  5. *    文件名称: zhc_led.c
  6. *    摘    要: mmap 学习驱动
  7. *
  8. *    当前版本: 1.0
  9. *    作    者: Love 梦想
  10. *    完成日期:
  11. *
  12. *    取代版本:
  13. *    原作者  :
  14. *    完成日期:
  15. */
  16. #define __ISDEBUG__                // 开启打印信息
  17. #include <mach/zhc_public.h>
  18. #include <linux/miscdevice.h>
  19. #include <linux/delay.h>
  20. #include <linux/kernel.h>
  21. #include <linux/module.h>
  22. #include <linux/init.h>
  23. #include <linux/mm.h>
  24. #include <linux/fs.h>
  25. #include <linux/types.h>
  26. #include <linux/delay.h>
  27. #include <linux/moduleparam.h>
  28. #include <linux/slab.h>
  29. #include <linux/errno.h>
  30. #include <linux/ioctl.h>
  31. #include <linux/cdev.h>
  32. #include <linux/string.h>
  33. #include <linux/list.h>
  34. #include <linux/pci.h>
  35. #include <linux/vmalloc.h>
  36. #define DEVICE_NAME "mymap"
  37. #define MALLOC_SIZE        (8192 * 100)
  38. #define USE_KMALLOC        1
  39. static unsigned char array[10]= {0,1,2,3,4,5,6,7,8,9};
  40. unsigned char     *g_mmap_buff = NULL;
  41. int             g_mmap_buff_size = MALLOC_SIZE;

  42. // 分配内存
  43. int mmap_alloc(unsigned char **mmap_buff, int require_buf_size)
  44. {
  45.     struct page     *page;
  46.     unsigned char     *mmap_buf_t;
  47.     int             mmap_size;
  48.     int                i;

  49.     mmap_size = PAGE_ALIGN(require_buf_size);

  50. #if USE_KMALLOC //for kmalloc

  51.     mmap_buf_t = kzalloc(mmap_size, GFP_KERNEL);
  52.     if (!mmap_buf_t)
  53.     {
  54.         return -1;
  55.     }
  56.     for (page = virt_to_page(mmap_buf_t ); page < virt_to_page(mmap_buf_t + mmap_size); page++)
  57.     {
  58.         SetPageReserved(page);
  59.     }

  60. #else //for vmalloc

  61.     mmap_buf_t  = vmalloc(mmap_size);
  62.     if (!mmap_buf_t )
  63.     {
  64.         return -1;
  65.     }
  66.     for (i = 0; i < mmap_size; i += PAGE_SIZE)
  67.     {
  68.         SetPageReserved(vmalloc_to_page((void *)(((unsigned long)mmap_buf_t) + i)));
  69.     }

  70. #endif
  71.    
  72.     *mmap_buff = mmap_buf_t;
  73.     return mmap_size;
  74. }

  75. void mmap_free(unsigned char *mmap_buf, int mmap_size)
  76. {

  77. #if USE_KMALLOC

  78.     struct page *page;
  79.     for (page = virt_to_page(mmap_buf); page < virt_to_page(mmap_buf + mmap_size); page++)
  80.     {
  81.         ClearPageReserved(page);
  82.     }
  83.     kfree(mmap_buf);

  84. #else

  85.     int i;
  86.     for (i = 0; i < mmap_size; i += PAGE_SIZE)
  87.     {
  88.         ClearPageReserved(vmalloc_to_page((void *)(((unsigned long)mmap_buf) + i)));
  89.     }
  90.     vfree(mmap_buf);

  91. #endif

  92.     mmap_buf = NULL;
  93. }

  94. static int my_open(struct inode *inode, struct file *file)
  95. {
  96.     dprintk();
  97.     return 0;
  98. }

  99. static int my_map(struct file *filp, struct vm_area_struct *vma)
  100. {
  101.     int             ret;
  102.     unsigned long     pfn;
  103.     unsigned long     start = vma->vm_start;
  104.     unsigned long     size = PAGE_ALIGN(vma->vm_end - vma->vm_start);
  105.     int                i;
  106.     unsigned char     *mmap_buff = g_mmap_buff;

  107.     if (size > g_mmap_buff_size || !g_mmap_buff)
  108.     {
  109.         return -EINVAL;
  110.     }
  111.    
  112.     dprintk("g_mmap_buff = 0x%x", g_mmap_buff);
  113.     //往该内存写10字节数据
  114.     for(i=0; i<10; i++)
  115.     {
  116.         mmap_buff[i] = array[i];
  117.     }
  118.    
  119. #if USE_KMALLOC

  120.     return remap_pfn_range(vma, start, (virt_to_phys(g_mmap_buff) >> PAGE_SHIFT), size, PAGE_SHARED);

  121. #else
  122.     /* loop over all pages, map it page individually */
  123.     while (size > 0)
  124.     {
  125.         pfn = vmalloc_to_pfn(mmap_buff);
  126.         if ((ret = remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) < 0)
  127.         {
  128.             return ret;
  129.         }
  130.         start += PAGE_SIZE;
  131.         mmap_buff += PAGE_SIZE;
  132.         size -= PAGE_SIZE;
  133.     }
  134.    
  135. #endif
  136.     return 0;
  137. }

  138. static struct file_operations dev_fops =
  139. {
  140.     .owner    = THIS_MODULE,
  141.     .open    = my_open,
  142.     .mmap   = my_map,
  143. };

  144. static struct miscdevice misc =
  145. {
  146.     .minor = MISC_DYNAMIC_MINOR,
  147.     .name = DEVICE_NAME,
  148.     .fops = &dev_fops,
  149. };

  150. static ssize_t hwrng_attr_current_show(struct device *dev,
  151.                           struct device_attribute *attr,
  152.                            char *buf)
  153. {
  154.     int i;
  155.     for(i = 0; i < 10 ; i++)
  156.     {
  157.         printk("%d\n",g_mmap_buff[i]);
  158.     }
  159.     return 0;
  160. }

  161. static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
  162.                    hwrng_attr_current_show,
  163.                    NULL);
  164.                   
  165. static int __init dev_init(void)
  166. {
  167.     int ret;

  168.     dprintk();
  169.     //注册混杂设备
  170.     ret = misc_register(&misc);
  171.    
  172.     //内存分配
  173.     ret = mmap_alloc(&g_mmap_buff, g_mmap_buff_size);
  174.     dprintk("ret = %d\n", ret);
  175.    
  176.     if(NULL == g_mmap_buff)
  177.     {
  178.         eprintk("g_mmap_buff => NULL");
  179.         return 0;
  180.     }
  181.     ret = device_create_file(misc.this_device,&dev_attr_rng_current);
  182.     return ret;
  183. }

  184. static void __exit dev_exit(void)
  185. {
  186.     dprintk();
  187.     //注销设备
  188.     misc_deregister(&misc);
  189.    
  190.     mmap_free(g_mmap_buff, g_mmap_buff_size);
  191. }

  192. module_init(dev_init);
  193. module_exit(dev_exit);
  194. MODULE_LICENSE("GPL");

  195. 应用:
  196. #include <unistd.h>
  197. #include <stdio.h>
  198. #include <stdlib.h>
  199. #include <string.h>
  200. #include <fcntl.h>
  201. #include <linux/fb.h>
  202. #include <sys/mman.h>
  203. #include <sys/ioctl.h>
  204. #define PAGE_SIZE 4096 * 2

  205. int main(int argc , char *argv[])
  206. {
  207.     int fd;
  208.     int i;
  209.     unsigned char *p_map;
  210.     //打开设备
  211.     fd = open("/dev/mymap",O_RDWR);
  212.     if(fd < 0)
  213.     {
  214.         printf("open fail\n");
  215.         exit(1);
  216.     }
  217.     //内存映射
  218.     p_map = (unsigned char *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0);
  219.     if(p_map == MAP_FAILED)
  220.     {
  221.         printf("mmap fail\n");
  222.         goto here;
  223.     }
  224.      
  225.     //打印映射后的内存中的前10个字节内容
  226.     for(i=0; i<10; i++)
  227.     {
  228.         printf("%d\n",p_map[i]);
  229.         p_map[i] = i + 1;
  230.     }
  231.    
  232.     strcpy(p_map, "adcdefghij");

  233. here:
  234.     munmap(p_map, PAGE_SIZE);

  235.     return 0;
  236. }  
复制代码



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表