使用dmesg打印所有日志

目录
使用修改打印级别使用dmesg打印所有日志测试小结参考文档附录(3.4内核的分析)
title: 驱动调试(一)-
date: 2019/1/9 19:35:14
toc: true
---
驱动调试(一)- 引入
uboot的启动参数中定义了我们内核启动时的信息输出
bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0
如果去除=,则内核复制后没有信息输出,可以看下lcd,已经有显示了
#OpenJTAG> set bootargs noinitrd root=/dev/mtdblock3 init=/linuxrcStarting kernel ...Uncompressing Linux.............................................. done, booting the kernel.
也可以设置为tty1,直接在LCD上输出,这个需要有lcd驱动程序了(废话 哈哈),这里我试了tty0和tty1 和tty2,tty3都是在lcd显示
setbootargs noinitrd root=/dev/mtdblock3 init=/linuxrc console=tty1
其实也可以使用多个终端输出,比如这样
setbootargs noinitrd root=/dev/mtdblock3 init=/linuxrc console=tty1 console=ttySAC0
注意 这里设置参数后不要使用save 保存到flash,直接退回到menu,输入b启动即可
那么内核的是怎么根据=xxx找到输出的硬件设备的?
框架 入口
搜索=,在有以下代码("=", );,这个宏是用来处理启动参数的
文件在\.c
/** Set up a list of consoles.Called from init/main.c*/static int __init console_setup(char *str){char name[sizeof(console_cmdline[0].name)];char *s, *options;int idx;/** Decode str into name, index, options.*/// 先复制8字节到nameif (str[0] >= '0' && str[0] <= '9') {strcpy(name, "ttyS");strncpy(name + 4, str, sizeof(name) - 5);} else {strncpy(name, str, sizeof(name) - 1);}name[sizeof(name) - 1] = 0;// 判断是否有"," 也就是是不是有选项字节if ((options = strchr(str, ',')) != NULL)*(options++) = 0;#ifdef __sparc__if (!strcmp(str, "ttya"))strcpy(name, "ttyS0");if (!strcmp(str, "ttyb"))strcpy(name, "ttyS1");#endif//从name中 找数字for (s = name; *s; s++)if ((*s >= '0' && *s <= '9') || *s == ',')break;idx = simple_strtoul(s, NULL, 10);*s = 0;// 这里就会添加控制台了,也就是记录下来,还没有找到硬件add_preferred_console(name, idx, options);return 1;}__setup("console=", console_setup);
e
这里是将命令行参数解析后存入全绝的结构体变量,这里只是存起来,并没有去解析
add_preferred_console{struct console_cmdline *c;// 这里有个全局变量 console_cmdline,保存所有的终端,这里支持8个//#define MAX_CMDLINECONSOLES 8//static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];//step1 判断是否存在了已经for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)...//指向最后一个命令行的参数console_cmdlineselected_console = i;//step2 存入这个全局的数组 包括name,序号,选项c = &console_cmdline[i];memcpy(c->name, name, sizeof(c->name));c->name[sizeof(c->name) - 1] = 0;c->options = options;c->index = idx;}
继续搜索这个全局变量,可以看到注册函数,匹配命令行的name和注册的驱动后加入到链表中
selected_console 在add_preferred_console 处理命令参数的时候 指向最后一个命令行的参数console_cmdline
register_console// 如果没有注册过console,preferred_console 指向selected_console 也就是最后一个命令行参数的consoleif (preferred_console < 0 || bootconsole || !console_drivers)preferred_console = selected_console;// 如果没有注册过console,会先来一个初始化这第一个来注册的consoleif (preferred_console < 0)console->setup(console, NULL)console->index = 0; //没有注册时,强制赋值0for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];i++)...// 1. 比较命令行的名字与注册的驱动的名字,如果name匹配// 2. 执行带有option的 console->setup(console, console_cmdline[i].options)// 3. 如果成功,设置标志console->flags |= CON_ENABLED;console->index = console_cmdline[i].index;//4. 选择一个作为preferred_console,如果匹配到最后一个命令行,preferred_console就等于这个selected_console=最后一个命令行if (i == selected_console) {console->flags |= CON_CONSDEV;preferred_console = selected_console;// 5.加入到链表 console_drivers ,注册的console本身也包含了一个链表指向if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {console->next = console_drivers;console_drivers = console;if (console->next)console->next->flags &= ~CON_CONSDEV;} else {console->next = console_drivers->next;console_drivers->next = console;}