内核模块加载之虚拟内核空间 前面讲过,在32位平台的linux下,0-3G是用户程序可访问的,后面1G是内核空间专用的。 那么我们可以来做实验感受一下。 当然,写个普通的main函数就能够到达输出0-3G的空间地址,然而内核空间的地址不是用户程序能够访问的,要不就乱套了(其他进程也共享了这片内核空间)。 不过,我们可以有办法来输出,那就是利用加载内核模块的方法。 首先,我们看看输出用户空间的代码,简单的main函数即可。 #include <stdio.h> #include <malloc.h> #include <unistd.h> int bss_var; int data_var0 = 1; int main(int argc,char **argv) { printf("The user space's address division of a process as follow:\n"); printf("Data segment:\n"); printf("address of \"main\" function:%p\n",main); int stack_var0=2; printf("Stack segment:\n"); printf("initial end of stack:%p\n",&stack_var0); int stack_var1=3; printf("new end of stack:%p\n",&stack_var1); printf("Data segment:\n"); printf("address of data_var:%p\n",&data_var0); static int data_var1=4; printf("new end of data_var:%p\n",&data_var1); printf("BSS:\n"); printf("address of bss_var:%p\n",&bss_var); char *str=(char *)malloc(sizeof(char)*10); printf("initial heap end:%p\n",str); char *buf=(char *)malloc(sizeof(char)*10); printf("new heap end:%p\n",buf); /* char *b=sbrk((ptrdiff_t)0); printf("Heap location:\n"); printf("initial end fo head:%p\n",b); brk(b+4); b=sbrk((ptrdiff_t)0); printf("new end of heap:%p\n",b); */ return 0; } 输出: The user space's address division of a process as follow: Data segment: address of "main" function:0x8048454 Stack segment: initial end of stack:0xbf99c66c new end of stack:0xbf99c668 Data segment: address of data_var:0x804a01c new end of data_var:0x804a020 BSS: address of bss_var:0x804a02c initial heap end:0x8b3f008 new heap end:0x8b3f018 我们可以用个图来表示一下,用户空间的大概格局。 BSS和数据段通常是在一起的,而代码段和栈(通常我们说堆栈就是说的 是栈)往往独立存放,且栈是向下生长的,堆向上生长,但是,她们几乎不会碰头,你可以看看上面的输出就知道它们间的距离有多大了。 这个矩形从0x000000开始,到0xBFFFFFF结束 从0xC0000000-0xFFFFFFFF是内核空间,你没办法在用户程序中输出这里面的地址,不过前面讲了,我们可以利用内核模块加载的办法来访问之。。 下面是访问内核空间的办法,也即要靠加载模块。翻篇了。。 下面说说模块编程和应用程序编程的比较: 用户应用程序 内核模块程序 使用函数 libc库 内核函数 运行空间 用户空间 内核空间 运行权限 普通用户 超级用户 入口函数 main() modules_init() 出口函数 exit() modules_exit() 编译 gcc -c Makefile 链接 gcc insmod 运行 直接运行 insmod 调试 GDB kdbug 等工具 首先就是要会编写内核加载的Makefile文件 这里给出一个例子,然后说明 obj-m:=mymodule.o KDIR:=/lib/modules/$(shell uname -r)/build PWD:=$(shell pwd) all: make -C $(KDIR) M=$(PWD) modules clean: rm -rf *.o *.ko *.mod.c *sym* *.un* 第一行是定义要生成的目标文件,不过后来也会生成.ko的文件。 第二行是头文件路径:在内核编程的时候会用到内核中的头文件,这些在平时 编程中的include里面没有,须字节找到路径。 在找这个路径的时候我犯了很多错误。 首先要注意的是,原始的路径是在/usr/src/kernle/$(uname -r)/include 但在lib/modules/$(uname -r)/这个文件夹下面会有一个链接文件build是链接到上面这个路径的,所以,可以就用这个build链接文件即可。 再次药注意的是,如果这个build文件是红色的,那代表你没有链接成功,我就是在这一步出了问题,报告老是找不到头文件,就是因为链接没有成功,这时先删除掉原理的build,重新建立build touch build ln -s ../../usr/src/kernel/$(uname -r)/include 成功后会显示这个文件的颜色是绿色的。。 第三行是源文件所在路径名,用pwd命令找到即可。 后面的都是make 用的命令,具体可以自己添加即可。 Makefile写完后,写模块程序,写完后,就可以 make all 这时会生成.ko文件。加载 insmod *.ko(以root权限)。 成功后,可以用dmesg命令看到程序的运行结果。 上面说了那么多,下面开始编写访问内核空间的模块程序。。。 #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/mm.h> #include <linux/vmalloc.h> unsigned long pagemem; unsigned char *kmallocmem; unsigned char *vmallocmem; MODULE_LICENSE("GPL"); static int __init mmshow_init(void) { printk("mmshow module is working\n"); pagemem = __get_free_page(GFP_KERNEL); if(!pagemem) goto gfp_fail; printk(KERN_INFO "pagemem = 0x%lx\n",pagemem); kmallocmem = kmalloc(100 * sizeof(char),GFP_KERNEL); if(!kmallocmem) goto kmalloc_fail; printk(KERN_INFO "kmallocmem = 0x%p\n",kmallocmem); vmallocmem = vmalloc(1000000 * sizeof(char)); if(!vmallocmem) goto vmalloc_fail; printk(KERN_INFO "vmallocmem = 0x%p\n",vmallocmem); return 0; gfp_fail: free_page(pagemem); kmalloc_fail: kfree(kmallocmem); vmalloc_fail: vfree(vmallocmem); return -1; } static void __exit mmshow_exit(void) { free_page(pagemem); kfree(kmallocmem); vfree(vmallocmem); printk("mmshow module is leaving\n"); } module_init(mmshow_init); module_exit(mmshow_exit); 程序中用到了内核函数和内核结构(在文件mm中有详细的说明) 这里简单说明_get_free_page(),kmalloc()和 vmalloc()都是用来申请内核空间的。_get_free_page每次可以申请到完整的一页,其他两个则不一定。 用上面的方法加载后输出结果dmseg: mmshow module is working pagemem = 0xde7fa000 kmallocmem = 0xf49a64c0 vmallocmem = 0xfc209000 可以看到输出的地址实在0xC0000000-0xFFFFFFFF的内核空间的。 即我们的目的达到了,对内核空间有了感性的认识。 下面就开始来学习mm中的数据结构和函数吧
内核模块加载之虚拟内核空间
最新推荐文章于 2024-02-27 14:53:39 发布