如何编写一个简单的 Linux 内核模块

如何编写一个简单的 Linux 内核模块,第1张

编写helloworld.c及其对应的Makefile。

helloworld.c:

#include <linux/module.h>#include <linux/kernel.h>int init_hello_module(void)

{

printk("***************Start***************\n")

printk("Hello World! Start of hello world module!\n") return 0

}void exit_hello_module(void)

{

printk("***************End***************\n")

printk("Hello World! End of hello world module!\n")

}

MODULE_LICENSE("Dual BSD/GPL")

module_init(init_hello_module)

module_exit(exit_hello_module)1234567891011121314151617181920

Makefile:

# To build modules outside of the kernel tree, we run "make"# in the kernel source treethe Makefile these then includes this# Makefile once again.# This conditional selects whether we are being included from the# kernel Makefile or not.# called from kernel build system: just declare what our modules areobj-m := helloworld.oCROSS_COMPILE =

CC= gcc# Assume the source tree is where the running kernel was built

# You should set KERNELDIR in the environment if it's elsewhere

KERNELDIR ?= /usr/src/linux-headers-$(shell uname -r)# The current directory is passed to sub-makes as argument

PWD := $(shell pwd)all: modulesmodules:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean:

rm -rf *.o *~ core .depend *.symvers .*.cmd *.ko *.mod.c .tmp_versions $(TARGET)

在Makefile中,在obj-m := helloworld.o这句中,.o的文件名要与编译的.c文件名一致。

KERNELDIR ?= /usr/src/linux-headers-$(shell uname -r)指示当前linux系统内核的源码位置。

在编写linux内核模块的时候,有时候我们需要调用一只内核模块里面的函数,然而如果是在不同目录下面编译生成的内核模块,此时A模块去调用B模块的函数时候会出现函数未定义,无法调用的情况。那么以前我是在同一个目录下面,先后写两个makefile,然后编译生成两个不同的内核模块,这种方式可以正常实现A模块调用B模块里面的函数,不过非常麻烦。本博文将会针对这种情况提出一种可以同时生成多个内核模块,不要再次编译的方面,下面贴出源码:

内核模块cal.ko:

#include <linux/module.h>

#include <linux/init.h>

MODULE_LICENSE("GPL")

int add(int a, int b) {

return a+b

}

int sub(int a, int b) {

return a-b

}

static int sym_init() {

return 0

}

static int sym_exit() {

return 0

}

module_init(sym_init)

module_exit(sym_exit)

EXPORT_SYMBOL(add)

EXPORT_SYMBOL(sub)

内核模块hello.ko

#include <linux/module.h>

#include <linux/init.h>

MODULE_LICENSE("GPL")

MODULE_AUTHOR("David Xie")

MODULE_DESCRIPTION("Hello World Module")

MODULE_ALIAS("a simplest module")

static int age = 10

module_param(age, int, S_IRUGO)//allow all user to use this param

int add(int a, int b)

int sub(int a, int b)

static int hello_init(void)

{

printk("<0>"" Hello World! age = %d\n", add(10, 20))//调用内核模块cal.ko里面的add函数

return 0

}

static void hello_exit(void)

{

printk("<0>""hello exit %d\n", sub(30,10))//调用内核模块cal.ko里面的sub函数

}

module_init(hello_init)

module_exit(hello_exit)

可以生成多个内核模块的makefile

ifneq ($(KERNELRELEASE),)

obj-m := cal.o hello.o

cal-objs := operator.o

hello-objs := main.o

else

KDIR := /lib/modules/2.6.32-21-generic/build

all:

make -C $(KDIR) M=$(PWD) modules

clean:

rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order

endif

此时在当前目录执行make就会产生cal.ko和hello.ko两个内核模块

inet_network() / inet_addr() 等是供用户层使用的库函数。在内核里面一般都是直接使用整数型,而不用点分十进制形式的IP形式。不过如果需要的话,可以使用 in_aton() 函数,包含 linux/inet.h 头文件即可。find/grep 查找看下吧。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/6173739.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-03-17
下一篇2023-03-17

发表评论

登录后才能评论

评论列表(0条)

    保存