vprintk>release_console_sem>判断lev 打印 使用dmesg可。使用dmesg打印所有日志( 四 )。" />

使用dmesg打印所有日志( 四 )


使用( lev "...")来输出信息,如果没有指定lev,以默认的lev=4输出,具体是在中寻找驱动找到他的write函数输出
printk>vprintk>release_console_sem>判断lev 打印
使用dmesg可以打印所有日志,包括被屏蔽的
参考文档 \-.txt ,搜索查看命令行参数传递3.4内核代码分析附录(3.4内核的分析)
这个代码讲的比较具体,先不去仔细分析了
console驱动:一、基本概念终端是一种字符型设备,通常使用tty简称各种类型的终端 。linux的终端类型:/dev/ttySn,串行口终端/dev/pty,伪终端/dev/tty,当前进程的控制终端,可以是介绍的其它任何一种终端/dev/ttyn,tty1~tty6是虚拟终端,tty0当前虚拟终端的别名 。/dev/console,控制台终端(显示器)二、uboot传参数的处理linux启动时uboot传递进console=ttyS2,115200n8的参数内核中用__setup()宏声明参数处理的方法:__setup("console=", console_setup);1.console_cmdline结构体struct console_cmdline{char name[8];//驱动名intindex;//次设备号char *options;//选项#ifdef CONFIG_A11Y_BRAILLE_CONSOLEchar*brl_options;#endif};2.内核调用console_setup()函数处理uboot传进的console参数static int __init console_setup(char *str){char buf[sizeof(console_cmdline[0].name) + 4]; //分配驱动名+index的缓冲区,分配12个字节char *s, *options, *brl_options = NULL;int idx;#ifdef CONFIG_A11Y_BRAILLE_CONSOLEif (!memcmp(str, "brl,", 4)) {brl_options = "";str += 4;} else if (!memcmp(str, "brl=", 4)) {brl_options = str + 4;str = strchr(brl_options, ',');if (!str) {printk(KERN_ERR "need port name after brl=\n");return 1;}*(str++) = 0;}#endifif (str[0] >= '0' && str[0] <= '9') { //第一个参数属于[0,9]strcpy(buf, "ttyS");//则将其驱动名设为ttySstrncpy(buf + 4, str, sizeof(buf) - 5);//将次设备号放其后面} else {strncpy(buf, str, sizeof(buf) - 1); //否则直接将驱动名+设备号拷贝到buf中}buf[sizeof(buf) - 1] = 0;if ((options = strchr(str, ',')) != NULL) //获取options,即“115200n8”*(options++) = 0;#ifdef __sparc__if (!strcmp(str, "ttya"))strcpy(buf, "ttyS0");if (!strcmp(str, "ttyb"))strcpy(buf, "ttyS1");#endiffor (s = buf; *s; s++)if ((*s >= '0' && *s <= '9') || *s == ',')//移动指针s到次设备号处break;idx = simple_strtoul(s, NULL, 10); //获取次设备号,字符串转换成unsigend long long型数据,s表示字符串的开始,NULL表示字符串的结束,10表示进制 //这里返回的是次设备号=2*s = 0;__add_preferred_console(buf, idx, options, brl_options);console_set_on_cmdline = 1;return 1;}3.__add_preferred_console()函数//整体的作用是根据uboot传递的参数设置全局console_cmdline数组//该数组及全局selected_console,在register_console中会使用到static int __add_preferred_console(char *name, int idx, char *options,char *brl_options){struct console_cmdline *c;int i;for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)//可以最多8个consoleif (strcmp(console_cmdline[i].name, name) == 0 && console_cmdline[i].index == idx) {//比较已注册的console_cmdline数组中的项的名字及次设备号,若console_cmdline已经存在if (!brl_options)selected_console = i;//设置全局selected_console索引号return 0;//则返回}if (i == MAX_CMDLINECONSOLES)//判断console_cmdline数组是否满了return -E2BIG;if (!brl_options)selected_console = i; //设置全局selected_console索引号c = &console_cmdline[i];//获取全局console_cmdline数组的第i项地址strlcpy(c->name, name, sizeof(c->name));//填充全局console_cmdline的驱动名“ttyS2”c->options = options;//填充配置选项115200n8#ifdef CONFIG_A11Y_BRAILLE_CONSOLEc->brl_options = brl_options;#endifc->index = idx;//填充索引号2,即次设备号return 0;}三、在console初始化之前能使用printk,使用内核提供的early printk支持 。//在调用console_init之前调用printk也能打印出信息,这是為什麼呢?在start_kernel函数中很早就调用了 parse_early_param函数,//该函数会调用到链接脚本中.init.setup段的函数 。其中就有 setup_early_serial8250_console函数 。//该函数通过 register_console(&early_serial8250_console);//注册了一个比较简单的串口设备 。可以用来打印内核启 动早期的信息 。//对于early printk的console注册往往通过内核的early_param完成 。early_param(“earlycon”,setup_early_serial8250_console);//定义一个earlycon的内核参数,内核解析这个参数时调用setup_early_serial8250_console()函数1.setup_early_serial8250_console()函数//earlycon = uart8250,mmio,0xff5e0000,115200n8int __init setup_early_serial8250_console(char *cmdline){char *options;int err;options = strstr(cmdline, "uart8250,");//找到“uart8250,”字符串,返回此字符串的起始位置if (!options) {options = strstr(cmdline, "uart,");if (!options)return 0;}options = strchr(cmdline, ',') + 1;//options指针指向第一个逗号后边的字符串地址err = early_serial8250_setup(options);//进行配置if (err