1. dmesg 读取kernel 的log, system/core/toolbox/dmesg.c 文件中dmesg_main函数-->klogctl, 可以看到只支持dmesg -c,并且用dmesg显示kernel log不能连续显示(可从代码中看出来),用cat proc/kmsg 则可以连续显示kernel log.
2. klogctl函数的定义在那? bionic/libc/arch-arm/syscalls/klogctl.s, 从user space读取kernel space的log,需要进一步分析如何实现的????? klogctl是实现kernel log能输出到user space(logcat, dmesg)的关键。
3. logcat 能输出kernel log的机制, vendor/semc/system/utility/klogrouter/src/klogrouter.c 中有函数main-->klog_to_logcat-->klogctl
4. 在手机的init.st-ericsson.rc中有
on property:persist.kernel.log=logcat
stop klogrouterd
start klogrouterd
on property:persist.kernel.log=uart
stop klogrouterd
exec /system/bin/klogrouter uart
on property:persist.kernel.log=default
stop klogrouterd
exec /system/bin/klogrouter default
service klogrouterd /system/bin/klogrouter logcat
最开始执行的是带参数 logcat, 其中的stop/start/exec 你也可以单独在adb shell中执行
可以在adb shell中用setprop persist.kernel.log xxxx 做控制log的操作,实际上是控制klogrouter.c-->main-->会写/proc/console_control
setprop persist.kernel.log uart (enables UART logging)
setprop persist.kernel.log default (disables UART logging)
setprop persist.kernel.log logcat (redirects kernel logs to logcat)
5. kernel/arch/arm/kernel/console_control.c 会创建/proc/console_control, 函数console_control_write会设置console_drivers控制台con->flag是否CON_ENABLED,也就是是否可输出log
6. kernel/kernel/printk.c, 控制台信息输出路径release_console_sem-->call_console_drivers-->_call_console_drivers-->_call_console_drivers-->__call_console_drivers-->con->write(con, &LOG_BUF(start), end - start);
7. ????很重要semc_lotus_defconfig中有CONFIG_CMDLINE= ...rootwait console=ttyAMA2,115200n8 mem=96M@0 ...,才能有uart串口输出,如果还没有uart输出,则需要执行
adb shell chmod 6755 /system/bin/klogger
adb shell setprop persist.kernel.log uart
adb shell klogger &
UART串口注册的设备位于 sys/devices/uart2/tty/ttyAMA2,[console=ttyAMA2,115200n8]表示可以用ttyAMA2这个控制台,并且设置的参数为115200n8,这样就可以与实际的uart串口相关联, 但是实际这个uart串口设备在那注册的呢???? 在kernel/drivers/serial/serial_core.c中有函数uart_register_driver-->tty_register_driver
8. 注册的设备为sys/devices/platform/ram_console,注册名称为ram_console,是啥????? 串口输出的uart设备是ttyAMA2, 这儿有三个uart设备
ttyAMA0: 位于sys/devices/uart0/tty/ttyAMA0, 但是没有enable
ttyAMA1: 位于sys/devices/uart1/tty/ttyAMA1, 但是没有enable
ttyAMA2: 位于sys/devices/uart2/tty/ttyAMA2; 这才是手机串口输出log的uart接口
9. 函数setup_arch-->继续调用文件(kernel/init/main.c中)函数parse_early_param-->parse_early_options-->(kernel/hernel/params.c)parse_args-->parse_one-->do_early_param 但是没有执行,因为没有用early_param添加到__setup_start到__setup_end段中, ealy_param和__setup两宏都会把函数对应关系添加到init.setup段中,但是用ealy_param添加时early=1,表示需要提前执行
10. /kernel/kernel/printk.c中有__setup("console=", console_setup);且console_setup 的参数是“ttyAMA2,115200n8“,该函数会初始化 uart串口输出的console;
11. /kernel/init/main.c中函数main->parse_args("Booting kernel",...)-->unknown_bootoption-->obsolete_checksetup,需要特别注意的是在函数unknown_bootoption中会对参数param做“=”的处理,最终param会变成"XXX=";这就与/kerne/kernel/printk.c中的__setup("console=", console_setup);对应上了,也就是console=ttyAMA2,115200n8,表示需要在init.setup段中,查找param为"console="对应的函数,恰好就是console_setup(“ttyAMA2,115200n8“),-->__add_preferred_console-->会往全局变量console_cmdline[MAX_CMDLINECONSOLES]添加值,
12. 以后继续分析/kernel/kernel/printk.c中console_setup-->__add_preferred_console 中会赋值selected_console=i,对全局变量static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];中对应的结构赋值;另外函数register_console(struct console *newcon)会注册该串口设备,实际上也就是与console_cmdline相关联起来。
13. 串口设备的驱动在那(才会调用register_console注册sys/devices/uart2/tty/ttyAMA2)???目前发现是在kernel/drivers/serial/serial_core.c中有函数uart_register_driver-->tty_register_driver;
14. Uart串口设备属于Serial drivers,硬件驱动位于kernel/drivers/serial/amba-pl011.c, 函数pl011_init-->uart_register_driver(&amba_reg);和amba_driver_register(&pl011_driver);
15. 然后会调用register_console(谁调用的????)kernel/drivers/serial/amba-pl011.c,函数amba_driver_register-->pl011_probe-->uart_add_one_port-->uart_configure_port-->register_console; 其中 uart_add_one_port(&amba_reg, &uap->port);中的amba_reg.cons = &amba_console; amba_reg.cons.setup = pl011_console_setup, 注意在register_console(struct console *newcon)中newcon->index=-1 or 2,但是amba-pl011.c中的pl011_console_setup 里amba_ports并没有对应的数据,所以pl011_console_setup在前两次会失败,第三次会成功(因为pl011_probe 会执行3次???,其中会对amba_ports添加三次值,所以newcon->index=2,就有对应的amba_ports[2]数据)
16. 最初由kernel/drivers/serial/amba-pl011.c中变量amba_console.index = -1;-->可以推出 ttyAMA第一次调用 register_console(struct console *newcon)中newcon->index=-1; 在register_console函数中,amba_console.index 会被赋值为2,这是根据console_cmdline给于的,因为console_cmdline[]中有一个的name也是ttyAMA. 这样两者就关联起来了;
17. 根据以上分析,尝试把CONFIG_CMDLINE= ...console=ttyAMA0[或3],115200n8 ... 会有啥结果呢????没有串口log输出;原因待查????
18. 手机上注册的sys/devices/uart0[1,2]/tty/ttyAMA0[1,2]/dev,其主设备号都是204,子设备号为64[65,66].
19. 在手机上能查看,cat proc/tty/drivers-->ttyAMA /dev/ttyAMA 204 64-77 serial
20. sys/bus/amba/drivers/uart-pl011,实际的driver 注册在这里 kernel/drivers/serial/amba-pl011.c-->amba_driver_register(&pl011_driver);
21. 实际上串口log输出的uart driver 一定会注册,在semc_lotus_defconfig中有CONFIG_CMDLINE= ...console=ttyAMA2,115200n8 ...,只是设置了该uart port的相关参数,同时把console_cmdline console_cmdline[MAX_CMDLINECONSOLES]其中一个值与实际的uart driver相关联起来。
2. klogctl函数的定义在那? bionic/libc/arch-arm/syscalls/klogctl.s, 从user space读取kernel space的log,需要进一步分析如何实现的????? klogctl是实现kernel log能输出到user space(logcat, dmesg)的关键。
3. logcat 能输出kernel log的机制, vendor/semc/system/utility/klogrouter/src/klogrouter.c 中有函数main-->klog_to_logcat-->klogctl
4. 在手机的init.st-ericsson.rc中有
on property:persist.kernel.log=logcat
stop klogrouterd
start klogrouterd
on property:persist.kernel.log=uart
stop klogrouterd
exec /system/bin/klogrouter uart
on property:persist.kernel.log=default
stop klogrouterd
exec /system/bin/klogrouter default
service klogrouterd /system/bin/klogrouter logcat
最开始执行的是带参数 logcat, 其中的stop/start/exec 你也可以单独在adb shell中执行
可以在adb shell中用setprop persist.kernel.log xxxx 做控制log的操作,实际上是控制klogrouter.c-->main-->会写/proc/console_control
setprop persist.kernel.log uart (enables UART logging)
setprop persist.kernel.log default (disables UART logging)
setprop persist.kernel.log logcat (redirects kernel logs to logcat)
5. kernel/arch/arm/kernel/console_control.c 会创建/proc/console_control, 函数console_control_write会设置console_drivers控制台con->flag是否CON_ENABLED,也就是是否可输出log
6. kernel/kernel/printk.c, 控制台信息输出路径release_console_sem-->call_console_drivers-->_call_console_drivers-->_call_console_drivers-->__call_console_drivers-->con->write(con, &LOG_BUF(start), end - start);
7. ????很重要semc_lotus_defconfig中有CONFIG_CMDLINE= ...rootwait console=ttyAMA2,115200n8 mem=96M@0 ...,才能有uart串口输出,如果还没有uart输出,则需要执行
adb shell chmod 6755 /system/bin/klogger
adb shell setprop persist.kernel.log uart
adb shell klogger &
UART串口注册的设备位于 sys/devices/uart2/tty/ttyAMA2,[console=ttyAMA2,115200n8]表示可以用ttyAMA2这个控制台,并且设置的参数为115200n8,这样就可以与实际的uart串口相关联, 但是实际这个uart串口设备在那注册的呢???? 在kernel/drivers/serial/serial_core.c中有函数uart_register_driver-->tty_register_driver
8. 注册的设备为sys/devices/platform/ram_console,注册名称为ram_console,是啥????? 串口输出的uart设备是ttyAMA2, 这儿有三个uart设备
ttyAMA0: 位于sys/devices/uart0/tty/ttyAMA0, 但是没有enable
ttyAMA1: 位于sys/devices/uart1/tty/ttyAMA1, 但是没有enable
ttyAMA2: 位于sys/devices/uart2/tty/ttyAMA2; 这才是手机串口输出log的uart接口
9. 函数setup_arch-->继续调用文件(kernel/init/main.c中)函数parse_early_param-->parse_early_options-->(kernel/hernel/params.c)parse_args-->parse_one-->do_early_param 但是没有执行,因为没有用early_param添加到__setup_start到__setup_end段中, ealy_param和__setup两宏都会把函数对应关系添加到init.setup段中,但是用ealy_param添加时early=1,表示需要提前执行
10. /kernel/kernel/printk.c中有__setup("console=", console_setup);且console_setup 的参数是“ttyAMA2,115200n8“,该函数会初始化 uart串口输出的console;
11. /kernel/init/main.c中函数main->parse_args("Booting kernel",...)-->unknown_bootoption-->obsolete_checksetup,需要特别注意的是在函数unknown_bootoption中会对参数param做“=”的处理,最终param会变成"XXX=";这就与/kerne/kernel/printk.c中的__setup("console=", console_setup);对应上了,也就是console=ttyAMA2,115200n8,表示需要在init.setup段中,查找param为"console="对应的函数,恰好就是console_setup(“ttyAMA2,115200n8“),-->__add_preferred_console-->会往全局变量console_cmdline[MAX_CMDLINECONSOLES]添加值,
12. 以后继续分析/kernel/kernel/printk.c中console_setup-->__add_preferred_console 中会赋值selected_console=i,对全局变量static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];中对应的结构赋值;另外函数register_console(struct console *newcon)会注册该串口设备,实际上也就是与console_cmdline相关联起来。
13. 串口设备的驱动在那(才会调用register_console注册sys/devices/uart2/tty/ttyAMA2)???目前发现是在kernel/drivers/serial/serial_core.c中有函数uart_register_driver-->tty_register_driver;
14. Uart串口设备属于Serial drivers,硬件驱动位于kernel/drivers/serial/amba-pl011.c, 函数pl011_init-->uart_register_driver(&amba_reg);和amba_driver_register(&pl011_driver);
15. 然后会调用register_console(谁调用的????)kernel/drivers/serial/amba-pl011.c,函数amba_driver_register-->pl011_probe-->uart_add_one_port-->uart_configure_port-->register_console; 其中 uart_add_one_port(&amba_reg, &uap->port);中的amba_reg.cons = &amba_console; amba_reg.cons.setup = pl011_console_setup, 注意在register_console(struct console *newcon)中newcon->index=-1 or 2,但是amba-pl011.c中的pl011_console_setup 里amba_ports并没有对应的数据,所以pl011_console_setup在前两次会失败,第三次会成功(因为pl011_probe 会执行3次???,其中会对amba_ports添加三次值,所以newcon->index=2,就有对应的amba_ports[2]数据)
16. 最初由kernel/drivers/serial/amba-pl011.c中变量amba_console.index = -1;-->可以推出 ttyAMA第一次调用 register_console(struct console *newcon)中newcon->index=-1; 在register_console函数中,amba_console.index 会被赋值为2,这是根据console_cmdline给于的,因为console_cmdline[]中有一个的name也是ttyAMA. 这样两者就关联起来了;
17. 根据以上分析,尝试把CONFIG_CMDLINE= ...console=ttyAMA0[或3],115200n8 ... 会有啥结果呢????没有串口log输出;原因待查????
18. 手机上注册的sys/devices/uart0[1,2]/tty/ttyAMA0[1,2]/dev,其主设备号都是204,子设备号为64[65,66].
19. 在手机上能查看,cat proc/tty/drivers-->ttyAMA /dev/ttyAMA 204 64-77 serial
20. sys/bus/amba/drivers/uart-pl011,实际的driver 注册在这里 kernel/drivers/serial/amba-pl011.c-->amba_driver_register(&pl011_driver);
21. 实际上串口log输出的uart driver 一定会注册,在semc_lotus_defconfig中有CONFIG_CMDLINE= ...console=ttyAMA2,115200n8 ...,只是设置了该uart port的相关参数,同时把console_cmdline console_cmdline[MAX_CMDLINECONSOLES]其中一个值与实际的uart driver相关联起来。