hugetlbfs在加载时,会向内核注册hugetlbfs文件系统,并mount hugetlbfs文件系统到内核中,结果保存到hugetlbfs_vfsmount中。这个mount,没有使用什么参数,因此对应到默认的hstate。
3. 使用巨页
有两种方式,mmap方式和共享内存方式(shmget/shmat)。
但是,无论是通过哪种方式,最终都是通过对一个hugetlbfs类型的文件做内存映射而实现的(通过file->f_op->mmap完成)。
a. mmap方式
这种方式,需要先通过如下命令mount一个hugetlbfs文件系统,通过pagesize指定页面大小。
mount -t hugetlbfs none /mnt/path/to/hugetlbfs -o pagesize=2048K
这样的话,新挂载的文件系统,与页面大小为2048K的hstate相关联。。
接下来,在/mnt/path/to/hugetlbfs下面创建文件,然后打开文件并通过mmap进行内存映射即可。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERR_DBG_PRINT(fmt, args...) \
do \
{ \
printf("ERR_DBG:%s(%d)-%s:\n"fmt": %s\n", __FILE__,__LINE__,__FUNCTION__,##args, strerror(errno)); \
} while (0)
/* mmap方式可以使用指定尺寸的巨页池 */
int main(int argc, char *argv[])
{
int ret = system("mount -t hugetlbfs none /home/shared/sunmingbao/hugetlb_test -o pagesize=2048K");
int fd = open("/home/shared/sunmingbao/hugetlb_test/hehe.txt", O_CREAT | O_RDWR, 0755);
char *huge_mem = mmap(NULL, 2048*1024*5, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0);
if (ret<0)
{
ERR_DBG_PRINT("mount fail:");
return 0;
}
if (fd<0)
{
ERR_DBG_PRINT("open fail:");
return 0;
}
if (-1 == (int)(unsigned long)huge_mem)
{
ERR_DBG_PRINT("mmap fail:");
return 0;
}
printf("press any key to access huge page\n");
getchar();
memset(huge_mem, 0, 2048*1024*5);
printf("press any key to delete huge page\n");
getchar();
/* 下面代码一执行,内存就释放回巨页池了 */
if (unlink("/home/shared/sunmingbao/hugetlb_test/hehe.txt")==-1)
ERR_DBG_PRINT("unlink fail:");
return 0;
}
b. 共享内存方式
这种方式,不需要上面提到的mount及创建文件操作。直接用shmget和shmat,即可使用巨页内存。
虽然用户没有mount及创建文件,但shmget内部还是创建了一个文件,并且是在上面提到的hugetlbfs_vfsmount挂载点下面。这样的话,就与mmap方式殊途同归了。hugetlbfs_vfsmount挂载点对应的是默认的hstate,因此所用巨页的页面大小也是默认的。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERR_DBG_PRINT(fmt, args...) \
do \
{ \
printf("ERR_DBG:%s(%d)-%s:\n"fmt": %s\n", __FILE__,__LINE__,__FUNCTION__,##args, strerror(errno)); \
} while (0)
/* shmget方式只能使用默认尺寸的巨页池 */
int main(int argc, char *argv[])
{
key_t our_key = ftok("/home/shared/sunmingbao/hello.c", 6);
int shm_id = shmget(our_key, 2048*1024*5, IPC_CREAT|IPC_EXCL|SHM_HUGETLB);
char *huge_mem = shmat(shm_id, NULL, 0);
if (-1 == (int)our_key)
{
ERR_DBG_PRINT("ftok fail:");
return 0;
}
if (-1 == shm_id)
{
ERR_DBG_PRINT("shmget fail:");
return 0;
}
if (-1 == (int)(unsigned long)huge_mem)
{
ERR_DBG_PRINT("shmat fail:");
return 0;
}
printf("press any key to access huge page\n");
getchar();
memset(huge_mem, 0, 2048*1024*5);
printf("press any key to delete huge page\n");
getchar();
/* 下面代码一执行,内存就释放回巨页池了 */
shmdt(huge_mem);
if (shmctl(shm_id, IPC_RMID, NULL)==-1)
ERR_DBG_PRINT("shmctl fail:");
return 0;
}