linux内核调试之魔术键sysrq

发布时间:2024年01月12日

linux内核调试之魔术键sysrq

1 sysrq简介

sysrq是内核提供的一组魔数组合键,通过该组合键可以直接触发内核的特定功能,如重启系统,设置loglevel等。它是一个你可以输入的具有魔法般的组合键。 无论内核在做什么,内核都会响应 SysRq 键的输入,除非内核完全卡死。在内核发生故障时,只要键盘还有响应就可以使用它们触发相应操作。

除了通过键盘触发以外,内核还支持通过proc文件系统触发sysrq操作。该方式为每种操作定义了一个唯一的字符,当需要触发操作时,只需将对应的字符写到/proc/sysrq-trigger文件即可。如以下命令可用于重启系统:

echo b > /proc/sysrq-trigger

在嵌入式系统中一般不含有键盘,因此后面我们的介绍将以proc方式为主

2 sysrq实现

2.1 内核配置

若要使能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 的任何操作调用都是允许的 (通过具有系统权限的用户)。

2.2 sysrq初始化流程

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命令,并根据解析值执行相应的处理函数。

3 sysrq支持的常用命令

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

3.1 命令介绍

echo > /proc/sysrq-trigger

OOM的内存状态信息 与该命令类似结果

echo m > /proc/sysrq-trigger

将当前内存信息 dump 到终端

3.2 sysrq支持的常用命令

(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


文章来源:https://blog.csdn.net/xushx_bigbear/article/details/135544400
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。