Linux中SysRq的使用

2019-07-13 07:01发布

  • 1.简介
SysRq 键可以直接从内核输出信息。只要不是禁止中断状态,即使死机时也可以获取信息。SysRq 键在确认内核运行、调查内核死机原因等各种情况下都非常有效。
  • 2.需要kernel打开CONFIG_MAGIC_SYSRQ选项支持

  • 3.内核的源代码位置:
drivers/tty/sysrq.c

  • 4.kernel中的实现
static int __init sysrq_init(void){    sysrq_init_procfs();        //注册proc入口    if (sysrq_on())   //按键的话需要开关控制        sysrq_register_handler();        //注册按键处理入口    return 0;}module_init(sysrq_init);
sysrq proc的支持:static void sysrq_init_procfs(void){    if (!proc_create("sysrq-trigger", S_IWUSR, NULL,             &proc_sysrq_trigger_operations))        pr_err("Failed to register proc interface ");}
static const struct file_operations proc_sysrq_trigger_operations = {    .write        = write_sysrq_trigger,    .llseek        = noop_llseek,};
static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,                   size_t count, loff_t *ppos){    if (count) {        char c;        if (get_user(c, buf))            return -EFAULT;        __handle_sysrq(c, false);    }    return count;}
void __handle_sysrq(int key, bool check_mask){    struct sysrq_key_op *op_p;    ...
        op_p = __sysrq_get_key_op(key);        if (op_p) {        /*         * Should we check for enabled operations (/proc/sysrq-trigger         * should not) and is the invoked operation enabled?         */        if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {            printk("%s ", op_p->action_msg);            console_loglevel = orig_log_level;            op_p->handler(key);        } else {            printk("This sysrq operation is disabled. ");        }    }  ...}
struct sysrq_key_op *__sysrq_get_key_op(int key){        struct sysrq_key_op *op_p = NULL;        int i;
    i = sysrq_key_table_key2index(key);    if (i != -1)            op_p = sysrq_key_table[i];
        return op_p;}
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 */}
     
sysrq按键的支持:首先需要打开开关打开这个功能,运行:  # echo 1 > /proc/sys/kernel/sysrq关闭这个功能:  # echo 0 > /proc/sys/kernel/sysrq
#ifdef CONFIG_MAGIC_SYSRQ    {        .procname    = "sysrq",        .data        = &__sysrq_enabled,        .maxlen        = sizeof (int),        .mode        = 0644,        .proc_handler    = sysrq_sysctl_handler,    },#endif
int sysrq_toggle_support(int enable_mask){    bool was_enabled = sysrq_on();
    sysrq_enabled = enable_mask;
    if (was_enabled != sysrq_on()) {        if (sysrq_on())            sysrq_register_handler();        else            sysrq_unregister_handler();    }
    return 0;}由实现可以看出支持动态打开和关闭
注册sysrq按键处理函数:static inline void sysrq_register_handler(void){    int error;
    error = input_register_handler(&sysrq_handler);    if (error)        pr_err("Failed to register input handler, error %d", error);    else        sysrq_handler_registered = true;}
static struct input_handler sysrq_handler = {    .filter        = sysrq_filter,   //哪些消息给sysrq去处理    .connect    = sysrq_connect,    .disconnect    = sysrq_disconnect,    .name        = "sysrq",    .id_table    = sysrq_ids,};
static bool sysrq_filter(struct input_handle *handle,             unsigned int type, unsigned int code, int value){    ...
        default:            if (sysrq->active && value && value != 2) {                sysrq->need_reinject = false;                __handle_sysrq(sysrq_xlate[code], true);            }            break;        }    ....}可以看出sysrq按键最终和proc一样都是调用__handle_sysrq()来处理
  • 5.使用实例

查看内存信息:# echo 'm' > /proc/sysrq-trigger
重启:# echo 'b' > /proc/sysrq-trigger