其中页a、a+1类似的表示连续的物理页。
dpdk通过事先申请的大页,mmap对应的大页dir获得内存。可以看出,程序mmap每个页时,虽然物理页可能连续,但返回的虚拟地址却不一定是连续的。而且,返回的内存不会固定在某个socket上。为了高效的使用内存,需要重新组织内存,并对其进行管理。
组织的方式:
dpdk使用linux提供的获取大页、页表、numa节点表、mmap功能重新组织内存。
大页:最多可以同时存在3中大页。一般只是用2M的大页。linux中获取大页相关信息是通过访问解析/sys/kernel/mm/hugepages、/proc/meminfo、/proc/mounts等内容得到的。
页表:linux中每个进程的页表对应的文件是/proc/pid/pagemap,本进程的页表是/proc/self/pagemap。/proc/pid/pagemap中的内容(每一个页表项有64位)如下:
* Bits 0-54 page framenumber (PFN) if present
* Bits 0-4 swap type ifswapped
* Bits5-54 swap offset if swapped
*Bit 55 pte is soft-dirty (see Documentation/vm/soft-dirty.txt)
*Bit 56 page exclusively mapped (since 4.2)
* Bits57-60 zero
*Bit 61 page is file-page or shared-anon (since 3.5)
*Bit 62 page swapped
* Bit 63 page present
注意:大页是不会被swap的,是常驻内存的,所以每个大页对应的页表项中PFN都对应物理内存,不会对应到swap区或者外设内存中。
numa节点表:linux中每个物理页所在的numa socket表对应的文件是/proc/pid/numa_maps,本进程的numa socket表是/proc/self/numa_maps。
/proc/pid/numa_maps中的内容大致如下:
address policy mapping details
00400000 defaultfile=/usr/local/bin/app mapped=1 active=0 N3=1 kernelpagesize_kB=4
00600000 defaultfile=/usr/local/bin/app anon=1 dirty=1 N3=1 kernelpagesize_kB=4
3206000000 default file=/lib64/ld-2.12.so mapped=26 mapmax=6 N0=24 N3=2kernelpagesize_kB=4
320621f000 default file=/lib64/ld-2.12.so anon=1 dirty=1 N3=1 kernelpagesize_kB=4
3206220000 default file=/lib64/ld-2.12.so anon=1 dirty=1 N3=1 kernelpagesize_kB=4
3206221000 default anon=1 dirty=1 N3=1 kernelpagesize_kB=4
3206800000 default file=/lib64/libc-2.12.so mapped=59 mapmax=21 active=55 N0=41 N3=18kernelpagesize_kB=4
320698b000 default file=/lib64/libc-2.12.so
3206b8a000 default file=/lib64/libc-2.12.so anon=2 dirty=2 N3=2 kernelpagesize_kB=4
3206b8e000 default file=/lib64/libc-2.12.so anon=1 dirty=1 N3=1 kernelpagesize_kB=4
3206b8f000 default anon=3 dirty=3 active=1 N3=3 kernelpagesize_kB=4
7f4dc10a2000 default anon=3 dirty=3 N3=3 kernelpagesize_kB=4
7f4dc10b4000 default anon=2 dirty=2 active=1 N3=2 kernelpagesize_kB=4
7f4dc1200000 default file=/anon_hugepage\040(deleted) huge anon=1 dirty=1 N3=1kernelpagesize_kB=2048
7fff335f0000 default stack anon=3 dirty=3 N3=3 kernelpagesize_kB=4
7fff3369d000 default mapped=1 mapmax=35 active=0 N3=1 kernelpagesize_kB=4
Where:"address" is the starting address for the mapping;
"policy"reports the NUMA memory policy set for the mapping (seevm/numa_memory_policy.txt);
"mapping details" summarizes mappingdata such as mapping type, page usage counters, node locality page counters (N0== node0, N1 == node1, ...) and the kernel page size, in KB, that is backingthe mapping up.把每页信息都放到结构struct hugepage_file tmp_hp[]中。
/**
* Structure used to storeinformations about hugepages that we mapped
* through the files inhugetlbfs.
*/
struct hugepage_file {
void*orig_va; /**< virtual addr offirst mmap() */
void *final_va; /**< virtual addr of 2nd mmap() */
uint64_t physaddr; /**< physical addr */
size_t size; /**< the page size 页大小(多种大页)*/
int socket_id; /**< NUMA socket ID */
int file_id; /**< the '%d' in HUGEFILE_FMT每种大页都从0开始*/
int memseg_id; /**< the memory segment to which pagebelongs */
char filepath[MAX_HUGEPAGE_PATH]; /**< pathto backing file on filesystem */
};次进程主要是把重新组织的内存映射到进程中。