编写linux最简单内核模块helloworld

一、创建test目录,并在该目录下新建hello.c和Makefile文件
编写hello.c和Makefile文件
hello.c:

#include 
#include 
#include 

int hello_init(void)
{
        printk(KERN_INFO"Hello World!\n");
        return 0;
}

void hello_exit(void)
{
        printk(KERN_INFO"------exit------\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Adolph_wy");
MODULE_DESCRIPTION("This is a simple hello world module");

说明:所有的linux内核都必须包含头文件module.h
头文件kernel.h包含了常用的内核函数
头文件init.h包含了宏_init和_exit,一个内核模块至少包含两个函数,分别是模块被加载时执行的初始化函数init_module()和模块卸载时执行的结束函数cleanup_module()。在大部分内核版本里面这两个函数可以随意命名,通过宏module_init()和module_exit()注册调用要编译的内核模块,把代码嵌进内核空间。
这里的hello_init()函数为模块的初始化函数,hello_exit()为模块的退出和清理函数
其中printk()函数是内核定义的函数,与C库中的printf()功能相似,将输出信息打印到终端或系统日志
MODULE_LICENSE(“GPL”)是模块许可证声明,这是必须的
后面的两个是关于模块的作者与描述,这是可选的

Makefile文件:

obj-m := hello.o
KERNELDIR := /lib/modules/3.13.0-32-generic/build
PWD := $(shell pwd)
all:
                make -C $(KERNELDIR) M=$(PWD) modules 
clean:
                make -C $(KERNELDIR) M=$(PWD) clean

说明:
1、obj这个变量指明最终产生模块的名字,如果内核模块的源文件只有一个,一般取与源文件一样的名字,这里的源文件是hello.c故取hello.o
【注】:如果有一个模块名为hello.ko是来自两个源文件(分别为hello1.c与hello2.c),正确写法应该是:

obj-m := hello.o
hello-objs := hello1.c hello2.c

2、定义一个变量KERNELDIR(该变量可以随意命名),KERNELDIR := /lib/modules/3.13.0-32-generic/build是编译内核模块所需要的Makefile路径,指示当前linux系统内核的源码位置,不同的操作系统可能路径不同
3、make -C 表示进入源代码目录编译,然后调用module目标,modules命令是在内核代码中执行的。传入参数M=当前目录,跳转到当前目录去make
【注】最后make -C需要注意tab键空格,会有颜色提示

二、编译模块
1、在Makefile文件所在目录下直接make,成功后查看是否生成hello.ko文件
编写linux最简单内核模块helloworld_第1张图片
2、使用insmod命令加载该模块模块,并用lsmod命令查看模块是否在内核中正确运行
编写linux最简单内核模块helloworld_第2张图片
3、使用dmesg命令查看模块运行后的输出
可以看到在系统日志里面有输出Hello World!
4、使用rmmod命令卸载模块
通过dmesg命令可以看到模块已经卸载

你可能感兴趣的:(linux下C编程学习)