【kernel】内核模块开发--hello world

背景

参考《奔跑吧 Linux内核》4.1章的教程,动手完成第一个内核模块的编译。
Linux Kernel Workbook

内核模块代码

#include<linux/init.h>
#include<linux/module.h>
// __init是链接属性,表示把函数放到.init.text位置
static int __init demo_init(void)
{
    printk("demo init!\n");
    return 0;
}
//__exit是链接属性,表示把函数放到.exit.text位置
static void __exit demo_exit(void)
{
    printk("demo exit!\n");
}

// 设置入口点,module_init是加载模块时将调用的第一个函数
module_init(demo_init);
// module_exit() 是从系统中卸载模块时调用的函数
module_exit(demo_exit);

//执行modinfo时会显示模块相关的信息
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ben Shushu");
MODULE_DESCRIPTION("This my first kernel module");
MODULE_ALIAS("demo");

__init和__exit的定义

#define __init  __attribute__ ((__section__ (".init.text")))  __cold
#define __exit  __attribute__ (( __section__ (".exit.text"))) __cold

模块编译

参考链接

# 你的模块的名字
NAME = hello
# 内核的源码头文件目录
KDIR := /usr/lib/modules/$(shell uname -r)/build/

# 最后生成的*.ko的名字,与前面的NAME对应
obj-m := $(NAME).o

# 源文件的名字.o
$(NAME)-objs := hello_world.o

# 当前目录,给之后的M赋值
PWD := $(shell pwd)

# 进入内核源码头文件目录,调用该目录下的Makefile
# 设置M=PWD,M是内核源码头文件目录下的Makefile的一个变量
# 用来指示生成的模块存放的目录
build:
    $(MAKE) -C $(KDIR) M=$(PWD) modules
# 这样clean比较方便
clean: 
    $(MAKE) -C $(KDIR) M=$(PWD) clean
  • make -C 指定Makefile的路径,KDIR即内核模块Makefile的路径
  • M指定了当前模块的路径

模块的名字不能和.o的名字重名

执行make编译模块

image.png

安装和卸载模块

#安装模块
sudo insmod hello.ko
#卸载模块
sudo rmmod hello
#查询已经安装的模块
sudo lsmod
#查询模块日志
sudo dmesg
#查询模块信息
modinfo hello.ko
image.png

问题记录

  1. Ubuntu20 内核版本依赖gcc-12
sudo apt install gcc-12
#查询gcc12安装位置
whereis gcc-12
#查询结果gcc: /usr/bin/gcc /usr/lib/gcc /usr/share/gcc /usr/share/man/man1/gcc.1.gz

2.makefile miss separator
makefile只支持TAB,vscode默认将tab转成了4个空格

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容