綾小路龍之介の素人思考

[fork] 数値計算プログラムのデーモン化

CPUの空き時間を有効に利用しなければもったいない。ただえさえ時間のかかる計算プログラムですから。デーモン化の指針として、まずは子プロセスを作ることから始めよう。詳細はman forkとかで検索すればいろいろと引っかかる。関数fork()を使うためには、unistd.hとsys/types.hをインクルード、子プロセスを終了するexit()はstdlib.hをインクルード。pid_tという宣言はint宣言と同じ効果があるようだ。

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int some_caluculation_function(){
        /*
         * calc calc calc...
         */
        return(0);
}
int main()
{
        printf("0:     pid:--------\t");
        printf("0: getppid:%8d\t", getppid());
        printf("0:  getpid:%8d\n", getpid());
        pid_t pid = fork();     /* Make child process */
        printf("A:     pid:%8d\t",  pid);
        printf("A: getppid:%8d\t", getppid());
        printf("A:  getpid:%8d\n", getpid());
        if (pid == 0) {
                /*
                 * Child process
                 */
                printf("B:     pid:%8d\t", pid);
                printf("B: getppid:%8d\t", getppid());
                printf("B:  getpid:%8d\n", getpid());
                some_caluculation_function()
                exit(0);
        } else if (pid < 0) {
                /*
                 * Parent process
                 * Fail making child process
                 */
                printf("C:     pid:%8d\t", pid);
                printf("C: getppid:%8d\t", getppid());
                printf("C:  getpid:%8d\n", getpid());
                exit(1);
        } else {
                /*
                 * Parent process
                 * Success making child process
                 */
                printf("D:     pid:%8d\t", pid);
                printf("D: getppid:%8d\t", getppid());
                printf("D:  getpid:%8d\n", getpid());
        }
        printf("E:     pid:%8d\t", pid);
        printf("E: getppid:%8d\t", getppid());
        printf("E:  getpid:%8d\n", getpid());
        /*
        * return をかかないとinit.dから起動したときに常に失敗。
        */
        return (0);
}

テストプログラムとして作ったのが上。プログラムを実行してみてわかったことは、fork()が実行されると、親プロセスは一時的にストップして、子プロセスが終了するのを待つ。子プロセスはfork()以下から実行されて、どこかで終了する。子プロセスの終了待ちだった親プロセスは子プロセスの終了を検知するとストップしていたところから始まる。

これだけではだめ。せっかくだからchkconfigで起動終了をマシンのスタートストップと連動させてみよう。vineの場合、/etc/init.d/の中に起動スクリプトが納められている。こんな感じでかいてみた。普通のシェルスクリプトと違うところは、start()、stop()、restart()とあること。さらに、始めのコメントの部分にchkconfig:、discription:、processname:、pidfile:があること。

#! /bin/bash
#
# hoge run calculation program
#
# chkconfig: 2345 99 01
# description: hoge run calculation program
# processname: hoge
# pidfile: /var/run/hoge.pid
#
# Source function library.
. /etc/rc.d/init.d/functions
RETVAL=0
DIR="/home/hage/c/hoge/"
PROG="${DIR}hoge"
start(){
        echo -n $"Starting $PROG: "
        cd $DIR
        date >>hoge.stdout.dat
        date >>hoge.stderr.dat
        daemon $PROG
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && touch /var/lock/subsys/hoge
        return $RETVAL
}
stop(){
        echo -n $"Stopping $PROG: "
        killproc $PROG
        RETVAL=$?
        echo
        [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/hoge
        return $RETVAL
}
restart(){
        stop
        start
}
case "$1" in
        start)
                start
                ;;
        stop)
                stop
                ;;
        restart)
                restart
                ;;
        *)
                echo $"usage: $0 {start|stop|restart}"
esac
exit $?

んでもってデーモンの登録。

# chkconfig --add hoge
# chkdonfig --list

できたら起動。

# /etc/init.d/hoge start

再起動とかして起動の確認とかしておくとよさげ。

# ps wax

ソーシャルブックマーク

  1. はてなブックマーク
  2. Google Bookmarks
  3. del.icio.us

ChangeLog

  1. Posted: 2007-07-01T01:32:37+09:00
  2. Modified: 2007-07-01T02:39:24+09:00
  3. Generated: 2017-08-11T23:10:58+09:00