谁有mmap与用户层通信的代码?
时间:2010-04-30
来源:互联网
找了一个简单的,但有问题。
内核模块:
static unsigned long p = 0;
static int __init init(void)
{
p = __get_free_pages(GFP_KERNEL, 0); //
SetPageReserved(virt_to_page(p));
printk("<1> p = 0x%08x\n", p);
strcpy(p, "Hello world!\n");
return 0;
}
static void __exit fini(void)
{
ClearPageReserved(virt_to_page(p));
free_pages(p, 0);
return;
}
module_init(init);
module_exit(fini);
用户层程序:
#define PAGE_SIZE (4*1024)
#define PAGE_OFFSET 0xc0000000
#define KERNEL_VIRT_ADDR 0xcf9e5000 //这里是硬编址的, 可以通过ioctl 或者proc来实现的。
int main()
{
char *buf;
int fd;
unsigned long phy_addr;
fd=open("/dev/mem",O_RDWR);
if(fd == -1)
perror("open");
phy_addr=KERNEL_VIRT_ADDR - PAGE_OFFSET;
buf=mmap(0, PAGE_SIZE,
PROT_READ|PROT_WRITE, MAP_SHARED,
fd, phy_addr);
if(buf == MAP_FAILED)
perror("mmap");
puts(buf);//打印共享内存的内容
munmap(buf,PAGE_SIZE);
close(fd);
return 0;
}
模块可以正常加载,但用户程序运行会崩溃,就是物理地址(phy_addr)那里出错,应该怎样确定该地址?
内核模块:
static unsigned long p = 0;
static int __init init(void)
{
p = __get_free_pages(GFP_KERNEL, 0); //
SetPageReserved(virt_to_page(p));
printk("<1> p = 0x%08x\n", p);
strcpy(p, "Hello world!\n");
return 0;
}
static void __exit fini(void)
{
ClearPageReserved(virt_to_page(p));
free_pages(p, 0);
return;
}
module_init(init);
module_exit(fini);
用户层程序:
#define PAGE_SIZE (4*1024)
#define PAGE_OFFSET 0xc0000000
#define KERNEL_VIRT_ADDR 0xcf9e5000 //这里是硬编址的, 可以通过ioctl 或者proc来实现的。
int main()
{
char *buf;
int fd;
unsigned long phy_addr;
fd=open("/dev/mem",O_RDWR);
if(fd == -1)
perror("open");
phy_addr=KERNEL_VIRT_ADDR - PAGE_OFFSET;
buf=mmap(0, PAGE_SIZE,
PROT_READ|PROT_WRITE, MAP_SHARED,
fd, phy_addr);
if(buf == MAP_FAILED)
perror("mmap");
puts(buf);//打印共享内存的内容
munmap(buf,PAGE_SIZE);
close(fd);
return 0;
}
模块可以正常加载,但用户程序运行会崩溃,就是物理地址(phy_addr)那里出错,应该怎样确定该地址?
作者: cablink 发布时间: 2010-04-30
我这里有一篇总结,还有源码,LZ看一下:
http://blog.chinaunix.net/u/33048/showart_1271210.html
http://blog.chinaunix.net/u/33048/showart_1271210.html
作者: Godbach 发布时间: 2010-04-30
GOD老兄,你那篇BLOG里只有提到PROC,没有说MMAP啊。
回LZ:
#define KERNEL_VIRT_ADDR 0xcf9e5000
这个地址应该是你的KERNEL MODULE 的PRINTK那行打印出来的地址,不同机器上不一样的。你改了没?
回LZ:
#define KERNEL_VIRT_ADDR 0xcf9e5000
这个地址应该是你的KERNEL MODULE 的PRINTK那行打印出来的地址,不同机器上不一样的。你改了没?
作者: accessory 发布时间: 2010-04-30
模块内没有实现mmap。
示范代码
复制代码
【Note】:mem_map_reserve是2.4版本内核的函数,2.6内核用SetPageReserved取代之
示范代码
- /*内核模块加载函数*/
- int __init kmalloc_map_init(void)
- {
- //申请设备号,添加cdev结构体
- buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
- for (page = virt_to_page(buffer); page < virt_to_page(buffer + BUFFER_SIZE); page++)
- {
- mem_map_reserve(page);//置页为保留,virt_to_page()将内核虚拟地址转化为页
- }
- }
- /*mmap()函数*/
- static int kmalloc_map_mmap(struct file *filp, struct vm_area_struct *vma)
- {
- unsigned long page, pos;
- unsigned long start = (unsigned long)vma->vm_start;
- unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
- if (size > BUFFER_SIZE)
- {
- return - EINVAL;
- }
- pos = (unsigned long)buffer;
- /*映射buffer中的所有页*/
- while (size > 0)
- {
- page = virt_to_phys((void *)pos);
- if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
- return - EAGAIN;
- start += PAGE_SIZE;
- pos += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-
- /*
-
- **可否用io_remap_pfn_range(vma, vma->vm_start, virt_to_phys((void *)buffer) >> PAGE_SHIFT, vma->vm_end - vma->vm_start, PAGE_SHARED)来替代remap_page_range?
-
- **在Linux kernel 2.6.27中,已经找不到remap_page_range的实现,见Linux kernel change log: Changes remap_page_range to remap_pfn_range for 2.6.10 and above kernels
-
- */
- return 0;
- }
作者: sep 发布时间: 2010-05-01
前几天 在学习linux内核的内存管理时候找到了这么一个例子,不知道是否符合楼主的要求:
2.6.tar.gz (3.31 KB)
下面是这个例子的说明:
实例希望利用内存映射,将系统内核中的一部分虚拟内存映射到用户空间,以供应用程序读取——你可利用它进行内核空间到用户空间的大规模信息传输。因此我们将试图写一个虚拟字符设备驱动程序,通过它将系统内核空间映射到用户空间——将内核虚拟内存映射到用户虚拟地址。我们的例子程序将演示把vmalloc分配的内核虚拟地址映射到用户地址空间的全过程。
程序里主要应解决两个问题:
第一是将vmalloc分配的内核虚拟内存正确地转化成物理地址
因为内存映射先要获得被映射的物理地址,然后才能将其映射到要求的用户虚拟地址上。我们已经看到内核物理内存映射区域中的地址可以被内核函数virt_to_phys转换成实际的物理内存地址,但对于vmalloc分配的内核虚拟地址无法直接转化成物理地址,所以我们必须对这部分虚拟内存格外“照顾”——先将其转化成内核物理内存映射区域中的地址,然后在用virt_to_phys变为物理地址。
转化工作需要进行如下步骤:
a) 找到vmalloc虚拟内存对应的页表,并寻找到对应的页表项。
b) 获取页表项对应的页面指针
c) 通过页面得到对应的内核物理内存映射区域地址。
第二是当访问vmalloc分配区时,如果发现虚拟内存尚未被映射到物理页,则需要处理“缺页异常”。因此需要我们实现内存区域中的nopaga操作,以能返回被映射的物理页面指针,在我们的实例中就是返回上面过程中的内核物理内存映射区域中的地址。由于vmalloc分配的虚拟地址与物理地址的对应关系并非分配时就可确定,必须在缺页现场建立页表,因此这里不能使用remap_page_range方法,只能用vma的nopage方法一页一页的建立
程序组成
map_driver.c,它是以模块形式加载的虚拟字符驱动程序。该驱动负责将一定长的内核虚拟地址(vmalloc分配的)映射到设备文件上。其中主要的函数有——vaddress_to_kaddress()负责对vmalloc分配的地址进行页表解析,以找到对应的内核物理映射地址(kmalloc分配的地址);map_nopage()负责在进程访问一个当前并不存在的VMA页时,寻找该地址对应的物理页,并返回该页的指针。
test.c 它利用上述驱动模块对应的设备文件在用户空间读取读取内核内存。结果可以看到内核虚拟地址的内容(ok!),被显示在了屏幕上
PS:我也是内核新手,对这个例子是看到云里雾里的。如果这个例子真的对楼主有帮助,而楼主又能将其轻易看懂的话,希望能给我这个菜鸟讲解一下

下面是这个例子的说明:
实例希望利用内存映射,将系统内核中的一部分虚拟内存映射到用户空间,以供应用程序读取——你可利用它进行内核空间到用户空间的大规模信息传输。因此我们将试图写一个虚拟字符设备驱动程序,通过它将系统内核空间映射到用户空间——将内核虚拟内存映射到用户虚拟地址。我们的例子程序将演示把vmalloc分配的内核虚拟地址映射到用户地址空间的全过程。
程序里主要应解决两个问题:
第一是将vmalloc分配的内核虚拟内存正确地转化成物理地址
因为内存映射先要获得被映射的物理地址,然后才能将其映射到要求的用户虚拟地址上。我们已经看到内核物理内存映射区域中的地址可以被内核函数virt_to_phys转换成实际的物理内存地址,但对于vmalloc分配的内核虚拟地址无法直接转化成物理地址,所以我们必须对这部分虚拟内存格外“照顾”——先将其转化成内核物理内存映射区域中的地址,然后在用virt_to_phys变为物理地址。
转化工作需要进行如下步骤:
a) 找到vmalloc虚拟内存对应的页表,并寻找到对应的页表项。
b) 获取页表项对应的页面指针
c) 通过页面得到对应的内核物理内存映射区域地址。
第二是当访问vmalloc分配区时,如果发现虚拟内存尚未被映射到物理页,则需要处理“缺页异常”。因此需要我们实现内存区域中的nopaga操作,以能返回被映射的物理页面指针,在我们的实例中就是返回上面过程中的内核物理内存映射区域中的地址。由于vmalloc分配的虚拟地址与物理地址的对应关系并非分配时就可确定,必须在缺页现场建立页表,因此这里不能使用remap_page_range方法,只能用vma的nopage方法一页一页的建立
程序组成
map_driver.c,它是以模块形式加载的虚拟字符驱动程序。该驱动负责将一定长的内核虚拟地址(vmalloc分配的)映射到设备文件上。其中主要的函数有——vaddress_to_kaddress()负责对vmalloc分配的地址进行页表解析,以找到对应的内核物理映射地址(kmalloc分配的地址);map_nopage()负责在进程访问一个当前并不存在的VMA页时,寻找该地址对应的物理页,并返回该页的指针。
test.c 它利用上述驱动模块对应的设备文件在用户空间读取读取内核内存。结果可以看到内核虚拟地址的内容(ok!),被显示在了屏幕上
PS:我也是内核新手,对这个例子是看到云里雾里的。如果这个例子真的对楼主有帮助,而楼主又能将其轻易看懂的话,希望能给我这个菜鸟讲解一下
作者: cu_liang 发布时间: 2010-05-01
QUOTE:
前几天 在学习linux内核的内存管理时候找到了这么一个例子,不知道是否符合楼主的要求:
下面是这个例 ...
cu_liang 发表于 2010-05-01 23:19
下面是这个例 ...
cu_liang 发表于 2010-05-01 23:19
它这段代码应该是有问题的,不知道LS发现了没?
作者: new_learner 发布时间: 2010-07-30
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28