由于引入了 node 节点这个概念,所以在 DISCONTIGMEM 非连续内存模型下 page_to_pfn 与 pfn_to_page 的计算逻辑就比 FLATMEM 内存模型下的计算逻辑多了一步定位 page 所在 node 的操作。 通过arch_pfn_to_nid 可以根据物理页的 PFN 定位到物理页所在 node。 通过page_to_nid 可以根据物理页结构 struct page ...
2 __page_to_pfn:((unsigned long)((page) - mem_map) + ARCH_PFN_OFFSET) 就是简单地和mem_map进行加减操作(最后那个OFFSET可以无视,默认0),由于mem_map也是struct page*类型,所以相加减就能得到对应的pfn(数组index)和对应的struct page*,如图 1 #define phys_to_page(phys) (pfn_to_page(phys >>...
例如page_to_phys, 通过page_to_pfn宏取得相应的pfn后,还记得PAGE_SHIFT吗,假设pfn是1,左移12位,就是4096,也就是第二个对应的物理页的位置,这样就取得了物理地址(虽然内核在虚拟地址中是在高地址的,但是在物理地址中是从0开始的,所以这里也是从0开始) 1#definevirt_to_page(kaddr) pfn_to_page(__pa(k...
virt_to_phys(buf)>>PAGE_SHIFT,//与物理内存对应的页帧号,物理地址右移12位 //说明: 向后面移动12位相当于除4096 ,为了得到页编号 vma->vm_end - vma->vm_start,//映射区域大小,一般是页大小的整数倍 vma->vm_page_prot))//保护属性, { return -EAGAIN; } printk("tiny4412_mmap\n"); return ...
page_to_phys(skb_frag_page(frag)); bufend += offset + size - 1; if (unlikely(adapter->pcix_82544 && !(bufend & 4) && size > 4)) size -= 4; buffer_info->length = size; buffer_info->time_stamp = jiffies; buffer_info->mapped_as_page = true; ...
md->virtual>=PAGE_OFFSET&&md->virtual< FIXADDR_START && (md->virtual< VMALLOC_START || md->virtual>=VMALLOC_END)){ pr_warn("BUG:mappingfor0x%08llxat0x%08lxoutofvmallocspace ", (longlong)__pfn_to_phys((u64)md->pfn),md->virtual); ...
该区域的线性地址和物理地址存在线性转换关系「线性地址 =PAGE_OFFSET+ 物理地址」也可以用virt_to_phys()函数将内核虚拟空间中的线性地址转化为物理地址。 高端内存线性地址空间 内核空间线性地址从 896M 到 1G 的区间,容量 128MB 的地址区间是高端内存线性地址空间,为什么叫高端内存线性地址空间?下面给你解释一下...
__va(x)则相反,把低端物理内存空间的地址转换成对应的内核逻辑地址,相当于((void *)__phys_to_virt((unsigned long)(x))) 该区域的内存分配函数:kmalloc/kfree和__get_free_page都是从低端内存来分配内存 第六个区域:高端内存vmalloc区 该区域是属于linux内核的高端内存地址,该区域分配的虚拟地址是连续的,...
(vma,//虚拟内存区域,即设备地址将要映射到这里vma->vm_start,//虚拟空间的起始地址virt_to_phys(buf)>>PAGE_SHIFT,//与物理内存对应的页帧号,物理地址右移12位//说明: 向后面移动12位相当于除4096 ,为了得到页编号vma->vm_end-vma->vm_start,//映射区域大小,一般是页大小的整数倍vma->vm_page_prot)...