【Linux内核】内核模块编程helloworld与makefile编译安装

源程序hello.c

#include <linux/init.h>//用来指定程序的初始化和清理函数
#include <linux/module.h>//包含了大量加载模块需要的函数和符号的定义
#include <linux/kernel.h>

MODULE_LICENSE("GPL");//用于指定代码使用哪个许可
MODULE_AUTHOR("Hedwig");//声明谁编写了模块
MODULE_VERSION("V1");//代码修订版本号
MODULE_DESCRIPTION("Kernel example");//关于模块做什么的声明

static int year = 2021;

static int __init hello_init(void)//初始化函数应当声明成静态的
{
    printk(KERN_WARNING "Hello Kernel, it's %d!\n", year);
    return 0;
}

static void __exit hello_exit(void)//清理函数,注销接口、在模块被去除之前返回所有资源给系统
{
    printk("Bye, kernel!\n");
}

module_init(hello_init);
module_exit(hello_exit);
  • 最简单的模块,只包含模块加载函数,卸载函数和模块的一些描述信息
  • printk是内核中的输出函数,类似与用户空间的printf
  • _ _ init 标志的函数:如果模块编译进内核,在连接时都会放到.init.text这个区段内。 在.initcall.init中保留了一份函数指针,在初始化时内核会调用这些函数,初始化完成后释放init段内存
  • _ _ exit 标志的函数:若编译成模块,模块退出时执行
  • _ _ initdata 标志的数据:若编译到内核,初始化时使用。若编译为模块,模块初始化时使用
  • _ _ exitdata 标志的数据:若编译到内核,初始化完成后释放数据

Makefile

模块编译:编写Makefile文件,用make编译模块得到ko文件

obj-m := hello.o
all:
  $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
  $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  • obi-m:=hello.o 表明有个模块要从目标文件 hello.o 建立,在从目标文件建立后结果模块命名为hello.ko。这里并没有输入 hello.c源文件,这得益于 makefile 的自动推导功能,需要编译生成 hello.o文件而没有显示指定 hello.c 文件位置时,make 查找hello.c 是否存在,如果存在就正常编译,如果不存在,则报错 (obj-m 表示编译生成可加载模块;obj-y表示直接将模块编译进内核)

  • all、clean 这一类的是makefile 中的伪目标,伪目标并不是-个真正的编泽目标,它代表着一系列你想要执行的命令集合,通常一个makefile 会对应多个操作,例如编译、清除编译结果、安装,就可以使用这些伪目标来进行标记。在执行时就可以键入make clean 或 make install,等指令来完成相应的指令操作,当命令make 后不带参数时,默认执行第一个伪目标的操作

  • C选项指定内核源码的位置,make 在编泽时将会进入内核源码目录,执行编译,编译完成时返回

  • KDIR: /lib/modules/(shell uname-r)/build/指定内核源码的位置

  • M=(PWD)需要编译的模块源文件地址

  • [target] modules 是个可选选项,默认行为是将源文件编译并生成内核模块,即module(s),它还支持以下选项: modules install:安装这个外部模块,默认安装地址是/lib/modules/(uname-n)/extral,同时可以由内建变量 INSTALL MOD PATH 指定安装目录; clean:卸载源文件目录下编译过程生成的文件; help:帮助信息;

编译安装

源程序与Makefile放在同一目录,make命令编译

make

在这里插入图片描述

加载模块、检查模块加载情况

sudo insmod ./hello.ko
lsmod | grep hello

在这里插入图片描述

卸载模块

sudo rmmod hello

检查日志输出

dmesg

在这里插入图片描述

内核编程基本特点

1,内核编程时既不能访问C库也不能访问标准的C头文件;

2,Linux内核编程就是开发Linux驱动程序,内核编程的语言仍是传统的C语言,但其编写方法和调用接口与传统应用程序的差别较大,必须了解如何处理中断、如何在内核态和用户态之间转换、PCI、DMA、内核地址映射、内核I/O等;

3,本例hello_init()是模块的入口点,通过module_init()注册到系统,在被装载时被调用;

4,通过makefile编译;

5,部分函数与用户编程写法不同,如printf改为printk;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值