内核 模块开发

linux内核的整体结构非常庞大,组件合成分为2种:

(1):把所有的组件都编译进内核文件,即zImage或bzImage。这种有两个缺点:

  a、生成的内核文件过大。

  b、如果想要添加或删除某个组件,需要重新编译整个内核。

(2)内核模块机制:需要该组件时,动态地添加到正在运行的内核中。

内核模块特点:

(1)模块本身并不被编译进内核文件(ZImage/bzImage).

(2)可以根据需求,在内核运行期间动态的安装或卸载。

 

模块加载函数

安装模块时被系统自动调用的函数,通过module_init宏来指定,如hello_init。

模块卸载函数:

卸载模块时被系统自动调用的函数,通过module_exit宏来指定,如hello_exit。

 

模块编译:在linux2.6下编译内核模块,通常使用makefile

单个源文件(hello.c)编译:

ifneq ($(KERNELRELEASE),)                //如果KERNELRELEASE不等于空

obj-m := hello.o

else

KDIR := /lib/modules/2.6.18-53.el5/build    //内核源代码路径
all:

    make -C $(KDIR)  M=$(PWD)   modules    //modules:makefile的目标, 
  //-C:进入后面紧跟的目录中使用它的makefile来编译,后面紧跟的是一个目录。
  //M:build文件中要求的,表示内核代码所在。
clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers endif

 

多个源文件(main.c add.c)编译

ifneq  (($KERNELRELEASE),)

obj-m := hello.o            //内核模块的名字
hello-objs := main.o  add.o   //hello-objs中hello与模块名字必须一样,如果多个文件,add文件名

else 

KDIR := /lib/modules/2.6.18-53.el5/build
all:

    make  -C  $(KDIR)  M=$(PWD)  modules
clean:
    rm -f  *.ko  *.o  *.mod.o  *.mod.c  *.symvers

endif

 

1.加载insmod  (insmod hello.ko)

2.卸载rmmod   (rmmod hello)

3.查看 lsmod

4.加载modprobe (modprobe hello)

modprobe如同insmod,也就是加载一个模块到内核。它的不同之处在于它会根据文件

/lib/modules/<$version>/modules.dep

来查看要加载的模块,看它是否还依赖于其他模块,如果是,modprobe会首先找到这些模块,把它们先加载到内核。

 

1.许可证申明:

MODULE_LICENSE用来告知内核,该模块遵守的许可证协议,如“GPL”、“GPL v2”。

MODULE_LICENSE("遵守的协议")

MODULE_LICENSE("GPL")

2.作者申明

MODULE_AUTHOR("作者")

3.模块描述

MODULE_DESCRIPTION("模块的功能描述")

4.模块版本

MODULE_VERSION("V1.0")

5.模块别名

MODULE_ALIAS("别名");

6.模块参数:通过宏module_param指定保存模块参数的变量。模块参数用于在加载模块时传递参数给模块。

module_param(name,type,perm)

name:变量的名称

type:变量类型,bool:布尔型  int:整形  charp:字符串型

perm是访问权限。 S_IRUGO:读权限  S_IWUSR:写权限

如:

在hello.c中  int a = 9;
module_param(a,int,S_IRUGO);


命令行中输入:insmod  test.ko  a=100   //把100赋给a

 

内核符号导出:

EXPORT_SYMBOL(符号名)

EXPORT_SYMBOL_GPL(符号名)    //只能用于包含GPL许可证的模块

如两个模块A、B模块:需在A(定义变量或者函数)中利用EXPORT_SYMBOL(符号名)导出,在B模块中用extern 再声明下。

 

uname -r   //查看内核版本

内核打印:printk。允许根据严重程度,通过附加不同的“优先级”来对消息分类

printk(KERN_WARNING  "hello world");
printk("<0> hello world");

在<linux/kernel.h>中定义了8种记录级别:

KERN_EMERG     "<0>"     紧急消息

KERN_ALERT      "<1>"    需要立即处理

KERN_CRIT        "<2>"    严重情况

KERN_ERR        "<3>"    错误情况

KERN_WARNING  "<4>"   有问题的警告

KERN_NOTICE    "<5>"    正常情况,但仍然需要注意

KERN_INFO       "<6>"     信息型消息 

KERN_DEBUG   "<7>"     用作调试消息

注意:没有指定优先级printk默认使用DEFAULT_MESSAGE_LOGLEVEL优先级,定义在kernel/printk.c中

如:

#define DEFAULT_MESSAGE_LOGLEVEL 4

 

屏幕上没有打印的消息全在:/var/log/message

 

内核打印控制台优先级配置

在/proc/sys/kernel/printk文件中,cat  /proc/sys/kernel/printk

6 4 1 7   //console_loglevel    default_message_loglevel   minimum_console_level   default_console_loglevel

posted on 2018-01-14 02:01  白宫飘红旗  阅读(856)  评论(0编辑  收藏  举报