LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2650|回复: 3

何时分配物理内存?

[复制链接]
发表于 2009-5-4 21:00:41 | 显示全部楼层 |阅读模式
1:如果我们把一个文件映射到进程的地址空间,那以我们会在用户空间调用mmap函数,发出系统调用请求。下面是内核要做的事情:

           内核       :寻找一个VMA,并设置其中成员。插入进程VMA链表中,检查有无必要和相邻的VMA合并。然后调用驱动或者文件系统的mmap.
文件系统或驱动的MMAP:它的主任务是通过remap_pfn_range建立页表。
以上是我的看法,不知道对不对?请高手不吝赐教。

但是有一个问题,那么何时系统才会真正分配物理内存给进程呢,是在建立页表的同时吗?难道会是当我们访问VMA产生缺页时再通过nopage一页一页的分配吗?

2:remap_pfn_range(vma,vma->vm->start,vm->vm_pgoff,vm->vm_end-vm->vm_start,vm->vm_page_prot)
这个函数中的vm->vm_pgoff指的是什么?书上说物理地址页帧号,请问一下,此时页表还没建立,(因为本函数正是建立页表的)如何得知想要的物理地址页帧号?
其实vm->vm_pgoff是我们在用户空间调用mmap的offset参数右移PAGE_SHIFT。请问这到底是怎么回事?
 楼主| 发表于 2009-5-7 10:21:01 | 显示全部楼层
怎么没人回呢,请高人指点。
回复 支持 反对

使用道具 举报

发表于 2009-6-17 09:09:09 | 显示全部楼层
remap_pfn_range 通过你的页帧号来建立页表, 并映射到用户空间!
一般情况是你的驱动分配一块内存,然后在驱动的mmap中使用这块内存的 物理地址转成页帧号, 再调用remap_pfn_range!
假设1你是通过kmalloc(),get_free_pages()等分配的,这种内存页是不能通过remap_pfn_range()映射出去的,要对每个页面调用SetPageReserverd()标记为“保留”才可以,virt_to_phys()函数只是得到其物理地址,remap_pfn_range()中的第三个参数是要求物理页便的“帧”号,即pfn,所以你的phys还要“> > PAGE_SHIFT”操作
假设2你是通过vmalloc分配得来的,同上,不同的是要用vmalloc_to_pfn
3,用kmalloc,get_free_pages,vmalloc分配的物理内存页面最好还是不要用remap_pfn_page方法,建议使用VMA的nopage方法
4,对于这样的设备内存,最好对调用pgprot_nocached(vma-> vm_page_prot)后传给remap_pfn_range,防止处理器缓存
5,你写的是framebuffer驱动,最好是用fb_mmap(),可扩展

static int mmap_xxxxx(struct file *filp, struct vm_area_struct *vma)
{
        unsigned long start = vma->vm_start;
        unsigned long size = vma->vm_end - vma->vm_start;
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
        unsigned long page, pos;
       
        if(size > MMAP_MEM_SIZE)
                return -EINVAL;

        printk( "start=0x%08x offset=0x%08x\n", start, offset );
        printk( "kernel msg=%s\n", mmap_buf );
        pos = (unsigned long)mmap_buf + offset;
        page = virt_to_phys( pos ) >> PAGE_SHIFT ;
        if ( remap_pfn_range( vma, start, page, size, PAGE_SHARED )) {
                return -EAGAIN;
        }
        else {
                printk( "remap_pfn_range %u\n success\n", page );
        }
        vma->vm_flags &= ~VM_IO;
        vma->vm_flags |= VM_RESERVED;
        return 0;
}
回复 支持 反对

使用道具 举报

发表于 2009-6-17 09:14:56 | 显示全部楼层
还有就是
offset参数右移PAGE_SHIFT
就是得到页帧号, 前提是offset 是内核物理地址!
kmalloc, get_free_pages都可以通过 virt_to_phy取得
vmalloc 可以通过page_address( vmalloc_to_page( addr )  )取得
回复 支持 反对

使用道具 举报

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

本版积分规则

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