sysrq

    xiaoxiao2026-09-02  6

    要使用sysrq,需要定义SUPPORT_SYSRQ 如下所示: 438 #ifdef SUPPORT_SYSRQ 439 static inline int 440 uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) 441 { 442         if (port->sysrq) { 443                 if (ch && time_before(jiffies, port->sysrq)) { 444                         handle_sysrq(ch); 445                         port->sysrq = 0; 446                         return 1; 447                 } 448                 port->sysrq = 0; 449         } 450         return 0; 451 } 452 #else 453 #define uart_handle_sysrq_char(port,ch) ({ (void)port; 0; }) 454 #endif 这个函数一般在uart rx的中断函数中调用uart_handle_sysrq_char 最好的是第二个参数ch表示用户当前按下key的ascll码 uart_handle_sysrq_char 继续调用handle_sysrq出来按下的key source/drivers/tty/sysrq.c 577 void handle_sysrq(int key) 578 { 579         if (sysrq_on()) 580                 __handle_sysrq(key, true); 581 } 继续调用__handle_sysrq 524 void __handle_sysrq(int key, bool check_mask) 525 { 526         struct sysrq_key_op *op_p; 527         int orig_log_level; 528         int i; 529  530         rcu_sysrq_start(); 531         rcu_read_lock(); 532         /* 533          * Raise the apparent loglevel to maximum so that the sysrq header 534          * is shown to provide the user with positive feedback.  We do not 535          * simply emit this at KERN_EMERG as that would change message 536          * routing in the consumers of /proc/kmsg. 537          */ 538         orig_log_level = console_loglevel; 539         console_loglevel = CONSOLE_LOGLEVEL_DEFAULT; 540         pr_info("SysRq : "); 541  542         op_p = __sysrq_get_key_op(key); 543         if (op_p) { 544                 /* 545                  * Should we check for enabled operations (/proc/sysrq-trigger 546                  * should not) and is the invoked operation enabled? 547                  */ 548                 if (!check_mask || sysrq_on_mask(op_p->enable_mask)) { 549                         pr_cont("%s\n", op_p->action_msg); 550                         console_loglevel = orig_log_level; 551                         op_p->handler(key); 552                 } else { 553                         pr_cont("This sysrq operation is disabled.\n"); 554                 } 555         } else { 556                 pr_cont("HELP : "); 557                 /* Only print the help msg once per handler */ 558                 for (i = 0; i < ARRAY_SIZE(sysrq_key_table); i++) { 559                         if (sysrq_key_table[i]) { 560                                 int j; 561  562                                 for (j = 0; sysrq_key_table[i] != 563                                                 sysrq_key_table[j]; j++) 564                                         ; 565                                 if (j != i) 566                                         continue; 567                                 pr_cont("%s ", sysrq_key_table[i]->help_msg); 568                         } 569                 } 570                 pr_cont("\n"); 571                 console_loglevel = orig_log_level; 572         } 573         rcu_read_unlock(); 574         rcu_sysrq_end(); 575 } 这个函数的542行拿到对应key的函数,例如按下0~9 来改变log lever.对应的hanler为sysrq_handle_loglever 然后在551行调用这个handle. 我们看看最重要的__sysrq_get_key_op实现. 504 struct sysrq_key_op *__sysrq_get_key_op(int key) 505 { 506         struct sysrq_key_op *op_p = NULL; 507         int i; 508  509         i = sysrq_key_table_key2index(key); 510         if (i != -1) 511                 op_p = sysrq_key_table[i]; 512  513         return op_p; 514 } 其中sysrq_key_table_key2index将key转成index,很简单 488 static int sysrq_key_table_key2index(int key) 489 { 490         int retval; 491  492         if ((key >= '') && (key <= '9')) 493                 retval = key - ''; 494         else if ((key >= 'a') && (key <= 'z')) 495                 retval = key + 10 - 'a'; 496         else 497                 retval = -1; 498         return retval; 499 } 得到这个index后就查询sysrq_key_table 数组得到对应key的handle。  static struct sysrq_key_op *sysrq_key_table[36] = { 429         &sysrq_loglevel_op,             /* 0 */ 430         &sysrq_loglevel_op,             /* 1 */ 431         &sysrq_loglevel_op,             /* 2 */ 例如1对应的op是sysrq_loglevel_op  93 static struct sysrq_key_op sysrq_loglevel_op = {  94         .handler        = sysrq_handle_loglevel,  95         .help_msg       = "loglevel(0-9)",  96         .action_msg     = "Changing Loglevel",  97         .enable_mask    = SYSRQ_ENABLE_LOG,  98 }; 可以看到handler是sysrq_handle_loglevel, 我们再来看看sysrq_handle_loglevel具体是怎么改变log level的  84 static void sysrq_handle_loglevel(int key)  85 {  86         int i;  87   88         i = key - '';  89         console_loglevel = CONSOLE_LOGLEVEL_DEFAULT;  90         pr_info("Loglevel set to %d\n", i);  91         console_loglevel = i;  92 } 可以看到是通过console_loglevel 来改变kernel log level的. 如果想要定制key对应的handler,就需要来修改sysrq_key_table。改法很简单的。只要替换对应key的handle就行了
    转载请注明原文地址: https://ju.6miu.com/read-1311807.html
    最新回复(0)