printk日志级别以及Linux内核atomic_set介绍


一、printk 介绍

printk 是 Linux 内核中用于输出信息的函数,它可以将信息输出到各种不同的设备和位置,例如控制台、串口、日志文件等。

printk 函数的输出会被写入内核的环形缓冲区中,并由一个或多个后台进程将其传输到目标设备或位置。可以使用 dmesg 命令来查看内核环形缓冲区中的输出消息。此外,也可以将 printk 输出重定向到其他设备或位置,例如串口或日志文件。

需要注意的是,由于 printk 函数可能会在中断上下文或原子上下文中被调用,因此需要遵循一些特殊规则来确保其安全性和可用性。例如,在中断上下文中只能使用 printk 函数的非阻塞版本,而在原子上下文中则不能使用 printk 函数。此外,为了避免死锁等问题,还需要谨慎地使用 printk 函数以及与之相关的锁机制。

(1)printk函数原型介绍

printk 是 Linux 内核中用于输出信息的函数。它的基本语法如下:

int printk(const char *fmt, ...);

其中,fmt 是格式化字符串,它指定了输出信息的格式,下面会介绍;… 表示可变参数列表,它可以传递多个参数给格式化字符串。

(2)printk日志级别介绍

在Linux内核中,printk函数用于在内核中输出日志信息。printk函数支持不同的日志级别来区分日志的重要性和优先级。

这些日志级别的定义位于头文件<linux/kernel.h>中。可以在Linux源代码树中的/include/linux/kernel.h路径下找到该头文件。

常用的日志级别包括:

  • KERN_EMERG:紧急情况,系统无法使用;
  • KERN_ALERT:需要立即采取行动;
  • KERN_CRIT:临界状态,需要注意;
  • KERN_ERR:错误信息;
  • KERN_WARNING:警告信息;
  • KERN_NOTICE:普通但重要的信息;
  • KERN_INFO:一般信息;
  • KERN_DEBUG:调试信息。

可以通过在格式化字符串前加上相应的日志级别前缀来指定输出的日志级别。

举个栗子:

printk(KERN_WARNING "This is a warning message\n");

(3)举个栗子

printk_test.c:

/*************************************************************************
    > File Name: printk_test.c
    > Author: WangDengtao
    > Mail: 1799055460@qq.com 
    > Created Time: 2023年04月02日 星期日 17时59分29秒
 ************************************************************************/

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

// 打印普通信息(info)
#define INFO(fmt, ...) \
    printk(KERN_INFO "INFO: " fmt "\n", ##__VA_ARGS__)

static int __init my_module_init(void)
{
	printk(KERN_INFO"Enter");
    printk(KERN_DEBUG "Debugging information!\n");
    printk(KERN_NOTICE "Common but important information!\n");
    printk(KERN_WARNING "Warning message!\n");
    printk(KERN_ERR "Error message!\n");
    printk(KERN_CRIT "Critical states, you need to pay attention!\n");
    printk(KERN_ALERT "Immediate action is needed!\n");
    printk(KERN_EMERG "GIn an emergency, the system is unavailable!\n");
    INFO("General Information!");

    return 0;
}

static void __exit my_module_exit(void)
{
	INFO("Exit");
}

module_init(my_module_init);
module_exit(my_module_exit);

/*添加LICENSE和作者信息,是来告诉内核,该模块带有一个自由许可证;没有这样的说明,在加载模块的时内核会“抱怨”.*/
MODULE_LICENSE("Dual BSD/GPL");//许可 GPL、GPL v2、Dual MPL/GPL、Proprietary(专有)等,没有内核会提示.
MODULE_AUTHOR("WangDengtao");//作者
MODULE_VERSION("V1.0");//版本

Makefile:

KERNAL_DIR ?= /lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
obj-m := printk_test.o

all:
	$(MAKE) -C $(KERNAL_DIR) M=$(PWD) modules
	@make clear

clean:
	@rm -f *.ko

clear:
	@rm -f *.o *.cmd *.mod *.mod.c
	@rm -rf *~ core .depend .tmp_versions Module.symvers modules.order -f
	@rm -f .*ko.cmd .*.o.cmd .*.o.d
	@rm -f *.unsigned

make之后就可以看见我们的.ko驱动文件了。
安装卸载驱动:

wangdengtao@wangdengtao-virtual-machine:~/wangdengtao/driver/x86$ sudo insmod printk_test.ko 
wangdengtao@wangdengtao-virtual-machine:~/wangdengtao/driver/x86$ sudo rmmod printk_test

查看:

wangdengtao@wangdengtao-virtual-machine:~/wangdengtao/driver/x86$ sudo dmesg | tail -10
[ 4993.976274] Enter
[ 4993.976277] Debugging information!
[ 4993.976278] Common but important information!
[ 4993.976278] Warning message!
[ 4993.976279] Error message!
[ 4993.976281] Critical states, you need to pay attention!
[ 4993.976282] Immediate action is needed!
[ 4993.976282] GIn an emergency, the system is unavailable!
[ 4993.976283] INFO: General Information!
[ 4997.412881] INFO: Exit

在这里插入图片描述
宏定义的INFO已经有’\n’了,所以就不需要了。


二、atomic_set 介绍

包含的头文件:

#include <asm/atomic.h>

(1)atomic_set 函数原型介绍

函数 atomic_set() 的功能是将原子类型的变量v的值设置为i。

static inline void atomic_set(atomic_t * v, int i)
  • v:原子类型变量,该参数一般传递一个指针;
  • 整型值,原子类型变量的值将被设置为该值;
  • 函数atomic_set()没有返回值。

原子类型 atomic_t

typedef struct {
        int counter;
} atomic_t;

counter 为一个int变量的计数器。

(2)举个栗子

首先定义一个原子类型my_atomic,然后调用函数atomic_set()将其值设置为5,并通过函数atomic_read()将原子类型my_atomic的counter字段读出。由输出信息可知,调用atomic_set()后,原子类型的值由0变为了5。

atomic_set_test.c:

/*************************************************************************
    > File Name: atomic_set_test.c
    > Author: WangDengtao
    > Mail: 1799055460@qq.com 
    > Created Time: 2023年04月02日 星期日 19时12分55秒
 ************************************************************************/

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

atomic_t my_atomic;
static int __init atomic_set_init(void)
{
    int i = 5;
    printk("before atomic_set, my_atomic.counter = %d\n", atomic_read(&my_atomic));
    atomic_set(&my_atomic, i);
    printk("after atomic_set, my_atomic.counter = %d\n", atomic_read(&my_atomic));
    return 0;
}
static void __exit atomic_set_exit(void)
{
    printk("exit!\n");
}

module_init(atomic_set_init);
module_exit(atomic_set_exit);

/*添加LICENSE和作者信息,是来告诉内核,该模块带有一个自由许可证;没有这样的说明,在加载模块的时内核会“抱怨”.*/
MODULE_LICENSE("Dual BSD/GPL");//许可 GPL、GPL v2、Dual MPL/GPL、Proprietary(专有)等,没有内核会提示.
MODULE_AUTHOR("WangDengtao");//作者
MODULE_VERSION("V1.0");//版本

Makefile:

KERNAL_DIR ?= /lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
obj-m := atomic_set_test.o

all:
	$(MAKE) -C $(KERNAL_DIR) M=$(PWD) modules
	@make clear

clean:
	@rm -f *.ko

clear:
	@rm -f *.o *.cmd *.mod *.mod.c
	@rm -rf *~ core .depend .tmp_versions Module.symvers modules.order -f
	@rm -f .*ko.cmd .*.o.cmd .*.o.d
	@rm -f *.unsigned
wangdengtao@wangdengtao-virtual-machine:~/wangdengtao/driver/x86$ sudo insmod atomic_set_test.ko  
wangdengtao@wangdengtao-virtual-machine:~/wangdengtao/driver/x86$ sudo rmmod atomic_set_test 
wangdengtao@wangdengtao-virtual-machine:~/wangdengtao/driver/x86$ sudo dmesg | tail -3
[ 9410.583005] before atomic_set, my_atomic.counter = 0
[ 9410.583029] after atomic_set, my_atomic.counter = 5
[ 9420.932523] exit!

在这里插入图片描述


  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值