免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2189 | 回复: 5
打印 上一主题 下一主题

问个内存分配和访问的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-11-27 16:33 |只看该作者 |倒序浏览
在user mode写了一个 application,内核有一个char设备驱动。

现在user mode的application打算ioctl到驱动程序,分配一段物理内存,同时map这段物理内存到用户态,这样应用程序就可以访问了。应该怎么实现??

我在内核驱动程序中使用get_free_pages,但是在用户态打开/dev/mem了,mmap不能成功啊。
大家一般怎么应对这种情况

论坛徽章:
0
2 [报告]
发表于 2010-11-27 16:53 |只看该作者
本帖最后由 EZWORD 于 2010-11-27 16:56 编辑

论坛上精典帖子里有这个源代码,不知道是哪位大神写的了。驱动如下:
  1. #include <linux/version.h>
  2. #include <linux/module.h>
  3. #include <linux/proc_fs.h>
  4. #include <linux/mm.h>

  5. #define PROC_MEMSHARE_DIR "memshare"
  6. #define PROC_MEMSHARE_PHYADDR "phymem_addr"
  7. #define PROC_MEMSHARE_SIZE "phymem_size"

  8. /*alloc one page. 4096 bytes*/
  9. #define PAGE_ORDER 8
  10. /*this value can get from PAGE_ORDER*/
  11. #define PAGES_NUMBER 38

  12. struct proc_dir_entry *proc_memshare_dir ;
  13. unsigned long kernel_memaddr = 0;
  14. unsigned long kernel_memsize= 0;

  15. static int proc_read_addr(char *page, char **start, off_t off, int count,int *eof, void *data)
  16. {
  17.         return sprintf(page, "%08lx\n", __pa(kernel_memaddr));
  18. }
  19. static int proc_read_size(char *page, char **start, off_t off, int count,int *eof, void *data)
  20. {
  21.         return sprintf(page, "%lu\n", kernel_memsize);
  22. }

  23. static int __init init(void)
  24. {
  25.         /*build proc dir "memshare"and two proc files: phymem_addr, phymem_size in the dir*/
  26.         proc_memshare_dir = proc_mkdir(PROC_MEMSHARE_DIR, NULL);
  27.         create_proc_read_entry(PROC_MEMSHARE_PHYADDR, 0, proc_memshare_dir, proc_read_addr,NULL);
  28.         create_proc_read_entry(PROC_MEMSHARE_SIZE, 0, proc_memshare_dir, proc_read_size,NULL);
  29.                 // for old kernel 2.6.26,use below format
  30.                 //create_proc_info_entry(PROC_MEMSHARE_PHYADDR, 0, proc_memshare_dir, proc_read_addr);
  31.         //create_proc_info_entry(PROC_MEMSHARE_SIZE, 0, proc_memshare_dir, proc_read_size);


  32.         /*alloc one page*/
  33.         kernel_memaddr =__get_free_pages(GFP_KERNEL, PAGE_ORDER);
  34.         if(!kernel_memaddr)
  35.         {
  36.                 printk("Allocate memory failure!\n");
  37.         }
  38.         else
  39.         {
  40.                 SetPageReserved(virt_to_page(kernel_memaddr));
  41.                 kernel_memsize = PAGES_NUMBER * PAGE_SIZE;
  42.                 printk("Allocate memory success!. The phy mem addr=%08lx, size=%lu\n", __pa(kernel_memaddr), kernel_memsize);
  43.         }
  44.         return 0;
  45. }

  46. static void __exit fini(void)
  47. {
  48.         printk("The content written by user is: %s\n", (unsigned char *) kernel_memaddr);
  49.         ClearPageReserved(virt_to_page(kernel_memaddr));
  50.         free_pages(kernel_memaddr, PAGE_ORDER);
  51.         remove_proc_entry(PROC_MEMSHARE_PHYADDR, proc_memshare_dir);
  52.         remove_proc_entry(PROC_MEMSHARE_SIZE, proc_memshare_dir);
  53.         remove_proc_entry(PROC_MEMSHARE_DIR, NULL);

  54.         return;
  55. }
  56. module_init(init);
  57. module_exit(fini);
  58. MODULE_LICENSE("GPL");
  59. MODULE_AUTHOR("Godbach ([email]nylzhaowei@163.com[/email])");
  60. MODULE_DESCRIPTION("memory dynamic alloc and use it at user space.");
复制代码
测试如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include <fcntl.h>
  6. #include <sys/stat.h>
  7. #include <sys/types.h>
  8. #include <sys/mman.h>

  9. int main(int argc, char* argv[])
  10. {
  11.         if(argc != 2)
  12.         {
  13.                 printf("Usage: %s string\n", argv[0]);
  14.                 return 0;
  15.         }
  16.         
  17.         unsigned long phymem_addr, phymem_size;
  18.         char *map_addr;
  19.         char s[256];
  20.         int fd;
  21.         
  22.         /*get the physical address of allocated memory in kernel*/
  23.         fd = open("/proc/memshare/phymem_addr", O_RDONLY);
  24.         if(fd < 0)
  25.         {
  26.                 printf("cannot open file /proc/memshare/phymem_addr\n");
  27.                 return 0;
  28.         }
  29.         read(fd, s, sizeof(s));
  30.         sscanf(s, "%lx", &phymem_addr);
  31.         close(fd);

  32.         /*get the size of allocated memory in kernel*/
  33.         fd = open("/proc/memshare/phymem_size", O_RDONLY);
  34.         if(fd < 0)
  35.         {
  36.                 printf("cannot open file /proc/memshare/phymem_size\n");
  37.                 return 0;
  38.         }
  39.         read(fd, s, sizeof(s));
  40.         sscanf(s, "%lu", &phymem_size);
  41.         close(fd);
  42.         
  43.         printf("phymem_addr=%lx, phymem_size=%lu\n", phymem_addr, phymem_size);
  44.         /*memory map*/
  45.         int map_fd = open("/dev/mem", O_RDWR);
  46.         if(map_fd < 0)
  47.         {
  48.                 printf("cannot open file /dev/mem\n");
  49.                 return 0;
  50.         }
  51.         
  52.         map_addr = mmap(0, phymem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, phymem_addr);
  53.         strcpy(map_addr, argv[1]);
  54.         munmap(map_addr, phymem_size);
  55.         close(map_fd);
  56.         return 0;
  57.         
  58. }
复制代码
以上为大神所做与本人无任何关系

论坛徽章:
0
3 [报告]
发表于 2010-11-27 16:56 |只看该作者

论坛徽章:
0
4 [报告]
发表于 2010-11-27 17:22 |只看该作者
相当不错,赞,谢谢

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
5 [报告]
发表于 2010-11-28 12:29 |只看该作者
呵呵,很荣幸啊。是偶的拙作。

至于 /dev/mem 能否被读取或者映射,也是和内核版本以及内核配置有关的。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
6 [报告]
发表于 2010-11-28 12:30 |只看该作者
这个毕竟相当于读到了系统的内存空间,牵涉到了安全的问题
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP