贝尔面瘫

注册

 

发新话题 回复该主题

Linux内核模块开发基础 [复制链接]

1#
白癜风可以用什么药 https://m.39.net/disease/a_5629059.html

Linux内核仅是操作系统的一部分,但对下它管理系统所有硬件设备,对上,它通过系统调用,向LibraryRoutine(如C库)/其他应用程序提供接口。

整体机构及其子系统如图所示:

A)ProcessScheduler,也称作进程管理、进程调度。负责管理CPU资源,以便让各个进程可以以尽量公平的方式访问CPU。B)MemoryManager,内存管理。负责管理Memory(内存)资源,以便让各个进程可以安全地共享机器的内存资源。另外,内存管理会提供虚拟内存的机制,该机制可以让进程使用多于系统可用Memory的内存,不用的内存会通过文件系统保存在外部非易失存储器中,需要使用的时候,再取回到内存中。C)VFS(VirtualFileSystem),虚拟文件系统。Linux内核将不同功能的外部设备,例如Disk设备(硬盘、磁盘、NANDFlash、NorFlash等)、输入输出设备、显示设备等等,抽象为可以通过统一的文件操作接口(open、close、read、write等)来访问。这就是Linux系统“一切皆是文件”的体现(其实Linux做的并不彻底,因为CPU、内存、网络等还不是文件,如果真的需要一切皆是文件,还得看贝尔实验室正在开发的Plan9”的)。D)Network,网络子系统。负责管理系统的网络设备,并实现多种多样的网络标准。E)IPC(Inter-ProcessCommunication),进程间通信。IPC不管理任何的硬件,它主要负责Linux系统中进程之间的通信。

上面是Linux内核的大致组成结构,每个子系统又有很多模块组成,实际开发使用中,一般也用不到那么多,而且开发起来也挺困难的就有了“自研”内核模块,内核模块编程。

学习内核模块开发前,我们先一起了解下现有的一些内核模块,有个大致概念。前面有提到LVS和DPVS的真实客户端IP获取的toa/uoa模块,它们就是一种内核模块。Linux内核模块是一种编译好的二进制代码,可以插入到Linux内核空间中,在ring0级别运行(安全限制最少的级别)。这样,通过内核模块我们可以访问到系统的任意内容,比如LVS中通过toa/uoa模块hook内核函数get_name(),之后应用层就可以调用getpeername后进入到toa模块定义的函数,返回socket中存放的特定数据了。下面是内核模块开发的一般流程,以打印helloworld的test模块为例来看一下如何开发(示例来自《奔跑吧Linux内核--入门篇》)内核模块代码文件:hello.c

#includelinux/init.h//头文件定义#includelinux/module.hstaticint__inithello_init(void)//模块入口——模块初始化函数{printk(myfirstkernelmoduleinit);return0;}staticvoid__exithello_exit(void)//模块退出函数定义{printk(goodbyehellomodule);}module_init(hello_init);//声明模块入口函数module_exit(hello_exit);//声明模块出口函数MODULE_LICENSE(GPL);//设置模块接受的许可证协议MODULE_AUTHOR(Azura);//描述作者信息MODULE_DESCRIPTION(kernelmodule:helloworld);//模块描述MODULE_ALIAS(fisrt);//用户空间别名

内核模块Makefile文件:Makefile

BASEINCLUDE?=/lib/modules/`uname-r`/build//通过uname-r找到内核版本,使BASEINCLUDE指向内核编译路径first-objs:=hello.o//目标文件,格式模块名-objs:=目标文件.oobj-m:=first.o//要生成的模块,格式obj-m:=模块名.oall://编译执行动作$(MAKE)-C$(BASEINCLUDE)M=$(PWD)modules;clean://makeclean执行动作$(MAKE)-C$(BASEINCLUDE)SUBDIRS=$(PWD)clean;rm-f*.ko;

make编译后,文件目录为:first.kofirst.mod.cfirst.mod.ofirst.ohello.chello.oMakefilemodules.orderModule.symvers

之后我们可以通过filefirst.ko命令看到变成x86-64架构的ELF文件(此处系统CentOS7,x86-64),还可以用modinfo进一步检查

接下来就可以在我们的Linux系统上加载模块了:sudoinsmodfirst.ko;然后在系统日志dmesg或者/var/log/messages里面就能看到“myfirstkernelmoduleinit”这个输出了。同时/sys/modules下面也会有一个新目录,目录名为模块名,此处为first;卸载模块命令时rmmod

分享 转发
TOP
发新话题 回复该主题