linux内核工程师 1.04节 linux内核模块编译

一.Linux内核介绍 
1.Linux 内核很庞大,相应的包含的组件也非常多。Linux文件就是常说的zImage和bzImage,在内核启动期间会被解压到内存。

2.新的使用组件的思路:动态加载和卸载。也就是需要这个组件的时候才去加载,不需要的时候,就卸载。即内核模块机制。

3.关于内核模块。有以下特征: 
(1)不被编译进内核文件 
(2)可以动态加载和卸载

4.关于内核模块的操作 
(1)加载insmod 
(2)卸载rmmod 
(3)查看lsmod

二.设计和编写 
1.分析和结构概括 
这里写图片描述

2.代码编写

#include <linux/init.h>
#include <linux/module.h>


static int hello_init()
{
    printk(KERN_WARNING"Hello world!\n");
    return 0;   
}

static void hello_exit()
{
    printk(KERN_WARNING"hello exit!\n");    
}

module_init(hello_init);
module_exit(hello_exit);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

(1)一般init函数是static int类型的,exit函数式static void类型的 
(2)printk和printf的区别是printk最前面需要的是表示优先级的参数

三.Makefile编写 
1.需要一个变量指明我们最终产生的内核模块的名字 
(1)如果内核模块只有一个源文件,一般模块名称和原文件一样,只是把.c改成.o 
obj-m := helloworld.o 
(2)如果有多个源文件,那么就应该是模块名可以随便,但是还要多一条语句 
模块名-objs := file1.o file2.o file3.o

2.定义一个变量指明内核代码所在的路径。因为模块是基于内核的,你用什么版本的内核作为基础,编译出来的模块只能在同版本的内核使用。 
KIR := /内核源代码路径

3.编写规则,只有目标all,但是没有依赖,却有命令。 
make -C KDIRM=(KDIR)M=(pwd) modules CROSS_COMPILE = arm-linux ARCH = arm 
-C指明要进入-C后面的路径(内核路径)编译模块,M指明了模块文件的路径

4.最后编写clean伪指令,清除产生的中间文件和.ko文件。将ko文件复制到文件系统。

扫描二维码关注公众号,回复: 1588826 查看本文章
obj-m := helloworld.o

KDIR := /home/S5-driver/lesson7/linux-tq2440

all:
    make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm

clean:
    rm -f *.o *.ko *.order *.symvers
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

5.rmmod的时候要在/lib/modules目录下面有和内核模块的内核版本一致的目录名 
经常用(uname -r)来获取内核版本 
mkdir -p /lib/modules/$(uname -r)

6..用tftp 地址 文件名的命令下载内核到sdram,然后用nfs挂载文件系统,启动Linxu系统,之后对内核模块进行操作。 
这里写图片描述 
四.模块可选项 
1.模块申明 
(1)MODULE_LICENSE(“遵守的协议”) 
没有这一个申明,在加载模块的时候会报警告。 
(2)MODULE_AUTHOR(“作者”) 
(3)MODULE_VERSION(“版本”) 
(4)MODULE_DESCRIPTION(“功能描述”)

2.模块参数 
(1)和普通应用程序一样,在加载模块的时候,可以给模块传递一些参数。 
(2)区别在于,要事先申明这些参数的数据类型和变量名字,而且要用到 
module_param(name,type,perm)这个宏定义。他用来指明保存模块参数的变量。 
name:变量名 
type:变量类型,一般是int,bool以及charp(字符串类型,记住是charp,不是char和char*) 
perm:权限。一般分为S_IRUGO和S_IWUSR。通常情况下将他们按位或。

3.模块符号导出 
(1)当一个模块要使用另一个模块的函数(变量)的时候,如果没有符号导出,不仅要实现这个函数,还要申明这个函数导出给其他模块使用,否则在其他模块使用这个函数的时候会出错,甚至不能加载要使用它的模块。 
(2)使用EXPORT_SYMBOL(符号名)或者EXPORT_SYMBOL_GPL(符号名)来申明。后者只可以用于遵循GPL协议的模块。


猜你喜欢

转载自blog.csdn.net/zjy900507/article/details/80660594