= 2009-01-22 = == DRBL Shutdown Agent == * [源起] 由於 DRBL Client 在 NFS 斷線後會因為 ROOTFS 消失而找不到關機程序所需的檔案。因此需要有一個背景程序持續等在記憶體中來協助 DRBL Client 關閉電源。 * 準備 sysvinit 套件環境 {{{ # apt-get install dpkg-dev build-essential # apt-get source sysvinit # apt-get build-dep sysvinit # cd sysvinit-2.86.ds1/src ~/sysvinit-2.86.ds1/src# vi Makefile }}} {{{ #!diff --- Makefile.org 2009-01-22 10:00:03.000000000 +0800 +++ Makefile 2009-01-22 09:15:42.000000000 +0800 @@ -9,8 +9,8 @@ -CFLAGS = -Wall -O2 -fomit-frame-pointer -D_GNU_SOURCE -LDFLAGS= -s +CFLAGS = -g -Wall -O2 -fomit-frame-pointer -D_GNU_SOURCE # 加入 -g ,讓 gcc 加入 DEBUG Symbol +LDFLAGS= # 拿掉 -s ,讓 LD 進行 Linking 時不進行 strip }}} {{{ #!sh ~/sysvinit-2.86.ds1/src# make ~/sysvinit-2.86.ds1/src# nm init # 用 nm 可以看到是否有保留 Symbol ~/sysvinit-2.86.ds1/src# file init # 顯示 not stripped 才會保留 Symbol 哦! init: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.4.1, dynamically linked (uses shared libs), for GNU/Linux 2.4.1, not stripped }}} * 先前有追蹤過 shutdown.c 跟 halt.c 的原始碼,發現最後都還是呼叫 init 來執行關機程序。因此這次改追蹤 init.c * 用 gdb 追蹤 init 0 的程序 {{{ ~/sysvinit-2.86.ds1/src# gdb init (gdb) set args 0 (gdb) show args Argument list to give program being debugged when it is started is "0". (gdb) br 2598 Breakpoint 1 at 0x804e140: file init.c, line 2598. (gdb) br 2555 Breakpoint 2 at 0x8049bfd: file init.c, line 2555. (gdb) run Starting program: /root/sysvinit-2.86.ds1/src/init 0 Failed to read a valid object file image from memory. Breakpoint 1, main (argc=1282785413, argv=0x54a165) at init.c:2598 2598 { (gdb) c Continuing. Breakpoint 2, telinit (progname=0xbfff5c53 "init", argc=2, argv=0xbfff5b34) at init.c:2555 2555 SETSIG(sa, SIGALRM, signal_handler, 0); (gdb) handle SIGALRM nopass Signal Stop Print Pass to program Description SIGALRM No No No Alarm clock (gdb) s }}} * 用 strace init 0 觀察關機程序 {{{ root@debian:~/sysvinit-2.86.ds1/src# strace init 0 execve("/sbin/init", ["init", "0"], [/* 14 vars */]) = 0 rt_sigaction(SIGALRM, {0x8049ad0, [], 0}, NULL, 8) = 0 alarm(3) = 0 open("/dev/initctl", O_WRONLY) = 3 write(3, "i\31\t\3\1\0\0\0000\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 384) = 384 close(3) = 0 alarm(0) = 3 exit_group(0) = ? }}}