90.内核模块实验1

本文详细介绍了Linux内核模块开发中使用的头文件、printk打印函数及其等级,以及如何通过/proc/sys/kernel/printk调整打印级别。此外,还提供了一个简单的内核模块示例,展示如何使用module_init和module_exit宏,以及printk进行信息输出。
摘要由CSDN通过智能技术生成

一、内核模块头文件

#include <linux/module.h>:包含内核模块信息声明的相关函数。

#include <linux/init.h>:包含了 module_init( )module_exit( ) 函数的声明。(module_init解析

#include <linux/kernel.h>:包含内核提供的各种函数,如 printk 函数。

二、内核模块打印函数 printk

printf:glibc实现的打印函数,工作于用户空间 / 目态。

printk:内核模块无法使用glibc库函数,内核自身实现的一个类printf函数,但是需要指定打印等级(若不指定就是用默认的打印等级)。

printk 打印等级 相关定义如下:

/* include/linux/kern_levels.h */
#define KERN_SOH    	"\001"      	/* ASCII Start Of Header */
...
#define KERN_EMERG  	KERN_SOH "0"    /* system is unusable */
#define KERN_ALERT  	KERN_SOH "1"    /* action must be taken immediately */
#define KERN_CRIT   	KERN_SOH "2"    /* critical conditions */
#define KERN_ERR    	KERN_SOH "3"    /* error conditions */
#define KERN_WARNING    KERN_SOH "4"    /* warning conditions */
#define KERN_NOTICE 	KERN_SOH "5"    /* normal but significant condition */
#define KERN_INFO  		KERN_SOH "6"    /* informational */
#define KERN_DEBUG  	KERN_SOH "7"    /* debug-level messages */

注意表示等级的数字越小,则优先级越高。
只有 prink 指定的打印等级console 当前等级 小才能打印到console,等于都不行。

查看当前系统printk打印等级:cat /proc/sys/kernel/printk (不手动去修改的话就是依次打印这个数组的4个成员值)。

//kernel/printk/printk.c
int console_printk[4] = {
	/* console_loglevel 当前控制台日志级别 */
    CONSOLE_LOGLEVEL_DEFAULT, 
    /* default_message_loglevel 默认消息日志级别 */  
    MESSAGE_LOGLEVEL_DEFAULT,
    /* minimum_console_loglevel 最小的控制台级别 */   
    CONSOLE_LOGLEVEL_MIN,
    /* default_console_loglevel 默认控制台日志级别 */
    CONSOLE_LOGLEVEL_DEFAULT,   
};

/ # 
/ # cat /proc/sys/kernel/printk
7       4       1       7
/ # 

/proc/sys/kernel/printk

Printk 共有4个参数

Cat /proc/sys/kernel/printk

7 4 1 7

  • (1)第一个参数 7表示小于7优先级消息才会被输出到控制台。
    (2)第二个参数4 表示默认的printk消息优先级别,即printk(“hell world”);优先级为4, 由于4<7,故可以被打印到控制台。
    (3)第三个参数1 表示可接收的最高优先级,当printk disable控制台输出时,设置第一个参数为1,但是,从内核等级来看,还有优先级0,这个是printk最高级优先级,一般用于内核严重消息打印。比如内存错误或者 watchdog reset.也可以设置第一个和第三个参数为0
    (4)第四个参数7 默认控制台优先级,即第一个参数的默认优先级。

修改上述四个默认优先级的方法:
1、修改源码
2、修改 /proc/sys/kernel/printk 文件
要设置的值 写入到 /proc/sys/kernel/printk 中。我们要先 cat /proc/sys/kernel/printk 来看一下这个文件中都有什么值。然后我们再写入。
其中这里的格式为:控制台的日志级别、默认消息日志级别、最小控制台日志级别 和 默认控制台日志级别
而我们要设置的就是第一个控制台的日志级别。我们通过 echo “W X Y Z” > /proc/sys/kernel/printk 将我们想要设置的四个值写入到 /proc/sys/kernel/printk 中。

通过 dmesg 可以查看 printk 的所有打印信息

内核log缓冲区大小有限制,缓冲区数据可能被冲掉

三、例程

1、内核模块源码

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

/* 
 * __init 是把该函数放到统一的段里,所有内核模块的入口函数都存到这个指定的段里,
 * 等到内核调用完成就释放这个段,以此节约内存空间
 * __exit 同理
 */
static int __init hello_init(void)
 {
	printk(KERN_EMERG "[KERN_EMERG]  Hello World Module Init\n");
	/* 也可以手动替换上面的宏如下,效果是一样的
	 * printk("\001" "1""[ KERN_EMERG ]  Hello World Module Init\n");
	 */
	printk( "[default]  Hello World Module Init\n");
 	return 0;
}

static void __exit hello_exit(void)
{
	printk("[default]   goodbye\n");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");

MODULE_AUTHOR("embedfire ");
MODULE_DESCRIPTION("hello world module");
MODULE_ALIAS("test_module");

2、Makefile

# 内核源码所在路径
KERNELDIR := /home/jl/linux/imx6ull/alientek_made_linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
CURRENT_PATH := $(shell pwd)
# 指定编译出的内核模块的名字
obj-m := test.o
build: kernel_modules

# -C 选项来指定子Makefile,借助内核Makefile执行modules伪目标来编译我们的模块
# $(CURDIR):Makefile默认变量,值为当前目录所在路径
# M=$(CURRENT_PATH) 告诉内核 模块源码所在位置
kernel_modules:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules  ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
clean:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

加一个 copy伪目标,省得每次都要手动复制

KERNELDIR := /home/jl/linux/imx6ull/linux/linux-imx-rel_imx_4.1.15_2.1.0_ga
#KERNELDIR := /home/jl/linux/imx6ull/alientek_made_linux/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
CURRENT_PATH := $(shell pwd)
obj-m := test.o
# 注意这个模式替换操作
res := $(patsubst %.o,%.ko,$(obj-m))
build: kernel_modules

kernel_modules:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules  ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
clean:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
copy:
	sudo cp  $(res)  ../../../nfs/rootfs/lib/modules/4.1.15/ -rf
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值