動作概要 Edit

  • 電源ボタンの状態取得方法
    LANDISKのカーネルには、元々電源ボタンの割り込み制御ルーチンが組み込まれている。
    その情報は次の2つの方法で取得可能。
    • 方法1
      デバイス(99,1)を読むことで割り込みの状態を取得可能。
      電源ボタンがONの場合はEOF(End of File)が、OFFになると、'1'が出力されます。

    • 方法2
      cat /proc/interrupts で 電源ボタンの割り込み発生回数が取得できます。
       11:          0      Julian IRQ  SHUTDOWNSWITCH
      

  • 電源ボタン監視プログラム、landiskpoffの仕様
    デーモンプロセスとして常駐し、デバイス(99,1)を5秒後毎に1byteリード。
    その結果がEOFかそうでないかで、電源ボタンの割り込み判定を行い、
    割り込みが検出されると、引数で指定されたコマンドを実行する。
    (起動時に自動的に実行されるようinit.dスクリプトも用意)
    landisk:~# /usr/local/sbin/landiskpoff /sbin/shutdown -h now &
    

landiskpoffの設定 Edit

  • 電源ボタン監視デーモン、landiskpoffの設定
    • landiskpoff.c
      /* landiskpoff.c  -  http://eggplant.ddo.jp/www/
       *
       * Usage:
       * # mknod /dev/shutdown c 99 1
       * # landiskpoff /usr/local/sbin/shutdown -h now &
       */
      
      #include <stdio.h>
      #include <unistd.h>
      #include <fcntl.h>
      
      int main(int argc, char *argv[])
      {
        int fd, dummy;
      
        if(argc < 2){
          printf("Usage: %s command [argument(s)]\n",argv[0]);
          exit(1);
        }
        if( (fd = open("/dev/shutdown",O_RDONLY)) < 0){
          perror("/dev/shutdown");
          exit(1);
        }
      
        while(read(fd, &dummy, 1) == 0){
          sleep(5);
        }
      
        close(fd);
        execvp(argv[1],&argv[1]);
        perror(argv[1]);
      }
      
      
    • コンパイル&コピー
      landisk:~# gcc -O2 landiskpoff.c -o landiskpoff
      landisk:~# strip landiskpoff
      landisk:~# cp landiskpoff /usr/local/sbin/
      
    • /dev/shutdownの作成
      landisk:~# mknod /dev/shutdown c 99 1
      
  • initスクリプト
    • /etc/init.d/landiskpoff
      #! /bin/sh
      
      set -e
      
      NAME=landiskpoff
      DAEMON=/usr/local/sbin/$NAME
      SCRIPTNAME=/etc/init.d/$NAME
      
      test -x $DAEMON || exit 0
      
      case "$1" in
        start)
      	echo -n "Starting $NAME"
      	$DAEMON  /sbin/shutdown -h now &
      	echo "."
      	;;
        stop)
      	echo -n "Stopping $NAME"
      	killall $DAEMON
      	echo "."
      	;;
        *)
      	echo "Usage: $SCRIPTNAME {start|stop}" >&2
      	exit 1
      	;;
      esac
      exit 0
      
      を用意して、
      landisk:~# chmod +x /etc/init.d/landiskpoff
      landisk:~# update-rc.d landiskpoff defaults 99
       Adding system startup for /etc/init.d/landiskpoff ...
         /etc/rc0.d/K99landiskpoff -> ../init.d/landiskpoff
         /etc/rc1.d/K99landiskpoff -> ../init.d/landiskpoff
         /etc/rc6.d/K99landiskpoff -> ../init.d/landiskpoff
         /etc/rc2.d/S99landiskpoff -> ../init.d/landiskpoff
         /etc/rc3.d/S99landiskpoff -> ../init.d/landiskpoff
         /etc/rc4.d/S99landiskpoff -> ../init.d/landiskpoff
         /etc/rc5.d/S99landiskpoff -> ../init.d/landiskpoff
      

個人メモ … カーネルのエラーログ Edit

  • エラーログ
    レビジョンlandisk.0.4(以前)のカーネルでは、電源ボタンをOFFするとdmesgに次のようなエラーが表れる。
    ソースを追ってみた結果、動作に実害はないもよう。
    次回のレビジョンで修正予定。(レビジョンlandisk.0.5で修正済み)
    irq event 11: bogus return value 5
    
    Call trace: 
    [<8c02da2e>] __report_bad_irq+0x2e/0xa0
    [<8c02d400>] handle_IRQ_event+0x0/0x80
    [<8c013cc0>] printk+0x0/0x20
    [<8c02db06>] note_interrupt+0x26/0xa0
    [<8c02d526>] __do_IRQ+0xa6/0x100
    [<8c007eea>] do_IRQ+0x2a/0x60
    [<8c007ec0>] do_IRQ+0x0/0x60
    [<8c0050e4>] ret_from_exception+0x0/0xc
    [<8c1a4500>] schedule+0x0/0x500
    [<8c003102>] default_idle+0x62/0x80
    [<8c003114>] default_idle+0x74/0x80
    [<8c013cc0>] printk+0x0/0x20
    [<8c00201a>] _stext+0x1a/0x60
    
    handlers:
    [<8c00ee20>] (sw_interrupt+0x0/0xc0)
    
  • 対策パッチ
    --- linux-2.6.11/arch/sh/boards/julian/julian_pwb.c.old 2005-06-16 20:03:03.000000000 +0900
    +++ linux-2.6.11/arch/sh/boards/julian/julian_pwb.c     2005-06-16 20:30:59.000000000 +0900
    @@ -21,6 +21,7 @@
     #include <linux/delay.h>
     #include <linux/sched.h>
     #include <linux/timer.h>
    +#include <linux/interrupt.h>
     
     #include <asm/system.h>
     #include <asm/io.h>
    @@ -41,7 +42,7 @@
     static int swdrv_open(struct inode *, struct file *);
     static int swdrv_close(struct inode *, struct file *);
     static int swdrv_read(struct file *, char *, size_t, loff_t *);
    -static void sw_interrupt(int, void *, struct pt_regs *);
    +static irqreturn_t sw_interrupt(int, void *, struct pt_regs *);
     
     static void shutdown_check(void)
     {
    @@ -100,7 +101,7 @@
                    return 0;
     }
     
    -static void sw_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    +static irqreturn_t sw_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     {
            if (!shutdown_sw_flag) {
                    disable_irq(irq);
    @@ -112,6 +113,7 @@
                    if (!shutdown_complete_flag)
                            enable_irq(irq);
            }
    +       return IRQ_HANDLED;
     }
     
     static struct file_operations swdrv_fops = {
    

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2006-06-13 (火) 20:02:27 (6534d)