SysRq를 위한 pyserial-miniterm에 send_break() 기능 추가하기

임베디드 리눅스 디바이스를 개발할 때, 시리얼 콘솔을 통해 커널 디버깅 또는 긴급 명령을 보내는 경우가 있다. 그중 하나가 Magic SysRq 키 조합을 시리얼 포트를 통해 보내는 기능이다. Magic SysRq는 리눅스 커널에서 정의된 특수한 시스템 요청 명령어로, 시스템 디버깅이나 복구에 사용된다. 이 기능을 시리얼 환경에서도 사용하려면 BREAK 신호를 전송해야 하는데, 필자가 Ubuntu에서 사용하는 pyserial의 miniterm은 이기능을 지원하지 않는다. 이 글에서는 pyserial의 miniterm 도구에 send_break() 기능을 추가하는 방법에 대해 알아본다.

pyserial-miniterm란?

pyserial-minitermpyserial 패키지에 포함된 시리얼 터미널 유틸리티이다. 사용자는 키보드를 통해 시리얼 장치에 명령을 입력하고, 장치로부터 응답을 받을 수 있다.

실행 예시

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는 시스템 디버깅과 복구를 위한 강력한 커널 기능이며, pyserialminiterm을 통해 시리얼 콘솔에서도 이 기능을 사용할 수 있도록 send_break()을 연동하면 실전 디버깅 환경에서 매우 유용하다. 이 글에서는 간단한 코드 수정을 통해 BREAK 전송 기능을 직접 구현할 하여 실제 동작하는 것을 확인했다.


참고 사이트

답글 남기기