Linux Magic System Request Key Hacks¶
sysrq.c 文档
什么是 magic SysRq 键?¶
这是一个“神奇”的组合键,你可以按下它,内核会对它做出响应,而不管它正在做什么,除非它完全锁死了。
如何启用 magic SysRq 键?¶
在配置内核时,你需要对 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' 说“yes”。当运行一个编译了 SysRq 的内核时,/proc/sys/kernel/sysrq 控制着允许通过 SysRq 键调用的功能。该文件中的默认值由 CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 配置符号设置,该符号本身默认为 1。以下是 /proc/sys/kernel/sysrq 中可能的值:
0 - 完全禁用 sysrq
1 - 启用 sysrq 的所有功能
>1 - 允许的 sysrq 功能的位掩码(有关详细的功能说明,请参见下文)
2 = 0x2 - enable control of console logging level 4 = 0x4 - enable control of keyboard (SAK, unraw) 8 = 0x8 - enable debugging dumps of processes etc. 16 = 0x10 - enable sync command 32 = 0x20 - enable remount read-only 64 = 0x40 - enable signalling of processes (term, kill, oom-kill) 128 = 0x80 - allow reboot/poweroff 256 = 0x100 - allow nicing of all RT tasks
你可以使用以下命令设置文件中的值
echo "number" >/proc/sys/kernel/sysrq
该数字可以以十进制或带有 0x 前缀的十六进制形式写入。CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 必须始终以十六进制形式写入。
请注意,/proc/sys/kernel/sysrq
的值仅影响通过键盘的调用。始终允许通过 /proc/sysrq-trigger
调用任何操作(由具有管理员权限的用户)。
如何使用 magic 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
或者,写入以 underscore 开头的多个字符。这样,所有字符都将被处理。例如:
echo _reisub > /proc/sysrq-trigger
<命令键> 区分大小写。
什么是“命令”键?¶
命令 |
功能 |
---|---|
|
将立即重启系统,而无需同步或卸载你的磁盘。 |
|
将执行系统崩溃,如果已配置,则会进行崩溃转储。 |
|
显示所有持有的锁。 |
|
向所有进程发送 SIGTERM,除了 init。 |
|
将调用 oom killer 来杀死一个内存占用进程,但如果无法杀死任何东西,则不要 panic。 |
|
由 kgdb(内核调试器)使用 |
|
将显示帮助(实际上,除了此处列出的键之外的任何其他键都将显示帮助。但 |
|
向所有进程发送 SIGKILL,除了 init。 |
|
强制 “Just thaw it” - 通过 FIFREEZE ioctl 冻结的文件系统。 |
|
安全访问键 (SAK) 杀死当前虚拟控制台上的所有程序。注意:请参阅下面 SAK 部分中的重要评论。 |
|
显示所有活动 CPU 的堆栈回溯。 |
|
将当前内存信息转储到你的控制台。 |
|
用于使 RT 任务可以 nice |
|
将关闭你的系统(如果已配置并支持)。 |
|
将当前寄存器和标志转储到你的控制台。 |
|
将转储每个 CPU 的所有已激活的 hrtimer 列表(但不是常规的 timer_list 定时器)以及有关所有 clockevent 设备的详细信息。 |
|
关闭键盘原始模式,并将其设置为 XLATE。 |
|
将尝试同步所有已挂载的文件系统。 |
|
将当前任务列表及其信息转储到你的控制台。 |
|
将尝试以只读方式重新挂载所有已挂载的文件系统。 |
|
强制恢复帧缓冲控制台 |
|
导致 ETM 缓冲区转储 [ARM 特定] |
|
转储处于不可中断(阻塞)状态的任务。 |
|
由 ppc/powerpc 平台上的 xmon 接口使用。在 sparc64 上显示全局 PMU 寄存器。在 MIPS 上转储所有 TLB 条目。 |
|
显示全局 CPU 寄存器 [SPARC-64 特定] |
|
转储 ftrace 缓冲区 |
|
设置控制台日志级别,控制哪些内核消息将打印到你的控制台。(例如, |
|
在控制台上重放内核日志消息。 |
好的,那么我可以用它们做什么?¶
当你的 X 服务器或 svgalib 程序崩溃时,unraw(r) 非常方便。
当你想要确保在控制台上没有木马程序运行时,sak(k)(安全访问键)非常有用,该木马程序可能会在你尝试登录时获取你的密码。它将杀死给定控制台上的所有程序,从而让你确保你看到的登录提示实际上是来自 init 的,而不是某些木马程序。
重要提示
以其真实形式,它不是真正的 SAK,就像 c2 兼容系统中的那样,并且不应将其误认为如此。
似乎其他人发现它作为(系统注意键)很有用,当你想要退出一个不允许你切换控制台的程序时,它很有用。(例如,X 或 svgalib 程序。)
当你无法关闭时,reboot(b)
很好,它相当于按下“reset”按钮。
当系统挂起时,crash(c)
可用于手动触发崩溃转储。请注意,如果没有任何可用的转储机制,这只会触发崩溃。
sync(s)
在拔出可移动介质之前或在使用不提供正常关机的救援 shell 之后很方便 - 它将确保你的数据安全地写入磁盘。请注意,直到你在屏幕上看到 “OK” 和 “Done” 出现,同步才完成。
umount(u)
可用于将文件系统标记为已正确卸载。从运行系统的角度来看,它们将以只读方式重新挂载。直到你在屏幕上看到 “OK” 和 “Done” 消息出现,重新挂载才完成。
当你的控制台被你不希望看到的内核消息淹没时,日志级别 0
-9
很有用。选择 0
将阻止除最紧急的内核消息之外的所有消息到达你的控制台。(如果 syslogd/klogd 处于活动状态,它们仍然会被记录。)
如果你有一些你无法以任何其他方式杀死的失控进程,特别是如果它正在生成其他进程,则 term(e)
和 kill(i)
很有用。
如果你的系统由于通过 FIFREEZE ioctl 冻结(可能是根)文件系统而变得无响应,“just thaw it(j)
” 很有用。
当系统挂起或者你无法使用 dmesg 命令查看 printk 缓冲区中的消息时,Replay logs(R)
可用于查看内核日志消息。如果控制台系统繁忙,用户可能需要多次按下组合键。如果它完全锁死,则不会打印消息。输出消息取决于当前的控制台日志级别,可以使用 sysrq[0-9] 修改(参见上文)。
有时在使用 SysRq 后它似乎会“卡住”,我该怎么办?¶
发生这种情况时,尝试在键盘的两侧轻敲 shift、alt 和 control,然后再次按下无效的 sysrq 序列。(即,类似于 alt-sysrq-z)。
切换到另一个虚拟控制台 (ALT+Fn) 然后再切换回来也应该有所帮助。
我按下了 SysRq,但似乎没有任何反应,怎么回事?¶
有些键盘为 SysRq 生成的键码与预定义的值 99 不同(请参阅 include/uapi/linux/input-event-codes.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, const struct sysrq_key_op *op_p);
,如果表键“key”中的该槽位为空白,这将注册由 op_p
指向的操作。在模块卸载时,你必须调用函数 unregister_sysrq_key(int key, const struct sysrq_key_op *op_p)
,这将从键“key”中删除由 “op_p” 指向的键操作,仅当它当前已在该槽位中注册时。这是为了防止自你注册以来该槽位已被覆盖。
Magic SysRQ 系统通过针对键操作查找表注册键操作来工作,该表在 “drivers/tty/sysrq.c” 中定义。此键表在编译时已注册了许多操作,但它是可变的,并且导出了 2 个函数用于与其交互。
register_sysrq_key and 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 邮件列表中提问
致谢¶
由 Mydraal <vulpyne@vulpyne.net> 编写
由 Adam Sulmicki <adam@cfar.umd.edu> 更新
由 Jeremy M. Dolan <jmd@turbogeek.org> 于 2001/01/28 10:15:59 添加
由 Crutcher Dunnavant <crutcher+kernel@datastacks.com> 添加到