分类: LINUX
2017-06-27 19:43:51
It is a 'magical' key combo you can hit which the kernel will respond to regardless of whatever else it is doing, unless it is completely locked up.
在linux系统下,我们有时候会碰到命令卡(hang)住的问题,这时候无法再输入命令,那么对我们调试问题就会造成影响,幸好linux一种后门机制,可以在命令hang住的时候打印一些内核信息,这个机制就是sysrq
具体描述我们可以查看内核文档
root@99-252:~/linux-3.10.70/Documentation# vi sysrq.txt
step1: enable kernel config
Symbol: MAGIC_SYSRQ [=y]
| Type : boolean
| Prompt: Magic SysRq key
| Location:
| (1) -> Kernel hacking
| Defined at lib/Kconfig.debug:55 | Depends on: !UML | Selected by: KGDB_SERIAL_CONSOLE [=y] && KGDB [=y] && TTY [=y]
step2: make sure sysrq open
确认sysrq是否是非0,非0则代表启用,可以通过快捷键触发进入sysrq,如果sysrq=1,则代表允许任何请求,sysrq等于其他值可以选择性开启部分功能. 不同的cpu平台的快捷键也不一样
/proc/sys/kernel # ls -al -rw-r--r-- 1 root 0 0 Mar 23 14:36 sysrq
/proc/sys/kernel # cat sysrq 1 // sysrq写0则关闭此功能 /proc/sys/kernel # echo "0" > sysrq
method1: 使用终端进入sysrq功能
以arm平台为例,可以在终端(like secureCRT)通过键盘组合键ctrl+pause, 5s内输入命令字符执行相应的sysrq功能.
method2: shell
/ # echo "h" >/proc/sysrq-trigger SysRq : HELP : loglevel(0-9) reboot(b) crash(c) terminate-all-tasks(e) memory-full-oom-kill(f) kill-all-tasks(i) thaw-filesystems(j) sak(k) show-backtrace-all-active-cpus(l) show-memory-usage(m) nice-all-RT-tasks(n) poweroff(o) show-registers(p) show-all-timers(q) unraw(r) sync(s) show-task-states(t) unmount(u) show-blocked-tasks(w) / #
键盘上所有的按键都有扫描码和虚拟码,扫描码由键盘硬件发至设备的键盘驱动,键盘驱动会将扫描码转换成统一的虚拟码,屏蔽掉厂家差异。
ctrl + 字母的ASCII码 = 字母的ASCII码 & 0x1f
linux kernel 如何识别sysrq
// 在串口接收字符处理函数中会调用break处理函数
unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
{
uart_handle_break(port)
uart_handle_sysrq_char(port, ch)
}
// break处理函数的实现,实际上调用了uart_port的break处理
static inline int uart_handle_break(struct uart_port *port)
{
struct uart_state *state = port->state;
if (port->handle_break)
port->handle_break(port);
#ifdef SUPPORT_SYSRQ
if (port->cons && port->cons->index == port->line) {
if (!port->sysrq) {
port->sysrq = jiffies + HZ*5;
return 1;
}
port->sysrq = 0;
}
#endif
if (port->flags & UPF_SAK)
do_SAK(state->port.tty);
return 0;
}
// 处理sysrq的字符,如果超时则不处理
static inline int
uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
{
if (port->sysrq) {
if (ch && time_before(jiffies, port->sysrq)) {
handle_sysrq(ch);
port->sysrq = 0;
return 1;
}
port->sysrq = 0;
}
return 0;
}
// sysrq.c 中处理sysrq命令
static struct sysrq_key_op *sysrq_key_table[36] = {
&sysrq_loglevel_op, /* 0 */
&sysrq_loglevel_op, /* 1 */
&sysrq_loglevel_op, /* 2 */
&sysrq_loglevel_op, /* 3 */
&sysrq_loglevel_op, /* 4 */
&sysrq_loglevel_op, /* 5 */
&sysrq_loglevel_op, /* 6 */
&sysrq_loglevel_op, /* 7 */
&sysrq_loglevel_op, /* 8 */
&sysrq_loglevel_op, /* 9 */
/*
* a: Don't use for system provided sysrqs, it is handled specially on
* sparc and will never arrive.
*/
NULL, /* a */
&sysrq_reboot_op, /* b */
&sysrq_crash_op, /* c & ibm_emac driver debug */
&sysrq_showlocks_op, /* d */
&sysrq_term_op, /* e */
&sysrq_moom_op, /* f */
/* g: May be registered for the kernel debugger */
NULL, /* g */
NULL, /* h - reserved for help */
&sysrq_kill_op, /* i */
#ifdef CONFIG_BLOCK
&sysrq_thaw_op, /* j */
#else
NULL, /* j */
#endif
&sysrq_SAK_op, /* k */
#ifdef CONFIG_SMP
&sysrq_showallcpus_op, /* l */
#else
NULL, /* l */
#endif
&sysrq_showmem_op, /* m */
&sysrq_unrt_op, /* n */
/* o: This will often be registered as 'Off' at init time */
NULL, /* o */
&sysrq_showregs_op, /* p */
&sysrq_show_timers_op, /* q */
&sysrq_unraw_op, /* r */
&sysrq_sync_op, /* s */
&sysrq_showstate_op, /* t */
&sysrq_mountro_op, /* u */
/* v: May be registered for frame buffer console restore */
NULL, /* v */
&sysrq_showstate_blocked_op, /* w */
/* x: May be registered on ppc/powerpc for xmon */
/* x: May be registered on sparc64 for global PMU dump */
NULL, /* x */
/* y: May be registered on sparc64 for global register dump */
NULL, /* y */
&sysrq_ftrace_dump_op, /* z */
};