sysrq魔法键

sysrq魔法键

一、简介

1. 简要介绍

注: 翻译自 /kernel/msm-4.4/Documentation/sysrq.txt

Linux 魔法系统请求键技巧对 sysrq.c 的说明文档

* 什么是 SysRq 魔法键?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~这是一个“神奇”的组合键,您可以按下它,内核会响应,无论它正在执行什么操作,除非它被完全锁定。

* 如何启用 SysRq 魔法键?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~配置内核时,您需要启用“SysRq 魔法键 (CONFIG_MAGIC_SYSRQ)”。运行编译了 SysRq 的内核时,/proc/sys/kernel/sysrq 控制允许通过 SysRq 键调用的功能。此文件中的默认值由CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 配置符号设置,该符号本身默认为 1。以下是 /proc/sys/kernel/sysrq 中可能的值列表: 0 - 完全禁用 sysrq; 1 - 启用 sysrq 的所有功能; >1 - 允许的 sysrq 功能的位掩码(有关详细的函数描述,请参见下文): 2 = 0x2 - 启用控制台日志级别控制 4 = 0x4 - 启用键盘控制(SAK、unraw) 8 = 0x8 - 启用进程调试转储等 16 = 0x10 - 启用同步命令 32 = 0x20 - 启用只读 remount 64 = 0x40 - 启用进程信号(term、kill、oom-kill) 128 = 0x80 - 允许重启/关机 256 = 0x100 - 允许所有 RT 任务的 nicing

您可以使用以下命令在文件中设置该值:

echo "number" >/proc/sys/kernel/sysrq

此处的数字可以是十进制,也可以是十六进制,并以 0x 为前缀。CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 必须始终以十六进制形式写入。

请注意,/proc/sys/kernel/sysrq 的值仅影响通过键盘的调用。始终允通过 /proc/sysrq-trigger 调用任何操作。

* 如何使用神奇的 SysRq 键?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~在 x86 上 - 按下组合键“ALT-SysRq-<命令键>”。注意 - 某些键盘可能没有标有“SysRq”的键。“SysRq”键也称为“Print Screen”键。此外,某些键盘无法处理同时按下这么多键,因此您可能更倾向于“按下 Alt”,“按下 SysRq”,“释放 SysRq”,“按下 <命令键>”,然后释放所有键。

在 SPARC 上 - 我相信您应该按下“ALT-STOP-<命令键>”。

在串行控制台(仅限 PC 风格的标准串行端口)上 - 发送一个 BREAK,然后在 5 秒内发送一个命令键。发送两次 BREAK 将被解释为正常的 BREAK。

在 PowerPC 上 - 按“ALT - Print Screen(或 F13)- <命令键>”,“Print Screen(或 F13)- <命令键>”即可。

在其他架构上 - 如果您知道其他架构的组合键,请告诉我,以便我将其添加到此部分。

在所有架构上 - 向 /proc/sysrq-trigger 写入一个字符。例如:

echo t > /proc/sysrq-trigger

* 什么是“命令”键?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'b' - 立即重启系统,无需同步或卸载磁盘。实测: 生效

'c' - 通过空指针解引用让系统崩溃。如果已配置,则会生成崩溃转储。实测: 生效

'd' - 显示持有的所有锁。实测: 不生效,需要依赖 CONFIG_LOCKDEP 才生效。

'e' - 向所有进程(init 除外)发送 SIGTERM 信号(下面有发 SIGKILL 信号的)。实测: 生效,(Android-P)上层会死掉,然后黑屏。但是Android-Q上只是进程重启,功能还会恢复正常状态。

'f' - 调用 oom kill 程序来终止占用大量内存的进程,但如果没有进程可以终止,也不会panic。实测: 生效,会调到 oom-killer 打印很多内存相关信息。

'g' - 由 kgdb(内核调试器)使用。实测: 不生效,功能没实现。

'h' - 显示帮助(实际上,除此处列出的键之外的任何其他键都可以显示帮助。但 'h' 更容易记住 :-)。实测: 生效,打印如下log,打印出来的就是 sysrq_key_op 结构的 help_msg 指定的信息。

[ 239.446091] (2)[1018:sh]sysrq: 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) show-backtrace-all-active-cpus(l) show-memory-usage(m) nice-all-RT-tasks(n) poweroff(o) show-registers(p) show-all-timers(q) sync(s) show-task-states(t) unmount(u) show-blocked-tasks(w) dump-ftrace-buffer(z)

'i' - 向所有进程(init 除外)发送 SIGKILL 信号(上面有发 SIGTERM 信号的)。实测: 生效,然后(P上)就一直卡静态logo,而且adb也连不上。Q上不会,只是进程重启,然后一切正常。

'j' - 强制“解冻” - 文件系统被 FIFREEZE ioctl 冻结。实测: echo后卡死,adb也不能用,一直在动态logo, 不知道有啥用。

'k' - 安全访问密钥 (SAK) 终止当前虚拟控制台上的所有程序。注意:请参阅下方 SAK 部分中的重要注释。

'l' - 显示所有active CPU 的堆栈回溯。实测: 生效,它会通过IPI中断去打印各个CPU的内核栈。

'm' - 将当前内存信息转储到控制台。实测: 生效,会打印出"Mem-Info:"里面有包含各类内存信息。

'n' - 用于使 RT 任务可进行 nice 操作。实测: 生效,它会跳过所有内核线程(只处理非内核线程),然后将所有任务设置为CFS-120, 它首先将所有CFS线程设置为CFS-120,然后将所有RT线程也设置为CFS-120.

'o' - 将关闭系统(如果已配置并支持)。实测: 不生效,未实现。

'p' - 将当前寄存器和标志转储到控制台。实测: 生效,但是只打印出"sysrq: SysRq : Show Regs".

'q' - 将转储所有已启用 hrtimer(但不包括常规 timer_list 定时器)的每个 CPU 列表以及所有 clockevent 设备的详细信息。实测: 生效,看起来和 cat /proc/timer_list 效果一样。

'r' - 关闭键盘原始模式并将其设置为 XLATE。实测: 不生效,依赖 CONFIG_VT

's' - 将尝试同步所有已挂载的文件系统。实测: 不生效,若成功执行会打印"sysrq: SysRq : Emergency Sync" 和 "Emergency Sync complete"。

't' - 将当前任务及其信息的列表转储到控制台。实测: 生效,有点类似 cat /proc/sched_debug 打印的内容。

'u' - 将尝试以只读方式重新挂载所有已挂载的文件系统。实测: 生效,但是用户感知不到区别。

'v' - 强制恢复帧缓冲区控制台。实测: 不生效,没实现。'v' - 导致 ETM 缓冲区转储 [ARM 专用]。实测: 不生效,没实现。

'w' - 转储处于不可中断(阻塞)D状态的任务。实测: 生效,会打印D状态任务的栈回溯。

'x' - 由 ppc/powerpc 平台上的 xmon 接口使用。在 sparc64 上显示全局 PMU 寄存器。在 MIPS 上转储所有 TLB 条目。

'y' - 显示全局 CPU 寄存器 [SPARC-64 专用]。实测: 不生效,未实现。

'z' - 转储 ftrace 缓冲区。实测: 生效,转储的log多了,它会把系统给搞重启。

'0'-'9' - 设置控制台日志级别,控制哪些内核消息将打印到控制台(例如,'0' 表示只有 PANIC 或 OOPS 等紧急消息才会打印到控制台)。看代码应该是生效的。

* 好的,那么我该用它们做什么呢?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~嗯,当你的 X 服务器或 svgalib 程序崩溃时,unraw(r) 非常方便。

sak(k)(安全访问密钥)在你想要确保控制台上没有运行任何木马程序,以便在你尝试登录时窃取你的密码时非常有用。它会终止指定控制台上的所有程序,从而确保你看到的登录提示符实际上是来自 init 的,而不是某个木马程序。==>实测,echo k后控制台上运行的脚本还在后台运行。重要提示:它的真实形式并非真正的 SAK,不像 :IMPORTANTIMPORTANT: c2 兼容系统中的 SAK,也不应该被误认为 :IMPORTANTIMPORTANT: 这样的 SAK。:IMPORTANT似乎其他人觉得它像(系统注意键)一样有用,当你想退出一个不允许切换控制台的程序时很有用。 (例如,X 或 svgalib 程序。)

无法关机时,reboot(b) 是个不错的选择。但您也应该先执行 sync(s) 和 umount(u)。==>实测: echo b后立即关机了。

crash(c) 可用于在系统挂起时手动触发崩溃转储。请注意,如果没有可用的转储机制,这只会触发崩溃。

sync(s) 在系统锁定时非常有用,它允许您同步磁盘,并肯定会降低数据丢失和文件系统检查的风险。请注意,直到屏幕上出现“OK”和“Done”消息时,同步才会发生。(如果内核真的出现问题,您可能永远都看不到“OK”或“Done”消息……)

umount(u) 的作用基本与 sync(s) 相同。我的系统锁定时,我通常会先 sync(s),然后 umount(u),最后 restart(b)。它帮我省了很多次文件系统检查。同样,卸载(以只读方式重新挂载)直到屏幕上出现“OK”和“Done”消息时才会发生。

当您的控制台充斥着您不想看到的内核消息时,日志级别“0”到“9”会很有用。选择“0”将阻止除最紧急的内核消息之外的所有消息到达您的控制台。(不过,如果 syslogd/klogd 处于活动状态,它们仍会被记录。)

如果您有某个无法通过其他方式终止的失控进程,尤其是当它正在创建其他进程时,term(e) 和 kill(i) 会很有用。

如果您的系统由于通过 FIFREEZE ioctl 冻结了文件系统(可能是根文件系统)而变得无响应,“just thaw it(j)”会很有用。

* 有时使用 SysRq 后似乎会“卡住”,我该怎么办?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~我也遇到过这种情况。我发现,同时按下键盘两侧的 Shift、Alt 和 Control 键,然后再次输入无效的 SysRq 序列,就可以解决问题。(例如,类似 alt-sysrq-z 的组合)。切换到另一个虚拟控制台(ALT+Fn),然后再切换回来,应该也能解决问题。

* 我按下了 SysRq 键,但似乎没有任何反应,这是怎么回事?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~有些键盘的 SysRq 键码与预定义的 99(参见 include/linux/input.h 文件中的 KEY_SYSRQ)不同,或者根本没有 SysRq 键。在这种情况下,请运行“showkey -s”命令来查找合适的扫描码序列,并使用“setkeycodes 99”命令将此序列映射到常用的 SysRq 键码(例如,“setkeycodes e05b 99”)。最好将此命令放在启动脚本中。哦,对了,十秒钟内不输入任何内容即可退出“showkey”。

* 我想将 SysRQ 按键事件添加到模块中,该如何操作?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~为了将基本函数注册到表中,首先必须包含头文件“include/linux/sysrq.h”,该文件定义了您需要的所有其他内容。接下来,您必须创建一个 sysrq_key_op 结构体,并在其中填充以下信息:A) 您将使用的按键处理函数;B) help_msg 字符串(当 SysRQ 打印帮助信息时会打印);C) action_msg 字符串(在您的处理程序被调用之前打印)。您的处理程序必须符合“sysrq.h”中的原型。

创建 sysrq_key_op 后,您可以调用内核函数:

register_sysrq_key(int key, struct sysrq_key_op *op_p);

如果表中的相应槽位为空,则此函数会将“op_p”指向的操作注册到表键“key”中。在模块卸载时,必须调用函数:

unregister_sysrq_key(int key, struct sysrq_key_op *op_p);

该函数会将“op_p”指向的键操作从键“key”中移除,前提是该操作当前已注册到该槽位中。这是因为,如果槽位在您注册后已被覆盖,则需要移除该操作。

Magic SysRQ 系统通过将关键操作注册到关键操作查找表中来工作,该查找表定义在“drivers/char/sysrq.c”中。该关键操作表在编译时注册了许多操作,但这些操作是可变的,并且有两个函数用于与其接口:register_sysrq_key 和 unregister_sysrq_key。当然,切勿在表中留下无效指针。例如,当调用 register_sysrq_key() 的模块退出时,它必须调用 unregister_sysrq_key() 来清理它使用的 sysrq 关键操作表条目。表中的空指针始终是安全的。:)

如果您出于某种原因需要在 handle_sysrq 调用的函数中调用 handle_sysrq 函数,则必须注意您处于锁定状态(您也处于中断处理程序中,这意味着不要休眠!),因此您必须调用 __handle_sysrq_nolock。

* 当我按下 SysRq 组合键时,控制台上是否只显示标题?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Sysrq 输出与所有其他控制台输出一样,受相同的控制台日志级别控制。这意味着,如果内核以“quiet”模式启动(这在发行版内核中很常见),则输出可能不会显示在实际控制台上,即使它会出现在 dmesg 缓冲区中,并且可以通过 dmesg 命令和 /proc/kmsg 的使用者访问。一个特殊的例外是,sysrq 命令的标题行会传递给所有控制台使用者,就好像当前日志级别为最高一样。如果只发出标题,则几乎可以肯定内核日志级别过低。如果您需要在控制台通道上显示输出,则需要使用 alt-sysrq-8 或以下方式临时提高控制台日志级别:

echo 8 > /proc/sysrq-trigger

触发您感兴趣的 sysrq 命令后,请务必将日志级别恢复正常。

* 我还有其他问题,可以咨询谁?~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~只需在 linux-kernel 邮件列表中提问即可:linux-kernel@vger.kernel.org

2. 配置使能

//msm-4.4/lib/Kconfig.debugconfig MAGIC_SYSRQ bool "Magic SysRq key" help 如果您在此处选择 Y,即使系统崩溃(例如在内核调试期间),您仍将拥有对系统的一定控制权(例如,您可以将缓冲区缓存刷新到磁盘,立即重启系统或转储一些状态信息)。这可以通过在按住 SysRq(Alt+PrintScreen)的同时按下各种按键来实现。如果您发送 BREAK 指令,然后在 5 秒内按下一个命令键,它也可以在串行控制台(至少在 PC 硬件上)上工作。这些按键的文档记录在 中。除非您真正了解这个 hack 的作用,否则不要选择 Y。

//msm-4.4/drivers/tty/Makefileobj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o

一般 userdebug/user 版本都默认使能此feature的。

二、sysrq命令定义

1. 静态定义命令

static struct sysrq_key_op *sysrq_key_table[36] = { //sysrq.c

&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 */

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 */

NULL, /* g */

NULL, /* h - reserved for help */

&sysrq_kill_op, /* i */

#ifdef CONFIG_BLOCK

&sysrq_thaw_op, /* j */

#endif

&sysrq_SAK_op, /* k */

#ifdef CONFIG_SMP

&sysrq_showallcpus_op, /* l */

#endif

&sysrq_showmem_op, /* m */

&sysrq_unrt_op, /* n */

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 */

NULL, /* v */

&sysrq_showstate_blocked_op, /* w */

NULL, /* x */

NULL, /* y */

&sysrq_ftrace_dump_op, /* z */

};

2. 动态定义命令

pm_sysrq_init //poweroff.c

register_sysrq_key('o', &sysrq_poweroff_op) //poweroff(o)

drm_fb_helper_single_fb_probe //drm_fb_helper.c

register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op) //force-fb(V), Restore framebuffer console

kgdb_register_callbacks //debug_core.c

register_sysrq_key('g', &sysrq_dbg_op) //debug(g)

三、sysrq数据结构

1. struct sysrq_key_op

struct sysrq_key_op {

void (*handler)(int);

char *help_msg;

char *action_msg;

int enable_mask;

};

此结构用于定义一个 sysrq 魔法键回调。

handler: 功能回调函数。

help_msg: 当 SysRQ 打印帮助信息时会打印。

action_msg: 在处理回调函数被调用之前打印。

enable_mask: sysrq的功能位掩码,比如 SYSRQ_ENABLE_RTNICE。应该是通过它将众多 sysrq 命令归为几类,通过 /proc/sys/kernel/sysrq 来选择只开启某些类。

四、sysrq调试接口

1. /proc/sysrq-trigger

通过此节点使用sysrq命令,比如通过 echo b 触发重启。

2. /proc/sys/kernel/sysrq

这里面配置只允许通过键盘使用的命令掩码。但不影响通过 /proc/sysrq-trigger 的使用,因为始终允许通过它调用所有掩码对应的命令。

参考:http://www.baidu.com/link?url=dDrEfDXtmLeBMPLtR-UF-ZGNhHwGkz0RRaOZkdqa9jBqVryPkHHv7quJqFBvJqeeEXZPQPvKCf8nDMOd-8mUjq&wd=&eqid=e5790bd10001a856000000065b17fe30

相关推荐