Basics about SysRq
During the kernel debugging, you can use SysRq to get some details about the system status at some point or to execute some commands without typing the command.
We can use one of the below method to trigger the operation.
Method 1.
- $ echo 1 > /proc/sys/kernel/sysrq
- Press ‘Alt-SysRq-[key]’ combination to trigger the operation. If you are in GUI mode, press ‘Ctrl-Alt-SysRq-[key]’
- You can get details in /var/log/messages.
Method 2.
- $ echo ‘key’ > /proc/sysrq-trigger
- Check /var/log/messages for the result
If you are not familiar what commands are provided in the kernel, you can check it by running the below command.
$ echo h > /proc/sysrq-trigger
Extending SysRq
You can extend SysRq with your own key with some basic steps. You need a handler and need to fill the fileds in sysrq_key_op structure which exists in include/linux/sysrq.h
struct sysrq_key_op { void (*handler)(int, struct tty_struct *); char *help_msg; char *action_msg; int enable_mask; };
After then, you can register and unregister it with the following functions.
int register_sysrq_key(int key, struct sysrq_key_op *op); int unregister_sysrq_key(int key, struct sysrq_key_op *op);
Here is the sample SysRq example module (mysysrq.c)
#include <linux/module.h> #include <linux/init.h> #include <linux/sysrq.h> #include <linux/sched.h> #include <linux/version.h> #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) static void hack_sysrq_task_list(int key, struct pt_regs *ptregs, struct tty_struct *ttystruct) #else static void hack_sysrq_task_list(int key, struct tty_struct *ttystruct) #endif { struct task_struct *p; printk("Start to dump task list ----n"); for_each_process(p) { printk("%s(%d) is %s Runnablen", p->comm, p->pid, p->state == TASK_RUNNING ? "" : "Not"); } printk("End of task dump ----n"); } static struct sysrq_key_op hack_sysrq_op = { .handler = hack_sysrq_task_list, .help_msg = "dump-All-tasks", .action_msg = "Show All Task List", }; static int __init my_init (void) { int ret = register_sysrq_key('a', &hack_sysrq_op); printk("Ret = %dn", ret); return ret; } static void __exit my_exit (void) { unregister_sysrq_key('a', &hack_sysrq_op); } module_init(my_init); module_exit(my_exit); MODULE_LICENSE ("GPL v2");
You also need Makefile to build this.
obj-m += mysysrq.o export KROOT=/lib/modules/`uname -r`/build allofit: modules modules: @$(MAKE) -C $(KROOT) M=$(PWD) modules modules_install: @$(MAKE) -C $(KROOT) M=$(PWD) modules_install clean: rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions .*.d .*.tmp Module.symvers
For this, your system needs to have kernel-devel package installed for the current kernel version.
Now, it’s time to compile and load it.
$ make make[1]: Entering directory `/usr/src/kernels/2.6.32-358.6.1.el6.x86_64' CC [M] /root/Study/mysysrq.o Building modules, stage 2. MODPOST 1 modules CC /root/Study/mysysrq.mod.o LD [M] /root/Study/mysysrq.ko.unsigned NO SIGN [M] /root/Study/mysysrq.ko make[1]: Leaving directory `/usr/src/kernels/2.6.32-358.6.1.el6.x86_64' $ insmod ./mysysrq.ko $ echo h > /proc/sysrq-trigger $ tail -1 /var/log/messages May 5 18:50:18 localhost kernel: SysRq : HELP : loglevel(0-9) dump-All-tasks reBoot Crash terminate-all-tasks(E) memory-full-oom-kill(F) kill-all-tasks(I) thaw-filesystems(J) saK show-backtrace-all-active-cpus(L) show-memory-usage(M) nice-all-RT-tasks(N) powerOff show-registers(P) show-all-timers(Q) unRaw Sync show-task-states(T) Unmount show-blocked-tasks(W) dump-ftrace-buffer(Z) $ echo a > /proc/sysrq-trigger $ tail -3 /var/log/messages May 5 18:48:12 localhost kernel: bash(7942) is Runnable May 5 18:48:12 localhost kernel: pickup(8001) is Not Runnable May 5 18:48:12 localhost kernel: End of task dump ---- $ rmmod mysysrq
Leave a Reply