0%

打印 日志 内核打印

打印

学C语言第一个就是printf(“Hello World\n”);这个可以说基本就是所有程序员的开头了,若干年之后再次看到这句话,真的会有不同的感觉吧。回到正题,为什么是打印呢?因为在上古时代,那些机械和电脑非常非常打的时候,输出是没有屏幕的,但是人们想要一个记录和输出,此时就是打卡机了,就是在纸上打孔,这个孔就是数据输出啦,随着慢慢发展,也就沿用下来了。

打印操作

这个真的太多了,而且分平台,分语法,分架构,分系统等等,不过,现在是很少用打印机了,写代码还用打印机才是逆天啊。所以,一般都是屏幕直接现实或者命令行输出。

C语言就是fputc、printf等操作;linuxc就是printf、perror等操作;Qt就是qdebug咯;python就是print啦;自然还有mcu那些非windows,非控制台的环境了,他们就得重定向才能使用打印函数哦,就是把打印函数重写成串口发送等函数。这里要提一下啊了,为什么,嵌入式不能使用控制台。我当时学c语言的,都是devC++和gcc编译的,我觉得有控制台才对啊,为什么mcu就不能有控制台那些东西呢,还要费尽心思搞那些环境和芯片配置,后面懂得越来越多才知道,其实所有编译都可以算是交叉编译,因为都是为了满足一个平台和架构的特性,之所以在windows上面可以跑控制台是因为,他本来就是用自己的编译链,本来就是跑自己环境和架构,同理因为gcc是支持linux环境,所以linux才能用gcc编译,然后在命令行中打印出来,后面又要使用交叉编译才能烧录到特定的架构的芯片上,因为linux环境和架构是同目标的芯片又是不同的,所以还得要一次交叉编译才行。

花活,多颜色打印:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
一个朋友 11:24:59
#ifndef _COLOR_H_
#define _COLOR_H_

#define NONE "\e[0m" //清除颜色,即之后的打印为正常输出,之前的不受影响
#define BLACK "\e[0;30m" //深黑
#define L_BLACK "\e[1;30m" //亮黑,偏灰褐
#define RED "\e[0;31m" //深红,暗红
#define L_RED "\e[1;31m" //鲜红
#define GREEN "\e[0;32m" //深绿,暗绿
#define L_GREEN "\e[1;32m" //鲜绿
#define BROWN "\e[0;33m" //深黄,暗黄
#define YELLOW "\e[1;33m" //鲜黄
#define BLUE "\e[0;34m" //深蓝,暗蓝
#define L_BLUE "\e[1;34m" //亮蓝,偏白灰
#define PURPLE "\e[0;35m" //深粉,暗粉,偏暗紫
#define L_PURPLE "\e[1;35m" //亮粉,偏白灰
#define CYAN "\e[0;36m" //暗青色
#define L_CYAN "\e[1;36m" //鲜亮青色
#define GRAY "\e[0;37m" //灰色
#define WHITE "\e[1;37m" //白色,字体粗一点,比正常大,比bold小
#define BOLD "\e[1m" //白色,粗体
#define UNDERLINE "\e[4m" //下划线,白色,正常大小
#define BLINK "\e[5m" //闪烁,白色,正常大小
#define REVERSE "\e[7m" //反转,即字体背景为白色,字体为黑色
#define HIDE "\e[8m" //隐藏
#define CLEAR "\e[2J" //清除
#define CLRLINE "\r\e[K" //清除行

#endif

printf("This is a character control test!\n" );
printf("[%2u]" CLEAR "CLEAR\n" NONE, __LINE__);
printf("[%2u]" BLACK "BLACK " L_BLACK "L_BLACK\n" NONE, __LINE__);
printf("[%2u]" RED "RED " L_RED "L_RED\n" NONE, __LINE__);
printf("[%2u]" GREEN "GREEN " L_GREEN "L_GREEN\n" NONE, __LINE__);
printf("[%2u]" BROWN "BROWN " YELLOW "YELLOW\n" NONE, __LINE__);
printf("[%2u]" BLUE "BLUE " L_BLUE "L_BLUE\n" NONE, __LINE__);
printf("[%2u]" PURPLE "PURPLE " L_PURPLE "L_PURPLE\n" NONE, __LINE__);
printf("[%2u]" CYAN "CYAN " L_CYAN "L_CYAN\n" NONE, __LINE__);
printf("[%2u]" GRAY "GRAY " WHITE "WHITE\n" NONE, __LINE__);
printf("[%2u]" BOLD "BOLD\n" NONE, __LINE__);
printf("[%2u]" UNDERLINE "UNDERLINE\n" NONE, __LINE__);
printf("[%2u]" BLINK "BLINK\n" NONE, __LINE__);
printf("[%2u]" REVERSE "REVERSE\n" NONE, __LINE__);
printf("[%2u]" HIDE "HIDE\n" NONE, __LINE__);


C语言中使用printf()打印漂亮的颜色字体_c语言printf颜色-CSDN博客

这里巧妙的使用字符串的自动拼接,而且不只是改变字体颜色那么简单哦,还可以改背景色,前景色等诸多操作,感兴趣去了解一下。给自己的枯燥无味的debug生活一点乐子咯。还有那种ai雌小鬼助手,打印出来的那些杂鱼啥的特殊颜色字体应该都是这样可以实现的哦。

日志

一开始,我看到那些神秘兮兮的log函数,我真的觉得有什么特别牛的东西,后面我才知道,他就是打印的一层封装,他本质还是打印函数,不过是会打印出操作、警告、操作者等属性,就是打印之前还会把其他属性也打印出来。这个在mcu中,因为空间的问题,所以都是直接打印出来没有保存的,如果使用文件系统就可以存放到文件系统,这样可以命令行去访问特定文件来知道干了什么,前提是空间要够啊。linux就不用说了,你敲的每一行指令,都有log历史记录的,用户是谁,干了什么,是否危险,什么权限都知道的。

内核打印

这个就是搞linux内核驱动的啦。Linux 内核共提供了八种不同的消息级别,分为级别 0~7。数值越大,表示级别越低,对应的消息越不重要。相应的宏定义include/linux/kern_levels.h 文件中。

KERN_EMERG 表示紧急事件,一般是系统崩溃之前提示的消息;
KERN_ALERT 表示必须立即采取行动的消息;
KERN_CRIT 表示临界状态,通常涉及严重的硬件或软件操作失败;
KERN_ERR 用于报告错误状态,设备驱动程序会经常使用该级别来报告来自硬件的问题;
KERN_WARNING 对可能出现问题的情况进行警告,这类情况通常不会对系统造成严重的问题;
KERN_NOTICE 表示有必要进行提示的正常情形,许多与安全相关的状况用这个级别进行汇报;
KERN_INFO 表示内核提示信息,很多驱动程序在启动的时候,用这个级别打印出它们找到的硬件信息;
KERN_DEBUG 用于调试信息。

1
2
3
4
5
6
7
8
#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 */

注意:打印消息的级别大于控制台的打印级别时,才能出现在终端。并且:数字越大,级别越低

1
2
$ cat /proc/sys/kernel/printk
4 4 1 7

控制台打印级别 消息的默认打印级别 控制台最大打印级别 控制台最小级别

四个数值的含义如下:

  • 控制台日志级别:优先级高于该值的消息将被打印至控制台;
  • 默认的消息日志级别:将用该优先级来打印没有优先级的消息(即 printk 没有指定消息级别);
  • 最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级);
  • 默认的控制台日志级别:控制台日志级别的缺省值。
1
2
printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);   //此时是没有设置打印等级的,就是默认4
printk(KERN_DEBUG "HELLO LINUX PRINTK\n"); //这个就是设置等级啦,KERN_DEBUG

Linux内核之 printk 打印_linux printk-CSDN博客

总结

打印是入门和快速测试的基础,日志是可以记录所有操作,可以保存到本地,这样其实是更加有利于bug复现的,还有调试交互,后续设计的,不过mcu和那些空间本来就少的设备是真的遭不住的。内核打印,就是写驱动的人才用得到的东西,因为此时打印函数都是无效的了,只能通过内核提供的打印函数才能实现打印效果哦。

-------------下次的来访是什么时候呢[doge]-------------