内核空间与用户空间共享内存(mmap)

好多次遇见mmap,但都没有实际实验过,最近终于抽出时间做了个mmap的小实验。这篇博文中的代码是在其他人的基础上修改而成,并非个人原创。

一、mmap实现方法:
将内核的物理内存通过mmap映射到用户空间,直接在用户空间对内核数据进行存取。
1、在内核中分配一片内存(kzalloc/__get_free_pages),将这片内存的虚拟地址转换成物理地址;
2、在内核的mmap函数中通过remap_pfn_range实现内核物理内存空间映射到用户虚拟地址空间转换的功能;
3、在应用程序中可以调用用户态的mmap函数,完成内核物理内存向用户空间的映射;
4、可直接利用这片被映射了的用户空间对内核空间进行存取操作。

二、程序实现功能:
1、创建mmap_dev字符设备,实现该设备的mmap函数;
2、在/proc中创建获取内核中分配的物理内存信息(起始地址和大小)的接口;
3、通过/proc读取内核中分配的物理内存信息(起始地址和大小);
4、通过读取的这些内存信息调用mmap函数,完成用户空间到内核空间的映射;
5、向这片映射过的用户空间写入数据。

三、代码

mmap_tes.c

Makefile

mmap_test_app.c

 

四、运行环境:
主机L:ubuntu 14.04 x86-64
内核版本:Linux-4.4
虚拟机:QEMU
文件:(内核x86-64)bzImage
(ramfs)busybox_initramfs.cpio.gz
(驱动模块)mmap_test.ko
(应用程序)mmap_test_app

五、利用busybox制作initramfs根文件系统
1、rootfs的制作
(待写)
2、 添加应用程序的支持库
ldd mmap_test_app
显示内容如下:

linux-vdso.so.1 => (0x00007fffbd475000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f605a0cb000)
/lib64/ld-linux-x86-64.so.2 (0x00007f605a4ad000)

linux-vdso.so.1是系统自动生成的,无法在/lib中找到,在/lib/x86_64-linux-gnu/文件夹中找到libc.so.6,发现其是libc-2.19.so的链接符号,libc-2.19.so也在这个文件夹中,将libc-2.19.so复制到根文件系统的/lib目录中,并创建libc-2.19.so链接符号。同样发现/lib64/ld-linux-x86-64.so.2 是链接到/lib/x86_64-linux-gnu/ld-2.19.so的链接符号,将ld-2.19.so复制到根文件系统的/lib目录中,并在/lib64创建libc-2.19.so链接符号ld-linux-x86-64.

app_so_1

app_so_2

3、将根文件系统制打包成cpio.gz格式(initramfs)
将(驱动模块)mmap_test.ko和(应用程序)mmap_test_app复制到initramfs目录的home目录下,通过以下命令打包成cpio.gz文件
find . | cpio -o -H newc | gzip > ../busybox_initramfs.cpio.gz

六、启动虚拟机:
(1)输入:
qemu-system-x86_64 -kernel bzImage -initrd busybox_initramfs.cpio.gz

qemu
(2)插入模块后,通过mknod命令手工生成/dev/mmap设备节点(文件系统中mdev动态创建设备节点有待进一步研究)

(3)执行应用程序
./mmap_test_app   www.ydea.net
(4)查看用户程序写入的信息
cat /dev/mmap

qemu1

qemu2

六、将驱动编译进内核
(1)将驱动拷贝到内核源码中./driver/char目录中
(2)修改Makefile,在文件的最末尾加入:
obj-$(CONFIG_MMAP_TEST) += mmap_test.o
(3)修改Kconfig文件,在文件中加入
config MMAP_TEST
bool “/dev/mmap virtual device support”
default n
help
just for mmap test.
(4)配置并编译内核
make menuconfig
Device Drivers->Character devices
选中下面选项
[*] /dev/mmap virtual device support

kernel_config
编译
make bzImage
在QEMU中启动新的内核,已经生成了/dev/mmap设备文件,直接执行应用程序,再查看结果。

3 Comments

  1. 静水流深

    代码用的什么插件?

    Reply

    • 一念花开

      Crayon Syntax Highlighter
      说起WordPress插入代码,我就一头黑线,老是把一些特殊符号转码,要最后插入代码,马上提交。也不敢轻易,修改,只要稍微不注意,完了,部分字符又被转码了,又需要重新拷贝上去。对于此,不知你有什么好的办法?

      Reply

  2. 电影王国

    看不懂,看不懂。。。

    Reply

Leave a Reply

*