Blogs

Linux.内核开发 - 第1部分:Hello Kernel!

丹尼斯卡瓦利2019年6月2日2评论

我们在每种语言或框架中的第一节目通常是臭名昭着的“Hello World”计划。对于这个Linux内核模块开发介绍,我们将遵循相同的概念,而不是通常的“Hello World”我们将成为“Hello Kernel!”你会在几个时刻理解的原因。请注意,在本文中,我不会专注于对此主题的深刻解释,因为这只是介绍。

但在我们潜入代码之前,我们需要最小了解内核模块以及它运行的位置。

内核模块和内核空间

内核模块是一个程序或一段代码,通常用c,可以在Linux内核中动态加载或卸载。以这种方式,您还可以内置模块进入Linux内核 不可能动态加载和卸载。

The linux kernel modules runs in a space called Kernel Space, where the kernel runs and provides its services. That means that you should not use some "userland" headers and functions in you code. But don't worry about it, the kernel has most functions that you normally use in C translated to Kernel Space, usually they have the same name but beginning with a "k". For an example, instead of using printf() you will use kprintf().

您的第一个内核模块

这是我们第一个内核模块的代码。 

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


/*
 * Init function of our module
 */
static int __init hellokernelmod_init(void)
{
 printk(KERN_INFO "Hello Kernel!\n");
 return 0;
}

/*
 * Exit function of our module.
 */
static void __exit hellokernelmod_exit(void)
{
 printk(KERN_INFO "Hasta la vista, Kernel!\n");
}

MODULE_AUTHOR("Your name here");
MODULE_DESCRIPTION("Simple Kernel Module to display messages on init and exit.");
MODULE_LICENSE("MIT");


module_init(hellokernelmod_init);
module_exit(hellokernelmod_exit);

好的,让我们看看那里发生了什么。
首先,我们需要为模块提供必要的标题来工作。

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

In our case we need kernel.h for the kernel functions (printk) and module.h for the module functions (init, exit..), every module needs this header.

然后,我们有2个功能: 

static int __init hellokernelmod_init(void)
{
 printk(KERN_INFO "Hello Kernel!\n");
 return 0;
}

当我们将模块加载到内核时,此功能将执行。这被称为模块的“init”功能,它需要在成功时返回0。通常,您alloc您需要的内存并执行初始化 of you module here.
__Init参数告诉内核在初始化之后释放此功能的空间。这仅适用于内置内核模块。

static void __exit hellokernelmod_exit(void)
{
 printk(KERN_INFO "Hasta la vista, Kernel!\n");
}

当我们从内核卸载模块时,将执行此函数。这被称为模块的“退出”或“清理”功能,基本上您在Init功能中所做的一切您需要在此处“撤消”,如释放内存空间,关闭套接字,整理设备等。

__exit参数告诉内核在模块内置时省略此功能,因为在内置模块中,此功能永远不会执行。

MODULE_AUTHOR("Your name here");
MODULE_DESCRIPTION("Simple Kernel Module to display messages on init and exit.");
MODULE_LICENSE("MIT");

模块API具有一些宏,有助于定义模块,例如描述其功能,命名作者,许可,参数等。这就是我们与这些模块_ *宏做的事情。

你可以看到这些信息 

 $ modinfo <PATH-TO>/hellokernel.ko.

module_init(hellokernelmod_init);
module_exit(hellokernelmod_exit);

在这里,我们实际上是注册我们在模块的开头和退出中执行的功能。

Now we need to compile and run our code. If you try to compile this module with $ gcc hellokernel.c, you are going to have a bad time.

我们需要正确构建我们的内核模块,这个makefile应该为我们做诀窍。

obj-m += hellokernel.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

首先,我们需要说出我们正在建造的东西。请注意,* .o需要匹配您的模块.c文件。

“所有”论证将为我们构建模块。 “-c”选项按照构建目录的路径$(shell uname -r) (A.K.A.您的内核版本)将使“使”将文件夹更改为指定的文件夹,并达到它的顶部makefile。

“m =”对“make”命令表示,编译后应该复制编译的二进制文件。

最后,我们说我们要使用“模块”参数编译内核模块。

The "clean" 将删除目的文件夹的所有已编译的二进制文件。

Now a simple $ make all 命令应适当编译我们的模块。

编译生成一堆文件,但我们将专注于生成的.ko文件,这是我们的内核模块。

To install-it, use the insmod tool. Only super users can load and unload kernel modules.

$ sudo insmod <path-to>/hellokernel.ko 

要查看内核是否加载成功使用lsmod 工具,此工具将列出系统中加载的所有内核模块。

$ lsmod

现在,如果您查看内核日志,您应该看到光荣的消息“Hello Kernel!”。

You can do this with the dmesg tool.

$ dmesg

要卸载内核模块,请使用RMMod工具。

$ sudo rmmod hellokernel

Again, use the dmesg tool to see our cleanup message "Hasta la vista, kernel!".

恭喜,你刚刚做了第一(我认为,所以)内核模块。

在下一个文章中,我们将深入在这个世界内核心模块中,也许是一个LED驱动程序,因为有什么比使LED眨眼更令人兴奋!

Happy coding :)


[]
评论 g_sanket.2019年7月24日

非常奇怪地解释了丹尼斯


[]
评论 deniscavalli.2019年9月13日

谢谢g_sanket,我希望在不久的将来发布更多教程:)

要发布回复评论,请单击连接到每个注释的“回复”按钮。发布新的评论(不是回复评论),请在评论的顶部查看“写评论”选项卡。

注册将允许您参加所有相关网站的论坛,并为您提供所有PDF下载。

注册

我同意 使用条款隐私政策.

尝试我们偶尔但流行的时事通讯。非常容易取消订阅。
或登录