函数printk的使用方法和printf相似,它用于内核打印消息。printk根据日志级别(loglevel)对消息进行分类。有时调试内核模块,打印信息太多了,可以通过修改/proc/sys/kernel/printk文件内容来控制。显示当前打印消息级别:
sw01@SMBIOS:~$ cat /proc/sys/kernel/printk
4 4 1 7
上面显示的4个数据分别对应:1,控制台日志级别:优先级[s1] 高于该值的消息将被打印至控制台;2,默认的消息日志级别:将用该优先级来打印没有优先级的消息;3,最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级);4,默认的控制台日志级别:控制台日志级别的缺省值, [s1]数值越小,优先级越高。其实这四个值是在kernel/printk.c 中被定义的,如下:
int console_printk[4] = {内核通过printk() 输出的信息具有日志级别,日志级别是通过在printk() 输出的字符串前加一个带尖括号的整数来控制的,如printk("<6>Hello, world!\n");。内核*提供了八种不同的日志级别
DEFAULT_CONSOLE_LOGLEVEL,/* console_loglevel */
DEFAULT_MESSAGE_LOGLEVEL,/* default_message_loglevel */
MINIMUM_CONSOLE_LOGLEVEL,/* minimum_console_loglevel */
DEFAULT_CONSOLE_LOGLEVEL,/* default_console_loglevel */
};
#define KERN_EMERG"<0>"/* system is unusable*/未指定日志级别的printk() 采用的默认级别是DEFAULT_MESSAGE_LOGLEVEL,这个宏在kernel/printk.c 中被定义为整数4,即对应KERN_WARNING。
#define KERN_ALERT"<1>"/* action must be taken immediately*/
#define KERN_CRIT"<2>"/* critical conditions*/
#define KERN_ERR"<3>"/* error conditions*/
#define KERN_WARNING"<4>"/* warning conditions*/
#define KERN_NOTICE"<5>"/* normal but significant condition*/
#define KERN_INFO"<6>"/* informational*/
#define KERN_DEBUG"<7>"/* debug-level messages*/
#define DEFAULT_MESSAGE_LOGLEVEL 4
了解了上面的这些知识后,我们就应该知道如何手动控制printk打印了。例如,我想屏蔽掉所有的内核printk打印,那么我只需要把第一个数值调到最小值1或者0。
# echo 1 4 1 7 > /proc/sys/kernel/printk或者# echo 0 4 0 7 > /proc/sys/kernel/printk
================================内核模块初始化入口函数的优先级==================================
对于需要考虑内核加载顺序和优先级的情况下,就需要对模块的入口函数进行评估调整,以下代码来自 linux内核源码中 include/linux/init.h 文件
117 #define pure_initcall(fn) __define_initcall("0",fn,1)数字越小,越靠前加载。所以基于:
118
119 #define core_initcall(fn) __define_initcall("1",fn,1)
120 #define core_initcall_sync(fn) __define_initcall("1s",fn,1s)
121 #define postcore_initcall(fn) __define_initcall("2",fn,2)
122 #define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
123 #define arch_initcall(fn) __define_initcall("3",fn,3)
124 #define arch_initcall_sync(fn) __define_initcall("3s",fn,3s)
125 #define subsys_initcall(fn) __define_initcall("4",fn,4)
126 #define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)
127 #define fs_initcall(fn) __define_initcall("5",fn,5)
128 #define fs_initcall_sync(fn) __define_initcall("5s",fn,5s)
129 #define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
130 #define device_initcall(fn) __define_initcall("6",fn,6)
131 #define device_initcall_sync(fn) __define_initcall("6s",fn,6s)
132 #define late_initcall(fn) __define_initcall("7",fn,7)
133 #define late_initcall_sync(fn) __define_initcall("7s",fn,7s)
134
135 #define __initcall(fn) device_initcall(fn)
#define module_init(x)__initcall(x);推断常用的 module_init 调用优先级为6低于subsys_initcall调用优先级4,而高于late_initcall
#define __initcall(fn) device_initcall(fn)
#define device_initcall(fn) __define_initcall("6",fn,6)