kmalloc申请的内存映射到用户态的问题

发布于 2022-09-30 11:44:30 字数 23115 浏览 38 评论 0

我最近写一个内存映射的模块,上网查了些资料,自己也写了测试程序,可是映射出现问题:

  1. #include <linux/module.h>
  2. #include <linux/slab.h>
  3. #include <linux/init.h>
  4. #include <linux/kthread.h>
  5. #include <asm/uaccess.h>
  6. #include <linux/proc_fs.h>
  7. #include <linux/err.h>
  8. #include <linux/mm.h>
  9. #include <asm/page.h>
  10. MODULE_AUTHOR("cwj@126.com");
  11. MODULE_DESCRIPTION("KENEL_MAP.DEMO");
  12. MODULE_LICENSE("GPL");
  13. #define MEM_SHARE_DIR "mem_share_dir"
  14. #define MEM_SHARE_ADDR "mem_share_addr"
  15. #define MEM_SHARE_SIZE "mem_share_size"
  16. #define MEM_SIZE 100
  17. #define PARM_SIZE 32
  18. unsigned long addr;
  19. char addr_py[PARM_SIZE];
  20. char size_py[PARM_SIZE];
  21. unsigned long addr_cnt_len;
  22. int i;
  23. static struct task_struct *thread_map;
  24. static struct proc_dir_entry *mem_share_dir;
  25. static struct proc_dir_entry *mem_share_addr;
  26. static struct proc_dir_entry *mem_share_size;
  27. static unsigned char *p1, *p2, *p3;
  28. long atol(const char *str)
  29. {
  30.         unsigned int index;
  31.         unsigned int num;
  32.         int ret;
  33.        
  34.         ret = 0;
  35.         index = 1;
  36.         num = 0;
  37.        
  38.         //计算字符串的长度(strlen的实现,字符串中只包含数字字符)
  39.         while(*str)
  40.         {
  41.                 if(*str < '0' || *str > '9') //判断字符是否是数字
  42.                 {
  43.                         return -1;
  44.                 }
  45.                 str++;
  46.                 num++;
  47.         }
  48.        
  49.         //转换字符到相应的数字,这里最好的数据结构描述应该是栈
  50.         while(str--, num--)
  51.         {
  52.                 ret += index * (*str - '0');
  53.                 index *= 10;
  54.         }
  55.        
  56.         return ret;
  57. }
  58. static int proc_read_addr(char *page, char **start, off_t off, int count, int *eof, void *data)
  59. {
  60.         int ret;
  61.        
  62.         ret = 0;
  63.        
  64.         if(off > 0)
  65.         {
  66.                 printk("copy has finished !\n");
  67.                 return ret;
  68.         }
  69.         if(addr == 0)
  70.         {
  71.                 return ret;
  72.     }
  73.         sprintf(page, "%lu", addr);
  74.         printk("page =%s, addr = %lu\n", page, addr);
  75.         ret = PARM_SIZE;
  76.        
  77.         return ret;
  78. }
  79. static int proc_write_addr(struct file *fp, const char *buf, unsigned long count, void *data)
  80. {
  81.         int ret;
  82.         memset(addr_py, 0, PARM_SIZE);
  83.        
  84.         ret = count;
  85.        
  86.         if(count > PARM_SIZE && count == 0)
  87.         {
  88.                 printk("buf fault!\n");
  89.                 return 0;
  90.         }
  91.         if(copy_from_user(addr_py, buf, count))
  92.         {
  93.                 printk("copy_from_user fault!\n");
  94.                 return -1;
  95.         }
  96.                
  97.         return ret;
  98. }
  99. static int proc_read_size(char *page, char **start, off_t off, int count, int *eof, void *data)
  100. {
  101.         int ret;
  102.        
  103.         ret = 0;
  104.        
  105.         if(off > 0)
  106.         {
  107.                 printk("copy has finished !\n");
  108.                 return ret;
  109.         }
  110.        
  111.         if(addr_cnt_len == 0)
  112.         {
  113.                 return 0;
  114.         }
  115.        
  116.         sprintf(page, "%lu", addr_cnt_len);
  117.         ret = PARM_SIZE;
  118.        
  119.         return ret;
  120. }
  121. static int proc_write_size(struct file *fp, const char *buf, unsigned long count, void *data)
  122. {
  123.         int ret;
  124.         memset(size_py, 0, PARM_SIZE);
  125.        
  126.         ret = count;
  127.        
  128.         if(count > PARM_SIZE && count == 0)
  129.         {
  130.                 printk("buf fault!\n");
  131.                 return 0;
  132.         }
  133.        
  134.         if(copy_from_user(size_py, buf, count))
  135.         {
  136.                 printk("copy_from_user fault!\n");
  137.                 return -1;
  138.         }
  139.        
  140.         addr_cnt_len = atol(size_py);
  141.        
  142.         return ret;
  143. }
  144. static int thread_map_func(void *data)
  145. {
  146.         if(kthread_should_stop())
  147.                 return 0;
  148.         while(p1 || p2 || p3)
  149.         {
  150.                 set_current_state(TASK_UNINTERRUPTIBLE);
  151.                
  152.                 if(kthread_should_stop())
  153.                         break;
  154.                
  155.                 if(i == 3 && addr_cnt_len == 0)
  156.                 {
  157.                         break;
  158.                 }
  159.                
  160.                 if(addr_cnt_len != 0)
  161.                         goto __next;
  162.                
  163.                 if(p1 && i == 0)
  164.                 {
  165.                         SetPageReserved(virt_to_page(p1));
  166.                         addr = __pa(p1);
  167.                         addr_cnt_len = 27;
  168.                         i++;
  169.                 }
  170.                 else if(p2 && i == 1)
  171.                 {
  172.                         SetPageReserved(virt_to_page(p2));
  173.                         addr = __pa(p2);
  174.                         addr_cnt_len = 27;
  175.                         i++;
  176.                 }
  177.                 else if(p3 && i == 2)
  178.                 {
  179.                         SetPageReserved(virt_to_page(p3));
  180.                         addr = __pa(p3);
  181.                         addr_cnt_len = 27;
  182.                         i++;
  183.                 }
  184.                 printk("py = %lu\n", addr);
  185.         __next:
  186.                 schedule_timeout(50 * HZ);
  187.         }
  188.         return 0;
  189. }
  190. static int __init init_kernel_map(void)
  191. {
  192.         thread_map = NULL;
  193.         mem_share_dir = NULL;
  194.         mem_share_addr = NULL;
  195.         mem_share_size = NULL;
  196.        
  197.         mem_share_dir = proc_mkdir(MEM_SHARE_DIR, NULL);
  198.         if(mem_share_dir == NULL)
  199.         {
  200.                 printk("proc create fault!\n");
  201.                 return 0;
  202.         }
  203.         mem_share_addr = create_proc_entry(MEM_SHARE_ADDR, 0644, mem_share_dir);
  204.         if(mem_share_addr == NULL)
  205.         {
  206.                 remove_proc_entry(MEM_SHARE_DIR, NULL);
  207.                 printk("mem_share_addr fault!\n");
  208.                 return 0;
  209.         }
  210.         mem_share_addr->read_proc = proc_read_addr;
  211.         mem_share_addr->write_proc = proc_write_addr;
  212.         mem_share_addr->uid = 0;
  213.         mem_share_addr->gid = 0;
  214.        
  215.         mem_share_size = create_proc_entry(MEM_SHARE_SIZE, 0644, mem_share_dir);
  216.         if(mem_share_size == NULL)
  217.         {
  218.                 remove_proc_entry(MEM_SHARE_ADDR, mem_share_dir);
  219.                 remove_proc_entry(MEM_SHARE_DIR, NULL);
  220.                 printk("mem_share_size fault!\n");
  221.                 return 0;
  222.         }
  223.         mem_share_size->read_proc = proc_read_size;
  224.         mem_share_size->write_proc = proc_write_size;
  225.         mem_share_size->uid = 0;
  226.         mem_share_size->gid = 0;
  227.         thread_map = kthread_create(thread_map_func, NULL, "kernel_mem_share");
  228.         if(IS_ERR(thread_map))
  229.         {
  230.                 printk("thread create fault!\n");
  231.                 return 0;
  232.         }
  233.        
  234.         p1 = kmalloc(MEM_SIZE, GFP_KERNEL);
  235.         p2 = kmalloc(MEM_SIZE, GFP_KERNEL);
  236.         p3 = kmalloc(MEM_SIZE, GFP_KERNEL);
  237.         memset(p1, 0, MEM_SIZE);
  238.         memset(p2, 0, MEM_SIZE);
  239.         memset(p3, 0, MEM_SIZE);
  240.        
  241.         memcpy(p1, "111111111111111111111111111", 27);
  242.         memcpy(p2, "222222222222222222222222222", 27);
  243.         memcpy(p3, "333333333333333333333333333", 27);
  244.        
  245.         wake_up_process(thread_map);
  246.        
  247.         return 0;
  248. }
  249. static void __exit exit_kernel_map(void)
  250. {
  251.         if(p1)
  252.         {
  253.                 ClearPageReserved(virt_to_page(p1));
  254.                 kfree(p1);
  255.                 p1 = NULL;
  256.         }
  257.         if(p2)
  258.         {
  259.                 ClearPageReserved(virt_to_page(p2));
  260.                 kfree(p2);
  261.                 p2 = NULL;
  262.         }
  263.         if(p3)
  264.         {
  265.                 ClearPageReserved(virt_to_page(p3));
  266.                 kfree(p3);
  267.                 p3 = NULL;
  268.         }
  269.        
  270.         remove_proc_entry(MEM_SHARE_ADDR, mem_share_dir);
  271.         remove_proc_entry(MEM_SHARE_SIZE, mem_share_dir);
  272.         remove_proc_entry(MEM_SHARE_DIR, NULL);
  273.        
  274.         if(thread_map)
  275.         {
  276.                 kthread_stop(thread_map);
  277.                 thread_map = NULL;
  278.         }
  279. }
  280. module_init(init_kernel_map);
  281. module_exit(exit_kernel_map);

复制代码

  1. 用户态:
  2. [code]#include <stdio.h>
  3. #include <unistd.h>
  4. #include <sys/stat.h>
  5. #include <sys/mman.h>
  6. #include <fcntl.h>
  7. #include <sys/types.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #define MEM_SIZE 100
  11. #define MEM_ADDR_SIZE 32
  12. #define PAGE_SIZE 4096
  13. unsigned long addr;
  14. unsigned long addr_cnt_size;
  15. char _addr[MEM_ADDR_SIZE];
  16. char addr_cnt_len[MEM_ADDR_SIZE];
  17. char _buf[MEM_SIZE];
  18. char *map_addr;
  19. int get_mem(int fd, unsigned long _addr, char *buf, unsigned long size)
  20. {
  21.         unsigned long size_cpy;
  22.        
  23.         size_cpy = size;
  24.        
  25.         if(size % PAGE_SIZE)
  26.                 size = (size / PAGE_SIZE + 1) << 12;
  27.         else
  28.                 size = (size / PAGE_SIZE) << 12;
  29.                
  30.         map_addr =(char *)mmap(0, size , PROT_READ | PROT_WRITE, MAP_SHARED, fd, _addr);
  31.         perror("mmap");
  32.         if(!map_addr)
  33.         {
  34.                 return 0;
  35.         }
  36.         memcpy(buf, map_addr, size_cpy);
  37.         munmap(map_addr, size);
  38.         return 1;
  39. }
  40. int main(int argc, char *argv[])
  41. {
  42.         int fd;
  43.         int fd_addr;
  44.         int fd_size;
  45.         int i;
  46.        
  47.         i = 0;
  48.         fd = open("/dev/mem", O_RDWR);
  49.         fd_addr = open("/proc/mem_share_dir/mem_share_addr", O_RDWR);
  50.         fd_size = open("/proc/mem_share_dir/mem_share_size", O_RDWR);
  51.        
  52.         while(1)
  53.         {
  54.                 if(i == 0 || !addr_cnt_size){
  55.                 memset(_addr, 0, MEM_ADDR_SIZE);
  56.                 map_addr = NULL;
  57.                 read(fd_addr, _addr, MEM_ADDR_SIZE);
  58.                 printf("%s\n", _addr);
  59.                 addr = atol(_addr);
  60.                 if(addr == 0)
  61.                         continue;
  62.                 printf("addr = %u[%8lx]\n", addr);
  63.                
  64.                 memset(addr_cnt_len, 0, MEM_ADDR_SIZE);
  65.                 read(fd_size, addr_cnt_len, MEM_ADDR_SIZE);
  66.                 addr_cnt_size = atol(addr_cnt_len);
  67.                 printf("size = %u[%8lx]\n", addr_cnt_size);
  68.                
  69.                 if(get_mem(fd, addr, _buf, addr_cnt_size))
  70.                 {
  71.                         i++;
  72.                         printf("mem_cnt = %s\n", _buf);
  73.                 }
  74.         }
  75.                 sleep(100);
  76.                
  77.                 if(i == 3)
  78.                 {
  79.                         break;
  80.                 }
  81.                
  82.         }
  83.        
  84.         close(fd_addr);
  85.         close(fd_size);
  86.         close(fd);
  87. }

复制代码上面是小弟写的用户态与内核态的例子,在运行该例子的时候,内核地址取的都对但是用户态映射不成功。
用户态程序运行后会出现如下的错误:

  1. 189023744
  2. addr = 189023744[ b444600]
  3. size = 27[      1b]
  4. mmap: Invalid argument
  5. Segmentation fault (core dumped)

复制代码kmalloc既然在实现上是调用的_get_free_pages()实现的,并且分配的是地址是连续的物理地址,大小也肯定是页的整数倍,我的程序理论上应该是可行的,请大家多多讨论,帮助小弟解决下,谢了啊!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

你怎么这么可爱啊 2022-10-07 11:44:36

回复  爱迟到

    map_addr =(char *)mmap(0, size , PROT_READ | PROT_WRITE, MAP_SHARED, fd, _add ...
chenrvmldd 发表于 2011-04-21 20:05

    写权限能不能用,关键看driver里面的mmap是怎么实现的,支不支持。

在风中等你 2022-10-07 11:44:36

要映射到用户空间,应该用remap_vmalloc_range这样的函数,我没看到你用。。。。

思念满溢 2022-10-07 11:44:35

回复 6# 爱迟到

    试完了之后告诉我一声

渡你暖光 2022-10-07 11:44:34

谢谢,我试下啊

月下凄凉 2022-10-07 11:44:34

回复 1# 爱迟到

    map_addr =(char *)mmap(0, size , PROT_READ | PROT_WRITE, MAP_SHARED, fd, _addr);
    兄弟,你把这个函数的PROT_WRITE这个选项去掉,用户权限级别不能写内核映射出来的内存,你试试

独木成林 2022-10-07 11:44:33

初学 者路 过.
你是 想要 在 上层 进行 映社 吗?
那 可 能 不行 .因 为 你 从 kernel 那到 的 那 个是 kernel space address, 上层 的function 是 没 法用 的 ,也 就是 那 个mmap会 出 错 .

说 错 勿 怪 ,偶 是 刚 从 win 投诚过来 的.

心的位置 2022-10-07 11:44:32

内核是不是不支持dev/mem映射到用户态了。貌似需要打开开关编译才行。

猛虎独行 2022-10-07 11:44:32

补充下顺便顶下,网上大部分都是那种字符设备映射的例子,我不想那样做,这样做怎么会出错呢?大家给点意见啊

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文