[root@localhost ~]# cd /sys/kernel/mm/hugepages
[root@localhost hugepages]# ls -al
total 0
drwxr-xr-x. 4 root root 0 6月 5 04:53 .
drwxr-xr-x. 5 root root 0 6月 5 04:53 ..
drwxr-xr-x. 2 root root 0 6月 6 07:27 hugepages-1048576kB
drwxr-xr-x. 2 root root 0 6月 6 07:27 hugepages-2048kB
[root@localhost hugepages]# cd hugepages-2048kB
[root@localhost hugepages-2048kB]# ls
free_hugepages nr_hugepages nr_hugepages_mempolicy nr_overcommit_hugepages resv_hugepages surplus_hugepages
[root@localhost hugepages-2048kB]#
在dpdk中主要通过eal_hugepage_info_init 来会的大页的信息,也就是主要parse /sys/kernel/mm/hugepages 这个目录下面的内容
这个目录下面的内容如上所示
int
eal_hugepage_info_init(void)
{
const char dirent_start_text[] = "hugepages-";
const size_t dirent_start_len = sizeof(dirent_start_text) - 1;
unsigned i, num_sizes = 0;
DIR *dir;
struct dirent *dirent;
#打开包含大页的目录 /sys/kernel/mm/hugepages
dir = opendir(sys_dir_path);
if (dir == NULL) {
RTE_LOG(ERR, EAL,
"Cannot open directory %s to read system hugepage info\n",
sys_dir_path);
return -1;
}
#从本例看大页的目录下有两个子目录,这两个子目录是按照大页的size 来分类的,所以下面这个for 循环会循环两次
for (dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) {
struct hugepage_info *hpi;
#比较目录名是否以开始 ,例如 hugepages-2048kB
if (strncmp(dirent->d_name, dirent_start_text,
dirent_start_len) != 0)
continue;
#大页的size的种类不能超过3个,本例中就刚好是两个
if (num_sizes >= MAX_HUGEPAGE_SIZES)
break;
#得到要保存大页信息的全局变量
hpi = &internal_config.hugepage_info[num_sizes];
#根据目录的name得到大页的size ,例如hugepages-1048576kB的size就是页大小就是2048K
hpi->hugepage_sz =
rte_str_to_size(&dirent->d_name[dirent_start_len]);
#得到大页的目录
hpi->hugedir = get_hugepage_dir(hpi->hugepage_sz);
/* first, check if we have a mountpoint */
#如果大页的目录为null,则可能还没有mount hugetlbfs
if (hpi->hugedir == NULL) {
uint32_t num_pages;
num_pages = get_num_hugepages(dirent->d_name);
if (num_pages > 0)
RTE_LOG(NOTICE, EAL,
"%" PRIu32 " hugepages of size "
"%" PRIu64 " reserved, but no mounted "
"hugetlbfs found for that size\n",
num_pages, hpi->hugepage_sz);
continue;
}
/* try to obtain a writelock */
#打开这个目录,并保存目录描述符
hpi->lock_descriptor = open(hpi->hugedir, O_RDONLY);
/* if blocking lock failed */
#锁定这个目录
if (flock(hpi->lock_descriptor, LOCK_EX) == -1) {
RTE_LOG(CRIT, EAL,
"Failed to lock hugepage directory!\n");
break;
}
/* clear out the hugepages dir from unused pages */
if (clear_hugedir(hpi->hugedir) == -1)
break;
/* for now, put all pages into socket 0,
* later they will be sorted */
#得到实际大页的个数
hpi->num_pages[0] = get_num_hugepages(dirent->d_name);
#ifndef RTE_ARCH_64
/* for 32-bit systems, limit number of hugepages to
* 1GB per page size */
#如果是32 位系统的话,则大页不能超过1GB
hpi->num_pages[0] = RTE_MIN(hpi->num_pages[0],
RTE_PGSIZE_1G / hpi->hugepage_sz);
#endif
num_sizes++;
}
#关掉这个目录/sys/kernel/mm/hugepages
closedir(dir);
/* something went wrong, and we broke from the for loop above */
if (dirent != NULL)
return -1;
internal_config.num_hugepage_sizes = num_sizes;
/* sort the page directory entries by size, largest to smallest */
#对已经保存的大页按照size 从小到大排序
qsort(&internal_config.hugepage_info[0], num_sizes,
sizeof(internal_config.hugepage_info[0]), compare_hpi);
/* now we have all info, check we have at least one valid size */
#再次检查保存大页的全局变量中目录和大约的个数不能为null
for (i = 0; i < num_sizes; i++)
if (internal_config.hugepage_info[i].hugedir != NULL &&
internal_config.hugepage_info[i].num_pages[0] > 0)
return 0;
/* no valid hugepage mounts available, return error */
return -1;
}