Linux 魔术系统请求键技巧

sysrq.c 的文档

什么是魔术 SysRq 键?

这是一个“神奇的”按键组合,您可以按下它,内核将响应它,而不管它在做什么,除非它完全被锁死。

如何启用魔术 SysRq 键?

在配置内核时,您需要对 '魔术 SysRq 键 (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 调用任何操作始终是被允许的(由具有管理员权限的用户)。

如何使用魔术 SysRq 键?

在 x86 上

您按下组合键 ALT-SysRq-<command key>

注意

某些键盘可能没有标记为“SysRq”的键。“SysRq” 键也称为 “Print Screen” 键。此外,某些键盘无法同时处理按下太多键,因此您可能最好按下 Alt,按下 SysRq,释放 SysRq,按下 <command key>,释放所有按键。

在 SPARC 上

我相信,您按下 ALT-STOP-<command key>

在串行控制台上(仅限 PC 风格的标准串行端口)

您发送一个 BREAK,然后在 5 秒内发送一个命令键。发送两次 BREAK 将被解释为正常的 BREAK。

在 PowerPC 上

按下 ALT - Print Screen (或 F13) - <command key>Print Screen (或 F13) - <command key> 可能就足够了。

在其他架构上

如果您知道其他架构的按键组合,请提交补丁以包含在本节中。

在所有架构上

向 /proc/sysrq-trigger 写入单个字符。仅处理第一个字符,字符串的其余部分将被忽略。但是,不建议写入任何额外的字符,因为行为是未定义的,并且可能会在未来的版本中更改。例如

echo t > /proc/sysrq-trigger

或者,写入以 underscore 开头的多个字符。这样,将处理所有字符。例如

echo _reisub > /proc/sysrq-trigger

<command key> 区分大小写。

什么是 “命令” 键?

命令

功能

b

将立即重启系统,而无需同步或卸载磁盘。

c

将执行系统崩溃,如果配置了,将进行崩溃转储。

d

显示所有持有的锁。

e

向除 init 之外的所有进程发送 SIGTERM。

f

将调用 OOM 杀手来杀死内存占用过多的进程,但如果无法杀死任何进程,则不要恐慌。

g

由 kgdb(内核调试器)使用

h

将显示帮助(实际上,除了此处列出的那些键之外的任何其他键都将显示帮助,但 h 很容易记住 :-))

i

向除 init 之外的所有进程发送 SIGKILL。

j

强制 “解冻” - 由 FIFREEZE ioctl 冻结的文件系统。

k

安全访问键 (SAK) 杀死当前虚拟控制台上的所有程序。注意:请参阅下面 SAK 部分中的重要评论。

l

显示所有活动 CPU 的堆栈回溯。

m

将当前内存信息转储到您的控制台。

n

用于使 RT 任务可被 nice

o

将关闭您的系统(如果已配置并支持)。

p

将当前寄存器和标志转储到您的控制台。

q

将转储每个 CPU 的所有已激活 hrtimer 的列表(但不是常规的 timer_list 定时器)以及有关所有 clockevent 设备的详细信息。

r

关闭键盘原始模式并将其设置为 XLATE。

s

将尝试同步所有已挂载的文件系统。

t

将当前任务列表及其信息转储到您的控制台。

u

将尝试以只读方式重新挂载所有已挂载的文件系统。

v

强制恢复帧缓冲控制台

v

导致 ETM 缓冲区转储 [特定于 ARM]

w

转储处于不可中断(阻塞)状态的任务。

x

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

y

显示全局 CPU 寄存器 [特定于 SPARC-64]

z

转储 ftrace 缓冲区

0-9

设置控制台日志级别,控制哪些内核消息会打印到您的控制台。(例如,0 将使其仅有紧急消息(如 PANIC 或 OOPS)才会显示在您的控制台上。)

R

在控制台上重播内核日志消息。

好的,那么我可以用它们做什么?

当您的 X 服务器或 svgalib 程序崩溃时,unraw(r) 非常方便。

当您想确保控制台上没有特洛伊木马程序在运行时,sak(k) (安全访问密钥) 非常有用,该程序可能会在您尝试登录时抓取您的密码。它将杀死给定控制台上的所有程序,从而让您确保您看到的登录提示确实来自 init,而不是某些特洛伊木马程序。

重要提示

在其真实形式中,它不是像 c2 合规系统中的真正的 SAK,不应将其误认为如此。

似乎其他人也认为它可以用作(系统注意键),当您想退出一个不允许您切换控制台的程序时非常有用。(例如,X 或 svgalib 程序。)

当您无法关机时,reboot(b) 很有用,它相当于按下“重置”按钮。

当系统挂起时,可以使用 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)” 非常有用。

Replay logs(R) 在系统挂起或您无法使用 dmesg 命令查看 printk 缓冲区中的消息时非常有用。如果控制台系统繁忙,用户可能需要多次按下组合键。如果它完全被锁定,则不会打印消息。输出消息取决于当前的控制台日志级别,可以使用 sysrq[0-9] 修改(见上文)。

有时,在使用 SysRq 后,它似乎会“卡住”,我该怎么办?

发生这种情况时,请尝试点击键盘两侧的 Shift、Alt 和 Ctrl 键,并再次输入无效的 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),如果 'op_p' 指向的键操作当前已在该槽中注册,则该函数将从键 'key' 中删除它。这是为了防止该槽自您注册以来被覆盖。

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 输出与所有其他控制台输出一样,都受制于相同的控制台日志级别控制。这意味着,如果内核像发行版内核上常见的那样以“安静”模式启动,则输出可能不会出现在实际控制台上,即使它会出现在 dmesg 缓冲区中,并且可以通过 dmesg 命令以及 /proc/kmsg 的使用者访问。作为一种特殊的例外,来自 sysrq 命令的标题行将传递给所有控制台使用者,就好像当前日志级别是最大的一样。如果仅发出标题,则几乎可以肯定内核日志级别太低。如果您需要在控制台通道上输出,那么您需要使用 alt-sysrq-8 临时提高控制台日志级别,或者

echo 8 > /proc/sysrq-trigger

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

我还有其他问题,我该问谁?

只需在 linux-kernel 邮件列表上提问即可

linux-kernel@vger.kernel.org

鸣谢