임베디드 리눅스 디바이스를 개발할 때, 시리얼 콘솔을 통해 커널 디버깅 또는 긴급 명령을 보내는 경우가 있다. 그중 하나가 Magic SysRq 키 조합을 시리얼 포트를 통해 보내는 기능이다. Magic SysRq는 리눅스 커널에서 정의된 특수한 시스템 요청 명령어로, 시스템 디버깅이나 복구에 사용된다. 이 기능을 시리얼 환경에서도 사용하려면 BREAK 신호를 전송해야 하는데, 필자가 Ubuntu에서 사용하는 pyserial의 miniterm은 이기능을 지원하지 않는다. 이 글에서는 pyserial의 miniterm
도구에 send_break()
기능을 추가하는 방법에 대해 알아본다.
pyserial-miniterm란?
pyserial-miniterm
은 pyserial
패키지에 포함된 시리얼 터미널 유틸리티이다. 사용자는 키보드를 통해 시리얼 장치에 명령을 입력하고, 장치로부터 응답을 받을 수 있다.
실행 예시
python3 -m serial.tools.miniterm /dev/ttyUSB0 115200
miniterm
에 BREAK 전송 핫키 추가하기
1. pyserial 소스 경로 확인
pyserial
은 설치 후 보통 아래 경로에 존재한다. (Python 버전에 따라 다를 수 있음):
/usr/lib/python3.*/dist-packages/serial/tools/miniterm.py
필자의 경우는 /usr/lib/python3/dist-packages/serial/tools/miniterm.py 를 사용하고 있었다.
2. 키 입력 핸들러에 BREAK 전송 로직 추가
아래와 같이 /usr/lib/python3/dist-packages/serial/tools/miniterm.py를 수정하여 k키를 누르면 send break 가 되도록 로직을 추가한다.
~$ diff -urN miniterm.py.old miniterm.py.new
--- miniterm.py.old 2025-03-27 16:00:06.404465438 +0900
+++ miniterm.py.new 2025-03-27 15:58:32.800830722 +0900
@@ -629,11 +629,18 @@
elif c in 'rR': # R -> change hardware flow control
self.serial.rtscts = (c == 'R')
self.dump_port_settings()
+ elif c in 'kK': # K -> send break
+ self.send_break()
elif c in 'qQ':
self.stop() # Q -> exit app
else:
sys.stderr.write('--- unknown menu character {} --\n'.format(key_description(c)))
+ def send_break(self):
+ """Send BREAK signal (for SysRq)"""
+ sys.stderr.write('--- Sending BREAK (SysRq) ---\n')
+ self.serial.send_break()
+
def upload_file(self):
"""Ask user for filenname and send its contents"""
sys.stderr.write('\n--- File to upload: ')
@@ -793,6 +800,7 @@
--- b change baud rate
--- x X disable/enable software flow control
--- r R disable/enable hardware flow control
+--- k send break for SysRq
""".format(version=getattr(serial, 'VERSION', 'unknown version'),
exit=key_description(self.exit_character),
menu=key_description(self.menu_character),
- line 8~9:
handle_menu_key()
함수에k
키를 누르면send_break()
가 호출되도록 한다. - lint 15~19:
send_break()
함수를 추가한다. send break를 한다는 출력과 함께serial.send_break()
함수를 호출한다. - line 27:
get_help_text()
함수에k
키가 SysRq를 위한 send break를 한다는 내용을 추가해 준다.
3. 동작 확인
동작 확인을 위해 Ctrl+t 후 k를 눌러서 아래와 같이 출력되는지 확인한다.
--- Sending BREAK (SysRq) ---
그러면 h를 입력하여 SysRq에 어떤 키들을 사용할 수 있는지 아래와 같이 확인한다.
--- Sending BREAK (SysRq) ---
[15105.052884] 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) dump-ftrace-buffer(z) replay-kernel-logs(R)
동작을 확인 했으므로, 아래와 같이 send break후에 show-task-states(t)
를 확인하기 위햇 t를 입력해 보자.
--- Sending BREAK (SysRq) ---
[ 55.543055] sysrq: Show State
[ 55.637848] Sched Debug Version: v0.11, 6.12.0-332 #1
[ 55.642893] ktime : 55636.023040
[ 55.649061] sched_clk : 55637.847775
[ 55.655229] cpu_clk : 55637.847905
[ 55.661395] jiffies : 4294906210
[ 55.667389]
[ 55.668868] sysctl_sched
[ 55.671388] .sysctl_sched_base_slice : 2.250000
[ 55.677469] .sysctl_sched_features : 32695263
[ 55.683549] .sysctl_sched_tunable_scaling : 1 (logarithmic)
[ 55.690237]
[ 55.691716] cpu#0
[ 55.693630] .nr_running : 1
[ 55.698234] .nr_switches : 513937
[ 55.698237] .nr_uninterruptible : -4
[ 55.698238] .next_balance : 4294.906177
[ 55.698240] .curr->pid : 4918
[ 55.698242] .clock : 55543.171340
[ 55.698244] .clock_task : 55543.171340
[ 55.698246] .avg_idle : 640355
[ 55.698247] .max_idle_balance_cost : 500000
[ 55.698249]
[ 55.698252] cfs_rq[0]:/
[ 55.698255] .left_deadline : 0.000001
[ 55.698257] .left_vruntime : 0.000001
[ 55.698258] .min_vruntime : 2666830.375357
[ 55.698261] .avg_vruntime : 2666830.375357
[ 55.698262] .right_vruntime : 0.000001
[ 55.698264] .spread : 0.000000
[ 55.698266] .nr_running : 1
[ 55.698267] .h_nr_running : 1
...
Magic SysRq는 시스템 디버깅과 복구를 위한 강력한 커널 기능이며, pyserial
의 miniterm
을 통해 시리얼 콘솔에서도 이 기능을 사용할 수 있도록 send_break()
을 연동하면 실전 디버깅 환경에서 매우 유용하다. 이 글에서는 간단한 코드 수정을 통해 BREAK 전송 기능을 직접 구현할 하여 실제 동작하는 것을 확인했다.