内核模块3 | 学习笔记

简介: 快速学习内核模块3

开发者学堂课程【物联网开发-Linux 驱动开发实操演练:内核模块3】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/657/detail/10871


内核模块3


内容介绍:

一、编译工具

二、如何进行编译

三、内核编译的几种方法

四、外部编译

五、编译说明文档的介绍

六、编译 Makefile,并进行编译


一、编译工具

c 语言是一种编译型语言,c 语言源码写完之后,需要进行编译。在 Linux 里面,使用的是 gcc 编译器或交叉编译工具。

 

二、如何进行编译

编译内核代码需要使用内核的构建方法来构建内核模块,因为内核模块是基于内核来编写。

内核模块里面调用的函数,涉及的内容是由内核提供的,因此需要用到编写编译内核模块的 Makefile。

 

三、内核模块编译的几种方法

1. 内部编译

写的内核模块的源文件放在内核源码中进行编译。

2. 外部编译

将内核模块的源文件放在外面进行编译

3. 动态编译

编译生成动态模块xxx.ko

4. 静态编译

将内核模块编译进uImage中

5、几种方法的对比

用的较多的为外部编译,因为现在正处于开发阶段,编写完之后的理想状态是可以动态的加载和卸载。

如果将编译放在 uimage 里面,当需要进行调试的时候,就需要用到 uimage 倾向,操作更加繁琐。

如果编译生成一个模块,这样会更加灵活。例如,在调试的时候加载到内核,将内核卸载出来,再重新对这个内核进行编译,编译完在插入到内核里面,进行测试,更加符合当前的实际。

静态编译和内部编译需要修改里面的 Kconfig Makefile。修改完成后,需要去配置make menuconfig。

编译内核模块:

编译器:gcc 交叉编译工具

编写编译内核模块的 Makefile

内部编译:将内核模块源文件放在内核源码中进行编译

静态编译:将内核模块编译进 uImage 中

外部编译:将内核模块源文件放在内核源码外进行编译

动态编译:编译生成动态模块 xxx.ko

 

四、外部编译

关于内核如何编写,提供了一个说明文档,即内核源码:

进入内核源码之后,进入 document 之后,有一个文档目录:

image.png

文档里面有一个 kbuilds ls 的目录,有一个 modules.txt 文档:

此文档描述的是,在外部构建时,如何构建一个内核模块:

l Building External_Modules

3This document describes how to build an out-of-tree kernel module.

5 ===Table of Contents

7 === 1 Introduction

8 === 2 How to Build External Modules

9 --- 2.1 Command Syntax

0 --- 2.2 Options

1 --- 2.3 Targets

2 --- 2.4 Building Separate Files

3 === 3. Creating a Kbuild File for an External Module

4 --- 3.1 Shared Makefile

5 --- 3.2 Separate Kbuild file and Makefile

6 --- 3.3 Binary Blobs

7 --- 3.4 Building Multiple Modules

8 === 4. Include Files

9 --- 4.1 Kernel Includes

0 --- 4.2 Single Subdirectory

1 --- 4.3 Several Subdirectories

2 === 5. Module Installation

34 --- 5.1 INSTALL MOD PATH

--- 5.2 INSTALL MOD DIR

5 === 6. Module Versioning

6 --- 6.1 Symbols From the Kernel (vmlinux + modules)

78 --- 6.2 Symbols and External Modules

--- 6.3Symbols From Another External Module

9 ===7.Tips & Tricks

里面包含了介绍和每个命令的说明,最后也列举了一些例子。因此,可以根据说明文档去编译一个内核模块

 

五、编译说明文档的介绍

例如语句:

54 NOTE:"modules prepare" will not build Module.symvers even if

55 CONFIG MODVERSIONSis set;therefore, a full kernel build needs to be

56executed to make module versioning work.

57

58---2.1 Command Syntax

59

10 The command to build an external module is:

$ make -Ckpath to_kernel Src> M=SPWD

13

74 The kbuild system knows that an external module is being built

15 due to the "M=" option given in the command.

16

17 To build against the running kernel use:

18

19 s make -C /1ib/modules/`uname -r /build M=SPWD

30

31 Then to install the module(s) just built, add the target

32 "modules_install" to the command:

33

34 s make -C /lib/modules/ uname -r /build M=SPWD modules_install

35

36---2.2 Options

37

38 (SKDIR refers to the path of the kernel source directory.)

19

例如语句“”72    $ make -e  M=$pwd”

此语句是要执行一个 Makefile,-c 指的是到指定的路径下,去执行该路径的Makefile,M=$pwd 指向的是当前的路径。                                                

79   $ make -c /lib/modules/uname -r/build > M=$pwd

lib/modules/uname -r/build 为一个命令置换。将此条语句执行完之后,将输出结果放在此处。

3.2.0-29是当前版本,进入3.2.0-29,发现里面有一个 build。进入 build 之后,里面有一个目录:

image.png

上面为内核的目录结构。

如果需要将其编译到具体的平台上,用得到的内核源码,应该指定 /kernel-3.4-3.9

该文档中,还有许多的内核源码,都做了详细的说明。


六、编写Makefile,并进行编译

进行编译之后,生成一个.ko的模块,并测试能否使用。

1. 编写Makefile

编写一个目标,相当于一个伪目标,接下来编写规则,指定内核的路径:kernel.dir,制定M=$(PWD),执行PWD的命令,将结果赋值给当前变量。

编译目标,这个目标为 modules 的目标和一个 clear 的目标,使用内核的目录下去清除,即在 kernel 的命令去执行。

指定.to 是依赖于哪一个.o生成。此处为依赖于 demo.o 生成的文件。

1

2KERNDIR:= /lib/modules/3.2.0-29-generic-pae/build/

3 PWD:=$(shell pwd)

5 obi-m:=demo.o

7 all:

8 make -C $(KERNDIR) M=$(PWD) modules

10 clean:

11 make -C $(KERNDIR) M=$(PWD) clean

12

2. 编译Makefile

将 demo.c 复制后进行编译:

edu@edu-T:~/work/test$ 1s

demo.c Makefile

edu@edu-T:-/work/test make

make -C /lib/modules/3.2.0-29-generic-pae/build/ M=/home/edu/work/test modulesmake[1]:

正在进入目录

/usr/src/linux-headers-3.2.0-29-generic-pae

CC [M]/home/edu/work/test/demo.o

Building modules, stage 2.

MODPOST 1 modules

CC /home/edu/work/test/demo.mod.o

LD [M] /home/edu/work/test/demo.ko

make 1]:正在离开目录

/usr/src/iinux-headers-3.2.0-29-generic-pae'

edu@edu-T:~/work/test$

在当前目录下查看 demo.ko 的文件:

edu@edu-T:~/work/test 15:39  edu

edu@edu-T:-/work/test$ 1s

demo.c demo.ko demo.mod.c demo.mod.o demo.o Makefile modules.order Module.symvers

edu@edu-T:-/work/test$

对于当前的 demo.ko 来说,可以插入到当前乌班图的内核里面,和乌班图形成整体来运行。

相关文章
|
3月前
|
NoSQL Linux Android开发
内核实验(三):编写简单Linux内核模块,使用Qemu加载ko做测试
本文介绍了如何在QEMU中挂载虚拟分区、创建和编译简单的Linux内核模块,并在QEMU虚拟机中加载和测试这些内核模块,包括创建虚拟分区、编写内核模块代码、编译、部署以及在QEMU中的加载和测试过程。
193 0
内核实验(三):编写简单Linux内核模块,使用Qemu加载ko做测试
|
3月前
|
Ubuntu Linux 开发工具
深入探索Linux内核模块编程
【8月更文挑战第4天】在这篇文章中,我们不仅将探讨Linux内核模块的基础知识,还将通过一个实际的例子来展示如何编写一个简单的内核模块。我们将从理论出发,逐步过渡到动手实践,最终实现一个可以在Linux系统上运行的模块。文章的目标是为读者提供足够的信息和知识,以便他们能够自己编写内核模块,从而对操作系统的内部工作原理有更深入的了解。
|
6月前
|
Linux
探索Linux操作系统的内核模块
本文将深入探讨Linux操作系统的核心组成部分——内核模块,揭示其背后的工作机制和实现方式。我们将从内核模块的定义开始,逐步解析其加载、卸载以及与操作系统其他部分的交互过程,最后探讨内核模块在系统性能优化中的关键作用。
|
存储 编译器 开发者
内核模块(下)
内核模块(下)
176 0
|
编译器 Linux 开发者
内核模块(上)
内核模块
108 0
|
Linux KVM 虚拟化
Linux内核模块
在模块A编译好后会生成符号表文件Module.symvers, 里面有函数地址和函数名对应关系,把这个文件拷贝到需要调用的模块B的源代码下,替换模块B的该文件。 然后重新编译B模块.这样就能够让模块B调用模块A的函数,以后加载模块顺序也必须先A后B,卸载相反。
Linux内核模块
|
网络协议 物联网 Linux
内核模块4 | 学习笔记
快速学习内核模块4
内核模块4 | 学习笔记
|
物联网 Linux 开发者
内核模块2 | 学习笔记
快速学习模块编写2
内核模块2 | 学习笔记
|
Linux
linux下自动加载设备驱动程序模块
<h1 class="postTitle" style="font-size: 14.7px; margin-bottom: 10px; color: rgb(75, 75, 75); font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;"><br></h1> <div id="cnblogs_post_body" style=
2745 0
|
缓存 IDE Linux
16.4 Linux内核(内核模块)的加载
GRUB 加载了内核之后,内核首先会再进行二次系统的自检,而不一定使用 BIOS 检测的硬件信息。这时内核终于开始替代 BIOS 接管 Linux 的启动过程了。
224 0
16.4 Linux内核(内核模块)的加载