实验内容:在内核下面申请4K大小的内存(kmalloc申请的物理连续内存),在应用程序中通过mmap把内核态下申请的内存块映射到用户空间,然后在应用程序中通过read,write操作读写内核空间数据,最后读取用户态映射的地址空间,看内容是否和内核数据空间一致。
我的编译工具:
/opt/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gun/bin/arrch64-linux-gun-gcc
内核实现:
#include#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct proc_dir_entry *mmap_dir = NULL; static struct proc_dir_entry *mmap_file = NULL; struct self_data { int arry[1024]; }; int alloc_size = 0; struct self_data *p_mem = NULL; static int mmap_open(struct inode *p_node, struct file *p_file); static ssize_t mmap_read(struct file *p_file, char __user *p_buf, size_t size, loff_t * p_loff); static ssize_t mmap_write(struct file *p_file, const char __user *p_buf, size_t size, loff_t *p_loff); static int mmap_mmap(struct file *p_file, struct vm_area_struct *vma); static int mmap_release(struct inode *p_node, struct file *p_file); static const struct file_operations mmap_opts = { .owner = THIS_MODULE, .open = mmap_open, .read = mmap_read, .write = mmap_write, .mmap = mmap_mmap, .release = mmap_release, }; int mmap_release(struct inode *p_node, struct file *p_file) { return 0; } static int mmap_open(struct inode *p_node, struct file *p_file) { return simple_open(p_node, p_file); } static ssize_t mmap_read(struct file *p_file, char __user *p_buf, size_t size, loff_t * p_loff) { copy_to_user(p_buf, p_mem, size); return size; } static ssize_t mmap_write(struct file *p_file, const char __user *p_buf, size_t size, loff_t *p_loff) { copy_from_user(p_mem, p_buf, size); return size; } static int mmap_mmap(struct file *p_file, struct vm_area_struct *vma) { unsigned long phyaddr = 0; unsigned long size = vma->vm_end - vma->vm_start; int ret; if (p_mem) { phyaddr = __pa(p_mem); } if (phyaddr == 0) { pr_err("get phy addr failed!n"); } ret = remap_pfn_range(vma, vma->vm_start, phyaddr >> PAGE_SHIFT, size, PAGE_SHARED); if (ret != 0) { pr_err("remap_pfn_range failed!n"); } printk(KERN_EMERG"phyaddr = %p, remap size = %dn", phyaddr, size); return ret; } static int __init my_mmap_init(void) { mmap_dir= proc_mkdir("module_mmap", NULL); if (mmap_dir == NULL) { pr_err("proc_mkdie failed!n"); } mmap_file = proc_create("self_mmap", 0666, mmap_dir, &mmap_opts); if (mmap_file == NULL) { pr_err("proc_data failed!n"); } alloc_size = PAGE_ALIGN(sizeof(struct self_data)); p_mem = kmalloc(alloc_size, GFP_KERNEL); if (p_mem == NULL) { pr_err("kmalloc failed!n"); } memset(p_mem, 0, alloc_size); printk(KERN_EMERG"alloc size = %dn", alloc_size); return 0; } static void __exit my_mmap_exit(void) { if (p_mem) { kfree(p_mem); } if (mmap_dir) { } } module_init(my_mmap_init); module_exit(my_mmap_exit); MODULE_LICENSE("GPL v2");
Makefile 文件:
KERNDIR ?=
ARCH ?=
PWD := $(shell pwd)
CROSS_COMPILE ?=
CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)ld
obj-m := module_mmap.o
all:
$(MAKE) ARCH=$(ARCH) -C $(KERNDIR) M=${PWD} modules
用户态实现:
#include#include #include #include #include #include #include #include #include #include #include #include char *p_file = NULL; char buf[1024]; int main (void) { int fd = 0; int i; void *p_viraddr = NULL; ssize_t len; for (i = 0; i < 1024; i++) { buf[i] = 'r'; } fd = open("/proc/module_mmap/self_mmap", O_RDWR); if (fd < 0) { printf("file open failedn"); return 0; } p_viraddr = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (p_viraddr == NULL) { printf("mmap failed!n"); close(fd); return 0; } len = write(fd, buf, 1024); if (len < 0) { printf("write errorn"); close(fd); return 0; } sleep(5); memset(buf, 0, 1024); len = read(fd, buf, 1024); if (len < 0) { printf("read errorn"); close(fd); return 0; } printf("kernal addr content: n"); for (i = 0; i < 1024; i++) { printf("%c", buf[i]); } printf ("nuser addr content: n"); for (i = 0; i < 1024; i++) { printf("%c",((char *)p_viraddr)[i]); } close(fd); return 0; }
用户态文件编译:
/opt/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gun/bin/arrch64-linux-gun-gcc -g mmap_main.c -o mmap_main
最后:将编译出的module_mmap.ko 和mmap_main文件,拷贝到内核编译结果目录:rootf, 然后image打包。
实验现象:
kernal addr content:
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr …
user addr content:
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr…



