南宁企业网站建设技术公司南京移动网站建设效果好
文章目录
- 前言
 - 模块的Hello World!
 
前言
Linux允许用户通过插入模块,实现干预内核的目的。一直以来,对linux的模块机制都不够清晰,因此本文对内核模块的加载机制进行简单地分析。
ref:https://www.cnblogs.com/fanzhidongyzby/p/3730131.html
模块的Hello World!
我们通过创建一个简单的模块进行测试。首先是源文件main.c和Makefile。
 florian@florian-pc:~/module$ cat main.c
#include<linux/module.h>
#include<linux/init.h>static int __init init(void){printk("Hi module!\n");return 0;}static void __exit exit(void){printk("Bye module!\n");}module_init(init);module_exit(exit);
 
其中init为模块入口函数,在模块加载时被调用执行,exit为模块出口函数,在模块卸载被调用执行。
 florian@florian-pc:~/module$ cat Makefile
obj-m += main.o#generate the pathCURRENT_PATH:=$(shell pwd)#the current kernel version numberLINUX_KERNEL:=$(shell uname -r)#the absolute pathLINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)#complie objectall:make -C (LINUXKERNELPATH)M=(CURRENT_PATH) modules#cleanclean:make -C (LINUXKERNELPATH)M=(CURRENT_PATH) clean
 
其中,obj-m指定了目标文件的名称,文件名需要和源文件名相同(扩展名除外),以便于make自动推导。
然后使用make命令编译模块,得到模块文件main.ko。
florian@florian-pc:~/module$ make
make -C /usr/src/linux-headers-2.6.35-22-generic M=/home/florian/module modulesmake[1]: 正在进入目录 `/usr/src/linux-headers-2.6.35-22-generic'Building modules, stage 2.MODPOST 1 modulesmake[1]:正在离开目录 `/usr/src/linux-headers-2.6.35-22-generic'
 
使用insmod和rmmod命令对模块进行加载和卸载操作,并使用dmesg打印内核日志。
florian@florian-pc:~/module$ sudo insmod main.ko;dmesg | tail -1
[31077.810049] Hi module!
 
florian@florian-pc:~/module$ sudo rmmod main.ko;dmesg | tail -1
[31078.960442] Bye module!
 
通过内核日志信息,可以看出模块的入口函数和出口函数都被正确调用执行。
模块文件
 使用readelf命令查看一下模块文件main.ko的信息。
florian@florian-pc:~/module$ readelf -h main.ko
ELF Header:Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00Class:                             ELF32Data:                              2's complement, little endianVersion:                           1 (current)OS/ABI:                            UNIX - System VABI Version:                       0Type:                              REL (Relocatable file)Machine:                           Intel 80386Version:                           0x1Entry point address:               0x0Start of program headers:          0 (bytes into file)Start of section headers:          1120 (bytes into file)Flags:                             0x0Size of this header:               52 (bytes)Size of program headers:           0 (bytes)Number of program headers:         0Size of section headers:           40 (bytes)Number of section headers:         19Section header string table index: 16
 
user@root:~/module$ sudo readelf -h main.ko
ELF Header:Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00Class:                             ELF64Data:                              2's complement, little endianVersion:                           1 (current)OS/ABI:                            UNIX - System VABI Version:                       0Type:                              REL (Relocatable file)Machine:                           Advanced Micro Devices X86-64Version:                           0x1Entry point address:               0x0Start of program headers:          0 (bytes into file)Start of section headers:          2936 (bytes into file)Flags:                             0x0Size of this header:               64 (bytes)Size of program headers:           0 (bytes)Number of program headers:         0Size of section headers:           64 (bytes)Number of section headers:         22Section header string table index: 21 
我们发现main.ko的文件类型为可重定位目标文件,这和一般的目标文件格式没有任何区别。我们知道,目标文件是不能直接执行的,它需要经过链接器的地址空间分配、符号解析和重定位的过程,转化为可执行文件才能执行。
那么,内核将main.ko加载后,是否对其进行了链接呢?
ref:https://www.cnblogs.com/fanzhidongyzby/p/3730131.html
