Chinaunix首页 | 论坛 | 博客
  • 博客访问: 44569
  • 博文数量: 11
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 90
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-08 18:03
文章分类

全部博文(11)

文章存档

2017年(8)

2016年(3)

我的朋友
最近访客

分类: LINUX

2017-06-27 19:43:51

linux && sysrq

what is sysrq

It is a 'magical' key combo you can hit which the kernel will respond to regardless of whatever else it is doing, unless it is completely locked up.

在linux系统下,我们有时候会碰到命令卡(hang)住的问题,这时候无法再输入命令,那么对我们调试问题就会造成影响,幸好linux一种后门机制,可以在命令hang住的时候打印一些内核信息,这个机制就是sysrq

具体描述我们可以查看内核文档

root@99-252:~/linux-3.10.70/Documentation# vi sysrq.txt

func of sysrq

  • b 在没有同步或卸载硬盘的情况下立即启动
  • c 为了获取崩溃转储执行kexe重启动
  • d 显示被持的所有锁
  • e 发送信号SIGTERM给所有进程,除了init外
  • f 将调用oom_kill杀死内存热进程
  • g 在平台ppc和sh上被kgdb使用
  • h 显示帮助信息
  • i 发送信号SIGKILL给所有的进程,除了init外
  • k 安全访问密钥(Secure Access Key,SAK)杀死在当前虚拟终端上的所有程序
  • m 转储当前的内存信息到控制台
  • o 将关闭系统(如果配置为支持)
  • p 打印当前寄存器和标识到控制台
  • q 将转储所有正运行定时器的列表
  • r 关闭键盘Raw模式并设置为XLATE模式
  • s 尝试同步所有挂接的文件系统
  • t 将转储当前的任务列表和它们的信息到控制台
  • u 尝试以仅读的方式重挂接所有已挂接的文件系统
  • v 转储Voyager SMP处理器信息到控制台
  • w 转储的所有非可中断(已阻塞)状态的任务
  • x 在平台ppc/powerpc上被xmon(X监视器)接口使用
  • 0~9 设备控制台日志级别,控制将打印到控制台的内核信息。例如:0仅打印紧急信息,如:PANIC和OOPS信息

open sysrq func

step1: enable kernel config

Symbol: MAGIC_SYSRQ [=y] 
  | Type : boolean             
  | Prompt: Magic SysRq key                                                  
  | Location:                                                              
  | (1) -> Kernel hacking                                                    
  | Defined at lib/Kconfig.debug:55  | Depends on: !UML | Selected by: KGDB_SERIAL_CONSOLE [=y] && KGDB [=y] && TTY [=y]

step2: make sure sysrq open

确认sysrq是否是非0,非0则代表启用,可以通过快捷键触发进入sysrq,如果sysrq=1,则代表允许任何请求,sysrq等于其他值可以选择性开启部分功能. 不同的cpu平台的快捷键也不一样

/proc/sys/kernel # ls -al -rw-r--r-- 1 root 0 0 Mar 23 14:36 sysrq
/proc/sys/kernel # cat sysrq  1 // sysrq写0则关闭此功能 /proc/sys/kernel # echo "0" > sysrq

how to use sysrq

method1: 使用终端进入sysrq功能

以arm平台为例,可以在终端(like secureCRT)通过键盘组合键ctrl+pause, 5s内输入命令字符执行相应的sysrq功能.

pause

method2: shell

/ # echo "h" >/proc/sysrq-trigger 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) sak(k) show-backtrace-all-active-cpus(l) show-memory-usage(m) nice-all-RT-tasks(n) poweroff(o) show-registers(p) show-all-timers(q) unraw(r) sync(s) show-task-states(t) unmount(u) show-blocked-tasks(w) / #

sysrq understand deeper

sysrq 到底如何触发

基础补充

扫描码和虚拟码

键盘上所有的按键都有扫描码和虚拟码,扫描码由键盘硬件发至设备的键盘驱动,键盘驱动会将扫描码转换成统一的虚拟码,屏蔽掉厂家差异。

ctrl + 字母的ASCII码

ctrl + 字母的ASCII码 = 字母的ASCII码 & 0x1f

串口与break信号

linux kernel 如何识别sysrq

// 在串口接收字符处理函数中会调用break处理函数
unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
{
    uart_handle_break(port)
    uart_handle_sysrq_char(port, ch)
}

// break处理函数的实现,实际上调用了uart_port的break处理
static inline int uart_handle_break(struct uart_port *port)
{
        struct uart_state *state = port->state;

        if (port->handle_break)
                port->handle_break(port);

#ifdef SUPPORT_SYSRQ
        if (port->cons && port->cons->index == port->line) {
                if (!port->sysrq) {
                        port->sysrq = jiffies + HZ*5;
                        return 1;
                }
                port->sysrq = 0;
        }
#endif
        if (port->flags & UPF_SAK)
                do_SAK(state->port.tty);
        return 0;
}    

// 处理sysrq的字符,如果超时则不处理
static inline int
uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
{
        if (port->sysrq) {
                if (ch && time_before(jiffies, port->sysrq)) {
                        handle_sysrq(ch);
                        port->sysrq = 0;
                        return 1;
                }
                port->sysrq = 0;
        }
        return 0;
}

// sysrq.c 中处理sysrq命令
static struct sysrq_key_op *sysrq_key_table[36] = {
        &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 & ibm_emac driver debug */
        &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 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 */
};
阅读(1829) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~