linux使用hugetlbfs的方式来支持巨页,也成为大页。
网上看到有人说巨页不支持read,和write调用,只支持mmap,但是看3.10内核代码的时候发现:
const struct file_operations hugetlbfs_file_operations = {
.read = hugetlbfs_read,--------------------------------初始化了。 .mmap = hugetlbfs_file_mmap, .fsync = noop_fsync, .get_unmapped_area = hugetlb_get_unmapped_area, .llseek = default_llseek,};查看vfs_read代码,要确定下是否hugetlbfs_read就是file->f_op->read
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{ ssize_t ret;if (!(file->f_mode & FMODE_READ))
return -EBADF; if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read)) return -EINVAL; if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) return -EFAULT;ret = rw_verify_area(READ, file, pos, count);
if (ret >= 0) { count = ret; if (file->f_op->read) ret = file->f_op->read(file, buf, count, pos);
使用如下测试代码分别测试:
#include <fcntl.h>
#include <sys/mman.h> #include <errno.h> #include <unistd.h>#include <stdio.h>#define MAP_LENGTH (10*1024*1024)
#define TEST_PATH ("/mnt/huge_caq/test") #define TEST_READ 1 #define TEST_WRITE 0 #define TEST_MMAP 1int main()
{ int fd; void * addr; ssize_t ret=0;/* create a file in hugetlb fs */
fd = open(TEST_PATH, O_CREAT | O_RDWR); if(fd < 0){ perror("Err: "); return -1; } #if 0 #if TEST_WRITE ret = write(fd,"hello\r\n",7); perror("Err: "); #endif #endif #if TEST_READ char buf[10]; ret = read(fd,buf,7); printf("read ret=%d\r\n",ret); #endif #if TEST_MMAP /* map the file into address space of current application process */ addr = mmap(0, MAP_LENGTH, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(addr == MAP_FAILED){ perror("Err: "); close(fd); unlink(TEST_PATH); return -1; }/* from now on, you can store application data on huage pages via addr */
memcpy(addr,"hello\r\n",7); #if TEST_WRITE ret = write(fd,"hello\r\n",7); perror("Err: "); #endif#if TEST_READ
memset(buf,0,10); ret = read(fd,buf,7); if(ret) { printf("read ret=%d,buf=%s\r\n",ret,buf); } #endif munmap(addr, MAP_LENGTH); #if TEST_READ memset(buf,0,10); ret = read(fd,buf,7); printf("read ret=%d\r\n",ret); #endif #endif close(fd); unlink(TEST_PATH); return 0; }然后gdb跟踪如下,发现是可以读的,读出来数据也是正常的。
54 memset(buf,0,10);
(gdb) 55 ret = read(fd,buf,7);(gdb) 56 if(ret)(gdb) p ret$1 = 7(gdb) p buf$2 = "hello\r\n\000\000"
使用如下脚本确定file->f_op->read的对应函数
probe kernel.function("vfs_read").return
{ #print_backtrace(); if(($count==7)&&($file->f_op)&&($file->f_op->read)) { printf("begin pid=%d,execname=%s,f_op=%s,read=%s,aio=%x\r\n",pid(),execname(),symname($file->f_op),symname($file->f_op->read),$file->f_op->aio_read); }}
begin pid=30371,execname=main.o,f_op=hugetlbfs_file_operations,read=hugetlbfs_read,aio=0,没错,就是hugetlbfs_read。
从测试结果看,是支持read的。至于从哪个内核版本支持的,没有继续研究,有兴趣的同学可以跟一下git的记录。