Linux内核基础——Linux内核基础编程

任务一、模块编程

子任务1、编写最简单的内核模块,并将其加载到内核中

hello.c

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
static int init_hello(void)
{
   
	printk(KERN_INFO "Hello, World!\n");
	return 0;
}
static void cleanup_hello(void)
{
   
	printk(KERN_INFO "Goodbye, world!\n");
}
module_init(init_hello);
module_exit(cleanup_hello);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zjc");
MODULE_DESCRIPTION("A test project");

Makefile

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

首先使用Linux内核的函数库编写最简单的模块,模块功能是使用printk内核控制台输出函数,打印KERN_INFO消息等级的字符串"Hello World"。

===============[根据官方文档说明]

内核模块的编程必须至少编写两个函数,一个初始化模块函数清除模块函数
初始化模块函数在模块被insmod(加载)到内核中时被调用,清除模块函数在模块被rmmod(卸载)之前被调用。
在linux内核2.4版本之前这个初始化模块函数和清除模块函数必须被命名为指定的函数名"init_module"和"cleanup_module",在linux2.4提出的新特性,使用module_init()和module_exit()宏对初始化模块函数和清除模块函数进行注册这允许了开发者自定义初始化模块函数和清除模块函数的名字。

====================.

以下编写内核模块的方式采用linux2.4后的宏注册方法,一般来说初始化模块函数返回值为int,传入参数为void;清除模块函数返回值和传参都为void。

编写完毕后一定要要使用宏module_init和module_exit对初始化模块函数和清除模块函数进行注册。这两个宏被定义在linux/init.h中。

注册完毕后,使用MODULE_LICENSE写入模块的描述信息,分别写入了:"GPL"许可证的协议声明、作者和模块描述信息。

最后,执行Makefile文件对模块进行编译,可以看到Makefile文件中导入体系相关的build文件夹,对模块进行编译。

编译结束后,除了hello.c和Makefile增加了一下文件,其中的hello.ko就是编译好的内核模块。

hello.ko  hello.mod.c  hello.mod.o  hello.o modules.order  Module.symvers

通过modinfo hello.ko可以查看内核模块的相关信息。这里可以看到我们刚才使用MODULE_XXX系列宏写入的协议、作者等描述信息。
在这里插入图片描述

我们可以通过sudo insmod hello.ko命令将hello模块加载到内核。当我们想卸载模块时,通过sudo rmmod hello.ko命令可以将hello模块进行卸载。

然后使用lsmod命令,查看已经成功加载好的模块信息。可以看到hello模块被成功加载。
在这里插入图片描述
当我们执行sudo insmod hello.ko命令将模块加载后,在终端中却没有发现我们所写的加载函数中hello world的打印信息。这是因为printk函数为内核函数,打印的信息只会写入到日志文件或者控制台(字符界面的终端)中,图形界面的终端一般不会显示。并且如果想让打印的信息出现在控制台(字符界面终端),还必须满足一个优先级的关系

上面的printk的消息等级被声明为KERN_INFO等级,KERN_INFO是一个宏,在linux4.15-30版本源码它被定义在include/linux/kern_levels.h下。同样控制台也存在一个优先级,它定义在宏CONSOLE_LOGLEVEL中。
如果你调用的printk的消息等级(优先级)大于控制台的优先级,printk所打印的信息才会在控制台(字符界面终端)中显示出来,并且如果你的计算机正确的运行着日志记录守护进程syslogd和klogd,还会将printk所打印的信息写入到/var/log/messages中。

如果你调用的printk消息等级(优先级)小于控制台的优先级,那么你打印的信息就需要执行dmesg命令查看内核的环形缓冲区信息来找到他们。对于printk更多的解释将会在任务4中进行展开。

这里因为我们的printk的消息等级小于控制台的消息等级,所以我们对模块进行加载和卸载后,在控制台并没有打印出使用printk打印的字符串。
在这里插入图片描述
需要执行dmesg命令,查看内核的环形缓冲区信息打印情况来找到我们打印的内容。
在这里插入图片描述

子任务2、练习内核模块多文件编译

hello_init.c

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
static int init_hello(void)
{
   
	printk(KERN_INFO "Hello, World!\n");
	return 0;
}
module_init(init_hello);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zjc");
MODULE_DESCRIPTION("A test project");

hello_exit.c

#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
static void<
  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值