要使用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就行了
如下所示:
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就行了