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,不像 :IMPORTANT
IMPORTANT: c2 兼容系统中的 SAK,也不应该被误认为 :IMPORTANT
IMPORTANT: 这样的 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 <sequence> 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.debug
config MAGIC_SYSRQ
bool "Magic SysRq key"
help
如果您在此处选择 Y,即使系统崩溃(例如在内核调试期间),您仍将拥有对系统的一定控制权(例如,您可以将缓冲区缓存刷新到磁盘,立即重启系统或转储一些状态信息)。这可以通过在按住 SysRq(Alt+PrintScreen)的同时按下各种按键来实现。如果您发送 BREAK 指令,然后在 5 秒内按下一个命令键,它也可以在串行控制台(至少在 PC 硬件上)上工作。这些按键的文档记录在 <file:Documentation/sysrq.txt> 中。除非您真正了解这个 hack 的作用,否则不要选择 Y。
//msm-4.4/drivers/tty/Makefile
obj-$(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
posted on 2018-06-07 00:51 Hello-World3 阅读(2588) 评论(0) 收藏 举报