一、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:文章来源:https://www.toymoban.com/news/detail-751413.html
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!
文章来源地址https://www.toymoban.com/news/detail-751413.html
到了这里,关于printk日志级别以及Linux内核atomic_set介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!