sysrq是内核提供的一组魔数组合键,通过该组合键可以直接触发内核的特定功能,如重启系统,设置loglevel等。它是一个你可以输入的具有魔法般的组合键。 无论内核在做什么,内核都会响应 SysRq 键的输入,除非内核完全卡死。在内核发生故障时,只要键盘还有响应就可以使用它们触发相应操作。
除了通过键盘触发以外,内核还支持通过proc文件系统触发sysrq操作。该方式为每种操作定义了一个唯一的字符,当需要触发操作时,只需将对应的字符写到/proc/sysrq-trigger文件即可。如以下命令可用于重启系统:
echo b > /proc/sysrq-trigger
在嵌入式系统中一般不含有键盘,因此后面我们的介绍将以proc方式为主
若要使能sysrq功能,需要设置内核的如下配置选项:
CONFIG_MAGIC_SYSRQ=y
在配置内核时,我们需要设置 ‘Magic SysRq key (CONFIG_MAGIC_SYSRQ)’ 为 ‘Y’。 当运行一个编译进 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 - 使能重新挂载只读 64 = 0x40 - 使能对进程的信号操作 (term, kill, oom-kill) 128 = 0x80 - 允许重启、断电 256 = 0x100 - 允许让所有实时任务变普通任务
你可以通过如下命令把值设置到这个文件中:
echo "number" >/proc/sys/kernel/sysrq
这里被写入的 number 可以是 10 进制数,或者是带着 0x 前缀的 16 进制数。 CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 必须是以 16 进制数写入。
注意,/proc/sys/kernel/sysrq
的值只影响通过键盘触发 SySRq 的调用,对于 通过 /proc/sysrq-trigger
的任何操作调用都是允许的 (通过具有系统权限的用户)。
sysrq初始化的主要工作包括为其创建proc文件,以支持proc方式触发sysrq命令。以及将其注册到input子系统中,以支持通过按键方式触发sysrq命令。其相应的流程如下:
其中procfs支持的操作函数如下:
static const struct proc_ops sysrq_trigger_proc_ops = {
.proc_write= write_sysrq_trigger,
.proc_lseek= noop_llseek,
}
在该ops操作函数中,write_sysrq_trigger用于解析用户输入的proc命令,并根据解析值执行相应的处理函数。
/kernel/drivers/tty/sysrq.c
static const struct sysrq_key_op *sysrq_key_table[62] = {
&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 */
&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 mips for TLB dump */
/* 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 */
NULL, /* A */
NULL, /* B */
NULL, /* C */
NULL, /* D */
NULL, /* E */
NULL, /* F */
NULL, /* G */
NULL, /* H */
NULL, /* I */
NULL, /* J */
NULL, /* K */
NULL, /* L */
NULL, /* M */
NULL, /* N */
NULL, /* O */
NULL, /* P */
NULL, /* Q */
NULL, /* R */
NULL, /* S */
NULL, /* T */
NULL, /* U */
NULL, /* V */
NULL, /* W */
NULL, /* X */
NULL, /* Y */
NULL, /* Z */
}
echo > /proc/sysrq-trigger
OOM的内存状态信息 与该命令类似结果
echo m > /proc/sysrq-trigger
将当前内存信息 dump 到终端
(1)0 – 9:用于设置控制台的loglevel,其中数字的值表示将要设置的loglevel等级
(2)b:重启系统
(3)c:手动触发panic
(4)d:显示所有进程持有的锁,该命令需要支持lockdep才有效
(5)e:结束所有用户进程
(6)f:手动触发oom流程
(7)i:杀死所有用户线程
(8)j:冻结所有文件系统
(9)l:显示所有cpu的调用栈
(10)m:显示系统的内存信息
(11)n:将所有用户实时进程修改为普通进程
(12)p:若cpu处于中断状态,则显示当前cpu的寄存器
(13)q:显示所有的timer
(14)s:执行文件系统的同步操作(sync)
(15)t:显示所有进程的执行状态,如其执行状态、pid、ppi以及调用栈等
(16)u:对所有文件系统执行remount操作
(17)w:显示所有当前为TASK_UNINTERRUPTIBLE进程的执行状态
(18)z:dump所有ftrace的buffer
状态,则显示当前cpu的寄存器
(13)q:显示所有的timer
(14)s:执行文件系统的同步操作(sync)
(15)t:显示所有进程的执行状态,如其执行状态、pid、ppi以及调用栈等
(16)u:对所有文件系统执行remount操作
(17)w:显示所有当前为TASK_UNINTERRUPTIBLE进程的执行状态
(18)z:dump所有ftrace的buffer