(57)【特許請求の範囲】
【請求項１】
複数のスレッドを実行する計算機システムであって、
前記計算機システムは、
少なくとも一つのプロセッサと、メモリとを備え、
アプリケーションプログラミングインタフェースによって処理が割り当てられたＡＰＩ関数を実行するため、前記各スレッドを実行し、
第１の前記ＡＰＩ関数に割り当てられた第１の処理を実行するため、第１の前記スレッドを実行し、
前記第１のスレッドの状態を監視する処理を実行するため、監視スレッドを実行し、
前記第１のスレッドが正常であるか否かを示す生存情報を保持するための監視情報領域と、
前記第１の処理を示す情報と、前記第１のスレッドが正常であることを示す値によって前記生存情報を更新する第２の処理を示す情報と、を含む第１の処理内容と、を前記メモリに保持し、
前記第１のスレッドは、前記第１の処理内容を読み出すことによって、前記第１の処理および前記第２の処理を実行するＡＰＩ関数フック処理を行い、
前記監視スレッドは、
前記生存情報が前記第１のスレッドが正常であることを示すか否かを判定し、
前記生存情報が前記第１のスレッドが正常であることを示すと判定された場合、前記第１のスレッドは正常であると判定し、かつ、前記第１のスレッドが正常であることを示さない値によって前記生存情報を更新し、
前記生存情報が前記第１のスレッドが正常であることを示さないと判定された場合、前記第１のスレッドは正常ではないと判定することを特徴とする計算機システム。
【請求項２】
前記計算機システムは、前記監視スレッドが前記第１のスレッドの状態を監視するための監視周期を、前記メモリにさらに保持し、
前記監視情報領域は、前記第１のスレッドが待ち状態であるか否かを示す待ち情報を、さらに保持し、
前記第１の処理内容は、前記第１の処理が開始されることを示す値によって前記待ち情報を更新する第３の処理を示す情報と、前記第１の処理が終了したことを示す値によって前記待ち情報を更新する第４の処理を示す情報と、前記第１の処理、前記第２の処理、前記第３の処理および前記第４の処理が実行される順番と、をさらに含み、
前記第１のＡＰＩ関数が実行される際、前記第１のスレッドは、前記第１の処理内容に含まれる前記順番に従って、前記第２の処理および前記第３の処理を実行した後に前記第１の処理を実行し、前記第１の処理を実行した後に前記第４の処理を実行し、
前記監視スレッドは、
前記監視周期において前記待ち情報が、前記第１の処理が開始されることを示すか、または、前記第１の処理が終了したことを示すかを判定し、
前記待ち情報が、前記第１の処理が開始されることを示すと判定された場合、前記第１のスレッドは正常であると判定し、
前記待ち情報が、前記第１の処理が終了したことを示すと判定された場合、前記生存情報が前記第１のスレッドが正常であることを示すか否かを判定することを特徴とする請求項１に記載の計算機システム。
【請求項３】
前記第１のスレッドは、前記第１のＡＰＩ関数を含むプログラムを実行するためのプロセスに含まれ、
前記監視スレッドが、前記第１のスレッドは正常ではないと判定した場合、前記計算機システムは、前記第１のスレッド、または、前記プロセスを再起動することを特徴とする請求項１に記載の計算機システム。
【請求項４】
前記計算機システムは、
前記ＡＰＩ関数が実行される際に読み出される共有ライブラリを、前記メモリにさらに保持し、
前記共有ライブラリは、前記第１の処理内容を示す識別子を含み、
前記第１のスレッドは、前記共有ライブラリを読み出すことによって、前記第１の処理内容を読み出すことを特徴とする請求項１に記載の計算機システム。
【請求項５】
前記計算機システムは、
前記スレッドが実行されることによって実行される前記ＡＰＩ関数の使用状況を示す統計情報と、
前記ＡＰＩ関数の使用状況を示す統計情報を更新する処理を示す第２の処理内容と、を前記メモリにさらに保持し、
第２の前記ＡＰＩ関数に割り当てられた第５の処理を実行するため、第２の前記スレッドを実行し、
前記統計情報に従って、前記第１のＡＰＩ関数を決定する決定スレッドを実行し、
前記第２のスレッドは、前記第２の処理内容を読み出すことによって、前記第５の処理と、前記第２のＡＰＩ関数の使用状況を示す前記統計情報を更新する処理とを実行し、
前記決定スレッドは、
前記第２のＡＰＩ関数を前記第１のＡＰＩ関数として決定するか否かを、前記統計情報に従って判定することを特徴とする請求項１に記載の計算機システム。
【請求項６】
前記計算機システムは、前記第１のＡＰＩ関数として選択されない前記ＡＰＩ関数を示す禁止情報を、前記メモリにさらに保持し、
前記第２のＡＰＩ関数を前記第１のＡＰＩ関数として決定すると前記統計情報に従って判定され、かつ、前記禁止情報が前記第２のＡＰＩ関数を示さない場合、前記決定スレッドは、前記第２のＡＰＩ関数を前記第１のＡＰＩ関数に決定することを特徴とする請求項５に記載の計算機システム。
【請求項７】
前記計算機システムは、
前記第１のスレッドが実行される際に、前記監視情報領域を前記メモリに生成し、前記第１のスレッドを示す識別子と前記監視情報領域の前記メモリにおける位置とを、前記監視スレッドに通知する処理を実行し、
前記監視スレッドは、前記通知された第１のスレッドを示す識別子と監視情報領域のメモリにおける位置とに基づいて、前記生存情報が第１のスレッドが生存していることを示すか否かを判定することを特徴とする請求項１に記載の計算機システム。
【請求項８】
複数のスレッドを実行する計算機システムによる監視方法であって、
前記計算機システムは、
少なくとも一つのプロセッサと、メモリとを備え、
前記監視方法は、
前記プロセッサが、アプリケーションプログラミングインタフェースによって処理が割り当てられたＡＰＩ関数を実行するため、前記各スレッドを実行する手順と、
前記プロセッサが、第１の前記ＡＰＩ関数に割り当てられた第１の処理を実行するため、第１の前記スレッドを実行する手順と、
前記プロセッサが、前記第１のスレッドの状態を監視する処理を実行するため、監視スレッドを実行する手順と、を含み、
前記計算機システムは、
前記第１のスレッドが正常であるか否かを示す生存情報を保持するための監視情報領域と、
前記第１の処理を示す情報と、前記第１のスレッドが正常であることを示す値によって前記生存情報を更新する第２の処理を示す情報と、を含む第１の処理内容と、を前記メモリに保持し、
前記第１のスレッドを実行する手順は、前記プロセッサが、前記第１の処理内容を読み出すことによって、前記第１の処理および前記第２の処理を実行するＡＰＩ関数フック処理を行う手順を含み、
前記監視スレッドを実行する手順は、
前記プロセッサが、前記生存情報が前記第１のスレッドが正常であることを示すか否かを判定する手順と、
前記プロセッサが、前記生存情報が前記第１のスレッドが正常であることを示すと判定された場合、前記第１のスレッドは正常であると判定し、かつ、前記第１のスレッドが正常であることを示さない値によって前記生存情報を更新する手順と、
前記プロセッサが、前記生存情報が前記第１のスレッドが正常であることを示さないと判定された場合、前記第１のスレッドは正常ではないと判定する手順と、を含むことを特徴とする監視方法。
【請求項９】
前記計算機システムは、前記監視スレッドが前記第１のスレッドの状態を監視するための監視周期を、前記メモリにさらに保持し、
前記監視情報領域は、前記第１のスレッドが待ち状態であるか否かを示す待ち情報を、さらに保持し、
前記第１の処理内容は、前記第１の処理が開始されることを示す値によって前記待ち情報を更新する第３の処理を示す情報と、前記第１の処理が終了したことを示す値によって前記待ち情報を更新する第４の処理を示す情報と、前記第１の処理、前記第２の処理、前記第３の処理および前記第４の処理が実行される順番と、をさらに含み、
前記第１のスレッドを実行する手順は、前記プロセッサが、前記第１の処理内容に含まれる前記順番に従って、前記第２の処理および前記第３の処理を実行した後に前記第１の処理を実行し、前記第１の処理を実行した後に前記第４の処理を実行する手順、を含み、
前記監視スレッドを実行する手順は、
前記プロセッサが、前記監視周期において前記待ち情報が、前記第１の処理が開始されることを示すか、または、前記第１の処理が終了したことを示すかを判定する手順と、
前記プロセッサが、前記待ち情報が前記第１の処理が開始されることを示すと判定された場合、前記第１のスレッドは正常であると判定する手順と、
前記プロセッサが、前記待ち情報が前記第１の処理が終了したことを示すと判定された場合、前記生存情報が前記第１のスレッドが正常であることを示すか否かを判定することを特徴とする請求項８に記載の監視方法。
【請求項１０】
前記第１のスレッドは、前記第１のＡＰＩ関数を含むプログラムを実行するためのプロセスに含まれ、
前記監視方法は、前記監視スレッドを実行する手順において前記プロセッサが、前記第１のスレッドは正常ではないと判定した場合、前記プロセッサが、前記第１のスレッド、または、前記プロセスを再起動する手順を含むことを特徴とする請求項８に記載の監視方法。
【請求項１１】
前記計算機システムは、前記ＡＰＩ関数が実行される際に読み出される共有ライブラリを、前記メモリにさらに保持し、
前記共有ライブラリは、前記第１の処理内容を示す識別子を含み、
前記第１のスレッドを実行する手順は、前記プロセッサが、前記共有ライブラリを読み出すことによって、前記第１の処理内容を読み出す手順を含むことを特徴とする請求項８に記載の監視方法。
【請求項１２】
前記計算機システムは、
前記スレッドが処理されることによって実行される前記ＡＰＩ関数の使用状況を示す統計情報と、
前記ＡＰＩ関数の使用状況を示す統計情報を更新する処理を示す第２の処理内容と、を前記メモリにさらに保持し、
前記監視方法は、
前記プロセッサが、第２の前記ＡＰＩ関数に割り当てられた第５の処理を実行するため、第２の前記スレッドを実行する手順と、
前記プロセッサが、前記統計情報に従って、前記第１のＡＰＩ関数を決定する手順と、を含み、
前記第２のスレッドを実行する手順は、前記第２の処理内容を読み出すことによって、前記第５の処理と、前記第２のＡＰＩ関数の使用状況を示す前記統計情報を更新するＡＰＩ関数フック処理とを実行する手順を含み、
前記第１のＡＰＩ関数を決定する手順は、前記プロセッサが、前記統計情報に従って、前記第２のＡＰＩ関数を前記第１のＡＰＩ関数に決定するか否かを判定する手順を含むことを特徴とする請求項８に記載の監視方法。
【請求項１３】
前記計算機システムは、前記第１のＡＰＩ関数として選択されない前記ＡＰＩ関数を示す禁止情報を、前記メモリにさらに保持し、
前記第１のＡＰＩ関数を決定する手順は、前記第２のＡＰＩ関数を前記第１のＡＰＩ関数として決定すると前記統計情報に従って判定され、かつ、前記禁止情報が前記第２のＡＰＩ関数を示さない場合、前記プロセッサが、前記第２のＡＰＩ関数を前記第１のＡＰＩ関数に決定する手順を含むことを特徴とする請求項１２に記載の監視方法。
【請求項１４】
前記監視方法は、
前記第１のスレッドが実行される際に、前記監視情報領域を前記メモリに生成し、前記第１のスレッドを示す識別子と前記監視情報領域の前記メモリにおける位置とを、前記監視スレッドに通知する手順を含み、
前記生存情報が前記第１のスレッドが正常であることを示すか否かを判定する手順は、前記プロセッサが、前記通知された第１のスレッドを示す識別子と監視情報領域のメモリにおける位置とに基づいて、前記生存情報が第１のスレッドが生存していることを示すか否かを判定する手順を含むことを特徴とする請求項８に記載の監視方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、計算機システムに関し、特に、スレッドの監視を行う計算機システムに関する。
【背景技術】
【０００２】
近年、様々なシステムにおいてマルチスレッド環境によって稼働するソフトウェアが普及している。マルチスレッド環境は、ＯＳ（Ｏｐｅｒａｔｉｎｇ  Ｓｙｓｔｅｍ）が処理の実行単位をスレッドによって管理し、複数のスレッドを実行する。具体的には、ＯＳが、各スレッドに割り当てられるＣＰＵ（Ｃｅｎｔｒａｌ  Ｐｒｏｃｅｓｓｉｎｇ  Ｕｎｉｔ）時間をスケジューリングする。そして、スケジューリングされたスレッドは、ＣＰＵ時間を割り当てられた時間だけ実行される。
【０００３】
従って、ＣＰＵが複数備わるマルチスレッド環境は、スレッドを並列に実行することによって処理を高速化できるという利点がある。しかし、スレッドを並列に実行することによって、シングルスレッド環境において生じなかったスレッドの異常動作という新たな問題が発生する。マルチスレッド環境におけるスレッドの異常動作としては、無限ループおよびデッドロックが知られている。
【０００４】
ここで、無限ループとは、ループ処理を終了できずに、ソフトウェア開発者が意図していない処理を繰り返す状態である。また、デッドロックとは、複数のスレッドまたは複数のプロセスなどの処理単位がリソースを共有する場合において、リソースを占有（ロック）中の処理単位が互いにリソースの解放（アンロック）を待ったり、または、各処理単位がリソースを占有した後にリソースをアンロックしなかったりすることによって、処理の続きが実行されずに処理が停止する状態である。
【０００５】
ここで、プロセスとはプログラムの実行単位である。プロセスは、プログラム内で利用される変数および状態を保持し、一つ以上のスレッドから構成される。また、アンロックとは、占有中の共有リソースを解放し、他のスレッドがアクセスできるようにすることである。
【０００６】
これらの異常動作はプロセスを異常終了させないため、ソフトウェアの開発者または使用者が異常の発生に気付かないという問題がある。また、異常に気付いた場合も、複数のスレッドによる処理が並列に実行されるため、スレッド全体の状態を追うことが困難になり、原因解析にも時間がかかる。そこで、スレッドの異常動作を検出する「スレッド死活監視」の技術が重要となってくる。
【０００７】
最も単純なスレッド死活監視の方法としては、監視対象となるスレッドが生存フラグを保持し、監視対象のスレッドを監視するスレッド（監視スレッド）が、生存フラグを確認する方法がある。しかし、この方法では監視対象となるプロセスを生成するプログラムのソースコードを直接変更し、さらに、ソースコードをコンパイルしなければならない点と、使用者の入力待ちなどのＷＡＩＴ状態を異常として誤検出する点に問題がある。
【０００８】
なお、コンパイルとは、ソースコードから計算機が実行できるバイナリ形式の実行ファイルを生成することである。
【０００９】
そこで、スレッドにＣＰＵを割り当ててからスレッドの切り替え命令が発生するまでの命令実行数から、無限ループを検出するスレッド異常動作検知方法およびプログラムが提案されている（例えば、特許文献１参照）。ここで、スレッドの切り替え命令とは、スレッドの処理を停止し、別スレッドにＣＰＵを割り当てる命令である。スレッドの切り替え命令には、スリープ関数およびロック取得待ち関数が含まれる。特許文献１に記載された方法は、スレッドが切り替わるまでの実行命令数が閾値より大きくなったか否かを判定することによって、命令を実行し続ける無限ループを検出することができる。
【００１０】
さらに、ロック取得および解除に対してＡＰＩ関数フックを行い、スレッド毎に共有リソースに対して「ロック中」および「ロック取得中」の情報を取得し、その組み合わせによってデッドロックを検出する計算機システムおよびプログラムが提案されている（例えば、特許文献２参照）。
【００１１】
ここで、ＡＰＩ関数とは、ＯＳまたはミドルウェアが提供するアプリケーションおよびソフトウェア開発向けのインターフェースであり、共通ライブラリによって提供される。また、ＡＰＩ関数フックとは、ＡＰＩ関数の処理を横取りし、横取りされたＡＰＩ関数の処理の代わりに使用者が独自に定義した処理を、ＣＰＵに行わせることである。
【００１２】
また、「ロック中」とは、リソースを使用しているスレッド以外のスレッドがリソースにアクセスできない状態であり、「ロック取得中」とは、ロック中のリソースが解放されるのを待ってからロックしようとしている状態である。
【００１３】
特許文献２に記載の計算機システムは、これらの情報を組み合わせることによって、デッドロックを検出できる。例えば、リソースＡを「ロック中」であり、かつ、リソースＢを「ロック取得中」であるスレッド１と、リソースＡを「ロック取得中」であり、かつ、リソースＢを「ロック中」であるスレッド２とが同時に存在した場合、互いにリソースが解放されるのを待ち続けるデッドロックとして検出できる。
【先行技術文献】
【特許文献】
【００１４】
【特許文献１】特開２００８−２０４０１３号広報
【特許文献２】特開２００９−２７１８５８号広報
【発明の概要】
【発明が解決しようとする課題】
【００１５】
まず、前述の特許文献１には以下の問題点が存在する。
【００１６】
特許文献１における第１の問題点は、デッドロックが発生した場合、スレッドが休眠状態（処理が停止している状態）を続け、実行命令数が増加しなくなるため、デッドロックが検出されないことである。
【００１７】
また、特許文献１における第２の問題点は、ＯＳの中枢であり、かつ、複雑なソフトウェアであるカーネル（または、さらに下位層のソフトウェア）の変更が必要であり、スレッド死活監視の対象外のプロセスにも影響があることである。
【００１８】
また、特許文献１における第３の問題点は、無限ループとなるプログラムがスレッド切り替え命令を含む場合、命令実行数がリセットされるため、無限ループが検出されないことである。
【００１９】
さらに、前述の特許文献２には以下の問題点が存在する。
【００２０】
特許文献２における第１の問題点は、特許文献２のように「ロック中」と「ロック取得中」との情報を取得する方法のみでは、ロック処理を全く行わない無限ループが検出されないことである。
【００２１】
特許文献２における第２の問題点は、ロック処理を行うＡＰＩ関数にＡＰＩ関数フックが行われるため、共有リソースを占有する時間がＡＰＩ関数フックする時間分増え、他のスレッドが共有リソースにアクセスできない時間が増えるため、実行速度に影響が出ることである。
【００２２】
特許文献２における第３の問題点は、特許文献２に記載のシステムが、ロック処理を伴わない関数が処理として停止している状態を、検出できないことである。例えば、特許文献２に記載のシステムは、他のスレッドからの信号が到達するまで停止し続けるｃｏｎｄ＿ｗａｉｔ  ＡＰＩ関数による停止状態を検出できない。
【００２３】
前述の特許文献１および特許文献２における問題点は、特許文献１と特許文献２とを組み合わせても、スレッド切り替え命令を含む無限ループ、および、ロック処理を伴わない関数の停止状態を検出できないため、容易には解決できない。
【００２４】
従って、本発明の目的は前述の六つの問題点を解決する方法を提供することである。
【００２５】
具体的には、本発明の目的は、無限ループ、デッドロック、またはロック処理を伴わない停止処理によってスレッドが正常に動作していないことを、検出できるスレッド死活監視方法の提供である。そして、この提供に伴い、カーネルの変更、ソースコードの変更およびリコンパイル、または、コンパイル済み実行ファイルへの変更が不要であり、かつ、スレッドの動作を遅延させないことが目的である。
【課題を解決するための手段】
【００２６】
本発明の代表的な一形態によると、複数のスレッドを実行する計算機システムであって、前記計算機システムは、少なくとも一つのプロセッサと、メモリとを備え、アプリケーションプログラミングインタフェースによって処理が割り当てられたＡＰＩ関数を実行するため、前記各スレッドを実行し、第１の前記ＡＰＩ関数に割り当てられた第１の処理を実行するため、第１の前記スレッドを実行し、前記第１のスレッドの状態を監視する処理を実行するため、監視スレッドを実行し、前記第１のスレッドが正常であるか否かを示す生存情報を保持するための監視情報領域と、前記第１の処理を示す情報と、前記第１のスレッドが正常であることを示す値によって前記生存情報を更新する第２の処理を示す情報と、を含む第１の処理内容と、を前記メモリに保持し、前記第１のスレッドは、前記第１の処理内容を読み出すことによって、前記第１の処理および前記第２の処理を実行するＡＰＩ関数フック処理を行い、前記監視スレッドは、前記生存情報が前記第１のスレッドが正常であることを示すか否かを判定し、前記生存情報が前記第１のスレッドが正常であることを示すと判定された場合、前記第１のスレッドは正常であると判定し、かつ、前記第１のスレッドが正常であることを示さない値によって前記生存情報を更新し、前記生存情報が前記第１のスレッドが正常であることを示さないと判定された場合、前記第１のスレッドは正常ではないと判定する。
【発明の効果】
【００２７】
本発明の一実施形態によると、無限ループ、デッドロック、または、ロック処理を伴わない停止処理による、スレッドの状態を判定できる。
【図面の簡単な説明】
【００２８】
【図１】本発明の第１の実施形態のスレッド死活監視方法を示す説明図である。
【図２】本発明の第１の実施形態の機器のハードウェア構成を示すブロック図である。
【図３】本発明の第１の実施形態のＡＰＩ関数フック群を示す説明図である。
【図４】本発明の第１の実施形態の監視スレッドが保持するデータおよびスレッドが保持するデータを示す説明図である。
【図５】本発明の第１の実施形態の生存報告および異常動作検出を示すシーケンス図である。
【図６】本発明の第１の実施形態の監視スレッドによる異常動作検出を示すフローチャートである。
【図７】本発明の第２の実施形態の異常動作検出を示すシーケンス図である。
【図８】本発明の第２の実施形態の生存確認示すフローチャートである。
【図９】本発明の第３の実施形態のＡＰＩ関数フック群を決定する処理を示す説明図である。
【図１０】本発明の第３の実施形態のＡＰＩ関数選択プログラムの処理を示すフローチャートである。
【図１１】従来技術のスレッド死活監視方法を示す説明図である。
【図１２】従来技術の生存確認の処理を示すフローチャートである。
【発明を実施するための形態】
【００２９】
以下、本発明実施の形態について図面を用いて説明する。
【００３０】
（第１の実施形態）
本実施形態において、スレッドが正常に稼働しているか否かを監視（以下、スレッド監視）する装置として、通信システムを構成するゲートウェイの機能を有する計算機を例に説明する。
【００３１】
なお、本実施形態におけるＡＰＩ関数フック処理とは、ＡＰＩ関数に対して利用者が独自の処理を追加または処理内容を変更することである。また、ライブラリとは、特定の処理および機能を行うための再利用可能なコード（プログラム）を含む、データの集まりである。また、共有ライブラリとは、複数のプログラムによって共有されるライブラリであり、ＡＰＩ関数も共有ライブラリとして提供される。また、スレッドとは、計算機による処理の分割単位であり、計算機がスレッドを生成することによって、計算機は、分割した処理を並列に実行することができる。
【００３２】
図１１は、従来技術のスレッド監視方法を示す説明図である。
【００３３】
従来のゲートウェイ機器におけるスレッド監視の処理は、図１１に示すように、複数のスレッド１２、監視スレッド１１、および、カーネル１００によって実行される。従来のゲートウェイ機器は、プロセッサおよびメモリ（主記憶装置）を備える。ゲートウェイ機器に備わるプロセッサがメモリを用いてＯＳまたはアプリケーションプログラムを実行することによって、カーネル１００、監視スレッド１１およびスレッド１２を実行する。
【００３４】
カーネル１００は、ゲートウェイ機器のＯＳを実行するための処理単位である。監視スレッド１１は、プログラムを実行するための処理単位であり、スレッド１２のスレッド監視を行うスレッドである。スレッド１２は、プログラムを実行するための処理単位である。
【００３５】
図１１に示すスレッド１２は、ゲートウェイ機器に送信されるパケットを受信し、受信したパケットを加工し、加工されたパケットを送信する処理を行う。スレッド１２は、命令メッセージキュー１３０、および、生存フラグ１４０をメモリに保持する。命令メッセージキュー１３０は、カーネル１００、他のスレッド１２、または、監視スレッド１１から送信される命令メッセージを保持するためのキューである。生存フラグ１４０は、スレッド１２によって更新される記憶領域であり、監視スレッド１１によって参照および更新される。
【００３６】
スレッド１２が開始された後（１２１）、スレッド１２は、命令メッセージキュー１３０に命令メッセージが追加されるまで待つ（１２２）。ステップ１２２の後、スレッド１２は、命令メッセージキュー１３０に追加された命令メッセージが、監視命令メッセージ１３１か否かを判定する（１２３）。
【００３７】
命令メッセージキュー１３０は、スレッド１２へ送信された命令メッセージを格納するデータ構造を含む。スレッド１２は、命令メッセージキュー１３０に命令メッセージが追加された順番に命令メッセージを処理する。
【００３８】
ステップ１２３において、命令メッセージキュー１３０に追加された命令メッセージが監視命令メッセージ１３１であると判定された場合、スレッド１２は、スレッド１２が生存していると報告するための処理（生存報告）を実行する（１２４）。
【００３９】
ステップ１２４における生存報告は、あらかじめ保持された１ビットの生存フラグ１４０に、１を格納する処理（有効化）である。生存フラグ１４０は、スレッド１２が生成された際に生成される。
【００４０】
ステップ１２３において、命令メッセージキュー１３０に追加された命令メッセージが監視命令メッセージ１３１ではなく、パケット受信命令メッセージである場合、スレッド１２は、パケットを受信し（１２５）、受信したパケットを加工し（１２６）、加工されたパケットを送信する（１２７）。スレッド１２は、ステップ１２４またはステップ１２７が終了後、ステップ１２２に戻り、次の命令メッセージが命令メッセージキュー１３０に追加されるまで待つ。
【００４１】
一方、監視スレッド１１が開始された後、監視スレッド１１は、所定の監視周期が経過したか否かを判定し（１１２）、監視周期が経過するまで待つ。監視周期が経過した場合、監視命令メッセージ１３１を生成し（１１３）、スレッド１２の命令メッセージキュー１３０の末尾に監視命令メッセージ１３１を追加する。ステップ１１３の後、生存フラグ１４０を参照し、スレッド１２の生存確認３００を行う。
【００４２】
生存確認３００において、監視スレッド１１は、生存フラグ１４０に１が格納されているか否かを判定し、１が格納されている場合、スレッド１２は生存していると判定し、生存フラグ１４０に０を格納する（無効化）。
【００４３】
生存確認３００の後、監視スレッド１１は、ステップ１１２に戻る。
【００４４】
図１２は、従来技術の生存確認３００の処理を示すフローチャートである。
【００４５】
監視スレッド１１は、図１２のフローチャートに示すように生存確認３００を行う。まず、監視スレッド１１は、生存フラグ１４０に１が格納されているか否か判定する（３１０）。そして、生存フラグ１４０に１が格納されている場合、監視スレッド１１は生存フラグ１４０に０を格納し（３２０）、監視スレッド１１はスレッド１２が正常であると判定する（３３０）。
【００４６】
ステップ３１０において、生存フラグ１４０に１が格納されていないと判定された場合、監視スレッド１１は、スレッド１２が異常であると判定する（３４０）。ステップ３３０またはステップ３４０が終了した後、監視スレッド１１は、生存確認３００を終了する（３５０）。
【００４７】
さらに、ＯＳの機能によってソフトウェア割り込み１５０が発生した場合、カーネル１００は、割り込み処理を開始する（１０１）。図１１に示すソフトウェア割り込み１５０は、パケットをゲートウェイ機器が受信した場合に実行される。
【００４８】
カーネル１００は、他の機器がゲートウェイ機器に送信したパケットを、ＮＩＦ（Ｎｅｔｗｏｒｋ  ＩｎｔｅｒＦａｃｅ）から受信する（１０２）。ステップ１０２の後、カーネル１００は、ソケットバッファに受信したパケットデータをコピーする（１０３）。
【００４９】
ここで、ソケットバッファとは、カーネル１００が受信したパケットの内容を一時的に保存しておくメモリである。ソケットバッファは、スレッド１２がパケットを受信するために用いられる。
【００５０】
ステップ１０３の後、カーネル１００は、パケット受信命令メッセージ１３２を生成し（１０４）、生成されたパケット受信命令メッセージ１３２を命令メッセージキュー１３０の末尾に追加する。そして、ステップ１０４の後、カーネル１００は、割り込み処理を終了する（１０５）。
【００５１】
図１１および図１２に示す処理によって、スレッド１２は、パケットの受信処理とスレッド監視処理における生存報告処理との両方を実現する。また、監視スレッド１１が監視命令メッセージ１３１を命令メッセージキュー１３０に追加するため、監視スレッド１１は、監視スレッド１１が生存確認３００をする前にスレッド１２のＷＡＩＴ状態を終了させ、ステップ１２４における生存報告を実行させることができる。
【００５２】
しかし、図１１および図１２に示す処理を、スレッド監視方法を導入していないシステムに適用する場合、開発者が、監視対象となるスレッド１２のソースコードを生存報告をするように変更し、さらに、変更されたソースコードをコンパイルしなければならない。また、監視スレッド１１による監視命令メッセージ１３１の送信およびスレッド１２による監視命令メッセージ１３１の受信のため、ゲートウェイ機器のＣＰＵ処理時間が増加する問題がある。
【００５３】
さらに、図１１の処理において、スレッド１２は監視命令メッセージ１３１を契機に生存報告を行うため、パケットを受信する処理（ステップ１２５〜ステップ１２７）に時間がかかった場合に生存報告が間に合わなくなる可能性がある。この場合、監視スレッド１１は、スレッド１２を異常と誤判定する可能性がある。
【００５４】
このため、本発明の第１の実施形態は、監視命令メッセージ１３１を利用しない方法として、ＡＰＩ関数フックによるスレッド監視方法を用いる。
【００５５】
図１は、本発明の第１の実施形態のスレッド監視方法を示す説明図である。
【００５６】
図１に示すスレッド監視の処理は、スレッド１２０、監視スレッド１１０、およびカーネル１００によって実行される
第１の実施形態のスレッド監視方法は、ステップ１２２における命令メッセージキュー１３０への命令メッセージの追加を待つ処理において、スレッド１２０が、スレッド１２０をＷＡＩＴ状態にするＡＰＩ関数（例えば、ｓｌｅｅｐ  ＡＰＩ関数）をＡＰＩ関数フックすることによって、ステップ１２２の処理を横取りする方法である。なお、ＡＰＩ関数フックの方法は後述する。
【００５７】
そして、第１の実施形態のスレッド監視方法は、横取りされたＡＰＩ関数に含まれる固有の処理（スレッド１２０をＷＡＩＴ状態にするＡＰＩ関数の処理）に、生存報告２００をする処理を追加させる。例えば、横取りされたＡＰＩ関数がｓｌｅｅｐ  ＡＰＩ関数である場合、スレッド１２０は、スレッド１２０を指定された秒数の間停止する処理に加え、生存報告２００をする処理を追加させる。
【００５８】
これによって、スレッド１２０は、図１１におけるステップ１２４において実行されていた生存報告を、スレッド監視の対象のスレッド１２０のソースコードの変更とコンパイルとを行うことなく、ステップ１２２において実行できる。また、監視命令メッセージ１３１に関する、ステップ１１３における生成処理とステップ１２３における受信判定処理とが不要になり、プログラムサイズの縮小とプロセッサの処理時間の削減とが可能になる。
【００５９】
そして、ＡＰＩ関数フックは、監視対象であるスレッド１２０のソースコードに変更を加えない方法であるため、既存システムに変更を加えずにスレッド監視方法を提供することができる。
【００６０】
さらに、第１の実施形態のスレッド監視方法はフックする対象のＡＰＩ関数を選択することができるため、ステップ１２５におけるパケットの受信処理、ステップ１２６におけるパケットの加工処理、または、ステップ１２７におけるパケットの送信処理が、ＡＰＩ関数フックする対象として選択されることによって、ステップ１２５〜ステップ１２７における処理のいずれかにおいて、スレッド１２０が生存報告２００をすることも可能である。
【００６１】
そしてこれによって、第１の実施形態のスレッド監視方法は、ゲートウェイ機器が受信するパケットのサイズが大きく、ステップ１２５〜ステップ１２７の処理に要する合計時間が、監視スレッド１１０が保持する所定の監視周期よりも大きくなった場合も、後述する処理によって、監視スレッド１１０がスレッド１２０を異常状態として誤判定することを防ぐことができる。
【００６２】
なお、後述する本実施形態におけるＡＰＩ関数フックを実現する方法には、Ｕｎｉｘ（登録商標）またはＬｉｎｕｘ（登録商標）系ＯＳにおいて、開発者または所定のプログラムが、フック処理を定義した共有ライブラリをあらかじめ生成し、生成された共有ライブラリへのパスをＬＤ＿ＰＲＥＬＯＡＤ環境変数等の環境変数に追記する方法を用いる。スレッド１２０を含むプロセスが起動時にＬＤ＿ＰＲＥＬＯＡＤ環境変数を読み出し、ＬＤ＿ＰＲＥＬＯＡＤ環境変数で指定された共有ライブラリ内のＡＰＩ関数をロードする。このため、スレッド１２０の実行時に共有ライブラリで定義したＡＰＩ関数を実行するため、スレッド１２０に含まれるＡＰＩ関数がＡＰＩ関数フックされる。
【００６３】
しかし、本実施形態におけるＡＰＩ関数フックを実現する方法は、ＯＳまたはＡＰＩ関数フック方法を限定するものではない。すなわち、スレッド１２０が実行される際に、処理される関数に新たな処理を追加できれば、いかなるＯＳまたは関数フック方法を用いてもよい。
【００６４】
また、後述する本実施形態において、ＡＰＩ関数フックを行うプログラムは標準Ｃライブラリ（ＧＬＩＢＣ）であるとして説明するが、ＡＰＩ関数フックを実現するプログラミング言語は、ＣおよびＣ＋＋に限定されるものではない。
【００６５】
また、前述および後述のスレッド１２０は、ゲートウェイ機器において実行されるが、本実施形態のスレッド１２０はゲートウェイ機器のみに限らず、いかなる計算機においても実行される。そして、いかなる計算機においても、本実施形態のスレッド監視方法が実行されうる。
【００６６】
図２は、本発明の第１の実施形態の機器４０のハードウェア構成を示すブロック図である。
【００６７】
本実施形態を実現する機器４０は、少なくとも一つのプロセッサ４００、メモリ４２０、および、ＮＩＦ４４０を備える。また、プロセッサ４００およびメモリ４２０は、バス４１０によって接続され、メモリ４２０およびＮＩＦ４４０はバス４３０によって接続される。
【００６８】
プロセッサ４００は、ＣＰＵ等の演算装置であり、ＯＳおよびアプリケーションプログラム等のソフトウェアを実行する。メモリ４２０は、プロセッサ４００がソフトウェア実行時に、プログラム実行バイナリおよびプログラムが使用するデータを格納するための記憶領域である。
【００６９】
ＮＩＦ４４０は、機器４０とは別の機器とパケットを送受信するための装置である。プロセッサ４００、メモリ４２０、およびＮＩＦは、バス４１０およびバス４３０によって接続されるため、互いに命令メッセージおよびデータを送信することが可能である。
【００７０】
なお、プロセッサ４００は、マルチタスク可能なマルチコアまたはマルチプロセッサであることが望ましいが、マルチタスクに対応したシングルコアまたはシングルプロセッサでも本発明を適用可能である。ここでマルチタスクとは、プロセッサ４００が複数の処理を切り替えながら複数の処理を実行する方法である。従って、マルチタスクが可能なハードウェアで稼働するソフトウェアであれば、本発明を適用することができる。
【００７１】
また、機器４０は、物理的に一つの計算機によって実装されてもよいし、少なくとも一つの計算機が提供する仮想的な計算機によって実装されてもよい。
【００７２】
図３は、本発明の第１の実施形態のＡＰＩ関数フック群５１０を示す説明図である。
【００７３】
本実施形態におけるＡＰＩ関数フック群５１０とは、ＡＰＩ関数フック対象として選択されたＡＰＩ関数の集合である。本実施形態において、監視対象となるプログラムの開発者または使用者が、あらかじめＡＰＩ関数フック群５１０に含まれるＡＰＩ関数を決定する。
【００７４】
本実施形態のスレッド監視の対象のプログラムが実行された場合、プロセッサ４００は、少なくとも一つのスレッドまたは少なくとも一つのプロセスによって、プログラムの処理を実行する。
【００７５】
スレッドプロシージャ５２０は、各スレッド１２０が生成されてから終了するまでの処理内容が、ソースコードにおいて定義されている箇所である。よって、スレッド１２０はスレッドプロシージャに従って動作する。
【００７６】
スレッドプロシージャ５２０には、複数のＡＰＩ関数が含まれる。第１の実施形態のスレッドプロシージャ５２０に含まれるＡＰＩ関数がメモリ４２０にロードされる際、ＬＤ＿ＰＲＥＬＯＡＤ環境変数５３０に共有ライブラリ５００を指定していると、共有ライブラリ５００に該当するＡＰＩ関数があればメモリ４２０にロードする。
【００７７】
共有ライブラリ５００は、ＡＰＩ関数フック群５１０を含む。このため、メモリ４２０にロードされるＡＰＩ関数が書き換わることによって、スレッドプロシージャ５２０に含まれる各ＡＰＩ関数は、ＡＰＩ関数フック群５１０が示す処理内容を実行する。
【００７８】
ただし、ＡＰＩ関数フックされるべきＡＰＩ関数は、スレッド監視の対象のプログラムを含むソフトウェアによって異なる。例えば、一般的に、ＡＰＩ関数フック群５１０として選択されるＡＰＩ関数は、定期的に実行されるＡＰＩ関数が望ましい。本実施形態のＡＰＩ関数フック群５１０は、開発者または使用者がスレッドプロシージャ５２０からフックされるＡＰＩ関数を選択することによって生成される。
【００７９】
開発者または使用者は、ＡＰＩ関数を選択するために、スレッドプロシージャ５２０からＡＰＩ関数を抜き出すためのスクリプトを用いてもよい。ＡＰＩ関数を抜き出すためのスクリプトは、簡易プログラミング言語によってコーディングされたプログラムである。
【００８０】
また、開発者または使用者は、定期的に実行されるＡＰＩ関数が既に取得されている場合、取得されたＡＰＩ関数をＡＰＩ関数フック群５１０に含めてもよい。
【００８１】
例えば、図１に示すゲートウェイ機器において、開発者または使用者は、スレッド１２０をＷＡＩＴ状態にするＡＰＩ関数をＡＰＩ関数フック群５１０として選択する。また例えば、スレッド１２０が正常時にｐｒｉｎｔｆ  ＡＰＩ関数によって文字列を表示し続ける場合、開発者または使用者は、ｐｒｉｎｔｆ  ＡＰＩ関数をＡＰＩ関数フック群５１０として選択する。
【００８２】
ただし、スレッド１２０が無限ループを含み、かつ、無限ループ内にフック対象のＡＰＩ関数がある場合、スレッド１２０は無限ループ内で生存報告２００をするため、スレッド１２０の異常動作として無限ループが検出されなくなる。従って、前述のプログラムは、無限ループを引き起こす可能性があるループ内のＡＰＩ関数を選択対象から除外し、ＡＰＩ関数フック群５１０を生成する。より具体的には、前述のプログラムは、ループ文の終了条件が他のスレッドによって満たされるループ文または条件を満たした時のみ、無限ループを抜け出すループ文を選択対象から除外する。
【００８３】
なお、ＡＰＩ関数フック群５１０に含まれるＡＰＩ関数の数は制限されない。
【００８４】
次に、共有ライブラリ５００の生成について説明する。共有ライブラリ５００は、ＯＳによって提供されるほか、開発者がソースコードをコンパイルすることによって生成される。従って、前述のプログラムが、ＡＰＩ関数フック群５１０に含まれるＡＰＩ関数を選択し、各ＡＰＩ関数がフックされた際の処理内容をＡＰＩ関数フック群５１０に定義した後、前述のプログラムは、ＡＰＩ関数フック群５１０をコンパイルすることによって共有ライブラリ５００を生成する。なお、生成される共有ライブラリ５００は、ＡＰＩ関数ごとに別々に生成されてもよい。
【００８５】
図３が示す共有ライブラリ５００において定義されるＡＰＩ関数の処理内容は、各ＡＰＩ関数が有する各ＡＰＩ関数固有の処理内容と、生存報告２００の処理内容とを含む。
【００８６】
例えば、スレッドプロシージャ５２０がｓｌｅｅｐ  ＡＰＩ関数を含み、ｓｌｅｅｐ  ＡＰＩ関数がＡＰＩ関数フック群５１０として選択された場合のｓｌｅｅｐ  ＡＰＩ関数の処理内容を図３に示す。スレッド１２０が実行され、ｓｌｅｅｐ  ＡＰＩ関数が実行された際、スレッド１２０は、ｓｌｅｅｐ  ＡＰＩ関数においてＡＰＩ関数フック５４０を行うことによって生存報告５５０を行う。これは、ＬＤ＿ＰＲＥＬＯＡＤ環境変数５３０によって、共有ライブラリ５００で定義したＡＰＩ関数がメモリ４２０にロードされているためである。そして、生存報告５５０が終了した後、スレッド１２０は、ｓｌｅｅｐ  ＡＰＩ関数固有の処理５６０を実行する。
【００８７】
一方、スレッドプロシージャ５２０がｐｒｉｎｔｆ  ＡＰＩ関数を含み、ｐｒｉｎｔｆ  ＡＰＩ関数はＡＰＩ関数フック群５１０として選択されていない場合のｐｒｉｎｔｆ  ＡＰＩ関数の処理内容を図３に示す。スレッド１２０が実行され、ｐｒｉｎｔｆ  ＡＰＩ関数が実行された際、スレッド１２０は、ｐｒｉｎｔｆ  ＡＰＩ関数固有の処理５７０を実行する。これは、共有ライブラリ５００が、ｐｒｉｎｔｆ  ＡＰＩ関数をフックし、ｐｒｉｎｔｆ  ＡＰＩ関数固有の処理以外の処理を行うことを定義されていないためである。
【００８８】
図３に示す生存報告５５０は、図１に示す生存報告２００の処理である。すなわち、図３に示す生存報告５５０は、生存フラグ１４０に１を格納する処理である。
【００８９】
本実施形態の生存フラグ１４０が１である場合、生存フラグ１４０は、スレッド１２０が生存していることを報告したことを示す。生存フラグ１４０が１以外である場合、生存フラグ１４０は、スレッド１２０が生存していることを報告していないことを示す。すなわち、生存フラグ１４０が１以外である場合、スレッド１２が異常である可能性が高い。
【００９０】
なお、図３におけるスレッド１２０は、生存フラグ１４０に１を格納する処理をＡＰＩ関数固有の処理を実行する前に行うが、本実施形態におけるスレッド１２０は、ＡＰＩ関数固有の処理を実行した後に生存フラグ１４０に１を格納してもよい。また、前述のプログラムは、ＡＰＩ関数フック時に追加される処理を少なくすることによって、ＡＰＩ関数フックによって生じる遅延を抑えることができる。
【００９１】
スレッド１２０がＡＰＩ関数がフックされた関数内からＡＰＩ関数固有の処理を実行するためには、スレッド１２０は、ｄｌｓｙｍ  ＡＰＩ関数によってＡＰＩ関数固有の処理を行う関数のアドレスを取得し、生存報告５５０を実行した後、取得されたアドレスを指定して呼びだすことによって、スレッド１２０は、ＡＰＩ関数固有の処理を実行する。ただし、ＡＰＩ関数固有の処理を実行する度にＡＰＩ関数のアドレスを取得すると効率が悪いため、スレッド１２０は、プロセスが終了するまで値を保持する静的な変数に保存しておくことによって効率を改善してもよい。
【００９２】
図３に示す共有ライブラリ５００は、ＡＰＩ関数名、ＡＰＩ関数の引数、追加される処理内容（生存報告５５０に対応）、および、ＡＰＩ関数固有の処理の４項目を含む。共有ライブラリ５００は、前述のＡＰＩ関数フック群５１０を生成するプログラムによって、定期的または開発者の指示によって、生成されてもよい。
【００９３】
ＡＰＩ関数フックによる生存報告５５０について説明する。前述のプログラムによって生成された共有ライブラリ５００を用いてＡＰＩ関数フックを有効にする場合、開発者は、ＬＤ＿ＰＲＥＬＯＡＤ環境変数５３０に共有ライブラリ５００へのパス（配置場所）を格納する。そして、パスを格納されたＬＤ＿ＰＲＥＬＯＡＤ環境変数５３０を用いてソフトウェアが起動した場合、起動されたソフトウェアに含まれるプロセスにおいてＡＰＩ関数フック５４０が有効になり、生存報告５５０が行われる。
【００９４】
なお、ＡＰＩ関数フックを有効にしたプロセスから子プロセスが起動された場合も、子プロセスにおいてＡＰＩ関数フックが有効になる。子プロセスへのＡＰＩ関数フックを無効にする場合、親プロセスが実行される関数は、環境変数を削除するｕｎｓｅｔｅｎｖ  ＡＰＩ関数を含み、親プロセスが実行された後、親プロセスは、ＬＤ＿ＰＲＥＬＯＡＤ環境変数５３０を無効にした状態において子プロセスを起動する。
【００９５】
このとき、本実施形態の機器４０は、予めＡＰＩ関数フックを有効にするプロセス数をメモリ４２０が保持する環境変数などに格納させ、ＡＰＩ関数フックの回数が環境変数に格納されたプロセス数を超えた場合、ＡＰＩ関数フックを無効にするプログラムを有することによって、ＡＰＩ関数フックの回数およびＡＰＩ関数フックの範囲を制御してもよい。
【００９６】
図４は、本発明の第１の実施形態の監視スレッド１１０が保持するデータおよびスレッド１２０が保持するデータを示す説明図である。
【００９７】
監視スレッド１１０は、メモリ４２０に監視対象リスト６１０を保持する。また、各スレッド１２０（１２０−１、１２０−２）は、メモリ４２０に監視情報６２０（６２０−１、６２０−２）を保持する。
【００９８】
監視対象リスト６１０は、各スレッドを一意に識別するための識別子と、各監視情報６２０がメモリ４２０のいずれの領域に格納されるかを示すポインタとを含む。監視スレッド１１０は、各スレッド１２０を監視する場合、監視対象リスト６１０を参照することによって、監視情報６２０から情報を取得する。
【００９９】
監視情報６２０は、各スレッド１２０を監視するために必要な情報を、スレッド１２０毎に保持する構造体である。監視情報６２０は、生存フラグ１４０および連続ＮＧ回数６２１を含む。
【０１００】
生存フラグ１４０は、図１に示す生存フラグ１４０と同じであり、スレッド１２０が正常状態であることを示す１ビットのフラグである。各スレッド１２０は、生存フラグ１４０を一つ保持する。生存フラグ１４０は、スレッド１２０および監視スレッド１１０によって更新される。
【０１０１】
連続ＮＧ回数６２１は、後述する異常動作検出８００の処理によって、スレッド１２０−１が無効であると連続して判定された場合に、無効であると判定された回数を含む。連続ＮＧ回数６２１は、監視スレッド１１０によって更新される。
【０１０２】
メモリ４２０が監視情報６２０を保持する方法としては、各スレッド１２０固有の記憶領域に各スレッド１２０に対応した監視情報６２０を保持する方法がある。また、メモリ４２０における各スレッド１２０間の共有メモリ領域に、監視情報６２０の構造体を含む一つのテーブルを保持し、このテーブルによって各監視情報６２０を一括管理する方法がある。
【０１０３】
ここで、スレッド１２０固有の記憶領域とは、アドレスが指定されなければ他のスレッドからアクセスされないため、各スレッド１２０が固有の記憶領域に監視情報６２０を保持した場合、他のスレッド１２０が誤って自らが保持する監視情報６２０にアクセスすることを防ぐことができる。
【０１０４】
また、各スレッド１２０間の共有メモリ領域とは、プロセス間で共有できる領域であり、プロセスに含まれる各スレッド１２０が共有メモリ領域に監視情報６２０を保持した場合、プロセスごとに監視することが可能になる。
【０１０５】
さらに、共有メモリ領域に監視情報６２０が格納された場合、監視情報６２０は、スレッド名などの情報を含むことによって、デバッグ時の情報として用いられてもよい。また、共有メモリ領域に監視情報６２０が格納された場合、監視情報６２０は、ロックハンドルを含むことによって、共有リソースのロック処理とアンロック処理とに用いられてもよい。ここで、ロックハンドルとはロック処理とアンロック処理とに必要なキーである。
【０１０６】
監視情報６２０は、スレッド１２０が生成される際に、スレッド１２０毎にメモリ４２０に生成される。プロセッサ４００は、スレッド１２０が生成された際に、スレッド１２０の処理によって監視情報６２０をメモリ４２０に生成する。
【０１０７】
本実施形態のスレッド１２０の動作には、メモリ４２０に監視情報６２０を生成する処理と、生成された監視情報６２０のメモリ４２０における位置を示すポインタを監視リスト６１０に登録する処理とが含まれる。これは、ｐｔｈｒｅａｄ＿ｃｒｅａｔｅ  ＡＰＩ関数（スレッド生成命令）にＡＰＩ関数フックを行い、生成および登録処理をあらかじめ設定することによって可能である。
【０１０８】
このため、スレッド１２０は、スレッド１２０が新たに生成された場合、スレッド１２０の監視情報６２０の位置を示すポインタと、スレッド１２０の識別子とを監視リスト６１０登録する。
【０１０９】
そして、監視スレッド１１０は、監視対象リスト６１０に従って異常動作検出を行う。生成された監視情報６２０は、監視情報６２０に対応するスレッド１２０がプロセッサ４００によって実行される間、メモリ４２０に保持される。そして、各スレッド１２０の処理の終了に従って、スレッド１２０は、監視情報６２０をメモリ４２０から削除し、監視対象リスト６１０からスレッド１２０のエントリを削除する。これは、ｐｔｈｒｅａｄ＿ｅｘｉｔ  ＡＰＩ関数（スレッド終了命令）にＡＰＩ関数フックを行い、削除処理を追加することで実現できる。
【０１１０】
また、本実施形態の監視スレッド１１０は、生成されたスレッド１２０を示す識別子と生成されたスレッド１２０を含むプロセスを示す識別子とを、メモリ４２０に格納する処理を含んでもよい。これによって、後述の処理によって、監視スレッド１１０がスレッド１２０を異常であると判定した場合、監視スレッド１１０は、スレッド１２０の識別子に基づいてスレッド１２０を含むプロセスの識別子をメモリ４２０から取得し、取得された識別子を用いて別プロセスからプロセスを再起動してもよい。
【０１１１】
また、本実施形態においてスレッド１２０は、監視情報６２０が削除された旨を監視スレッド１１０に通知してもよく、また、監視情報６２０が削除された旨を監視スレッド１１０に通知しなくてもよい。
【０１１２】
監視情報６２０が削除されたことが通知されない場合においても、監視対象リスト６１０に含まれる各エントリは、監視情報６２０が削除された時点でスレッド１２０によって削除されるため、監視スレッド１１０はスレッド１２０への異常検出を行わない。
【０１１３】
図５は、本発明の第１の実施形態の生存報告２００および異常動作検出８００を示すシーケンス図である。
【０１１４】
図５は、スレッド１２０による生存報告２００と監視スレッド１１０による異常動作検出８００とによって行われるスレッド監視の処理を示す。
【０１１５】
スレッド１２０が実行される間、スレッド１２０が実行するＡＰＩ関数のうち、ＡＰＩ関数フックされるＡＰＩ関数が、監視情報６２０に生存報告２００を行う。具体的には、ＡＰＩ関数フックされるＡＰＩ関数が、生存フラグ１４０に１を格納する。
【０１１６】
一方で、監視スレッド１１０は、監視対象リスト６１０を用いて監視情報６２０を参照することによって、異常動作検出８００を実行する。監視スレッド１１０は、監視対象リスト６１０のポインタが示す監視情報６２０をすべて参照することによって、監視対象リスト６１０に識別子が格納されるすべてのスレッド１２０に異常動作検出８００を行う。
【０１１７】
監視スレッド１１０は、監視対象リスト６１０に識別子が格納されていないスレッド１２０に、異常動作検出８００を行えない。このため、実行中のスレッド１２０を示す識別子は、監視対象リスト６１０に常に格納される必要がある。本実施形態において、監視対象リスト６１０に実行中のスレッド１２０を示す識別子を格納する方法は、スレッド１２０が生成された際に監視対象リスト６１０に識別子が格納され、スレッド１２０が終了した際に監視対象リスト６１０から削除することによって実現される。
【０１１８】
なお、監視対象リスト６１０のデータ構造はリスト構造に限定するものではなく、テーブル構造でもよい。また、図５に示す異常動作検出８００は、一定の監視周期によって実行されるが、本実施形態の異常動作検出８００は、開発者または使用者等が監視スレッド１１０に対応するコマンドを実行することによって、不定期または任意のタイミングによって実行されてもよい。
【０１１９】
図６は、本発明の第１の実施形態の監視スレッド１１０による異常動作検出８００を示すフローチャートである。
【０１２０】
所定の監視周期において監視スレッド１１０が異常動作検出８００を開始する（８０１）。監視スレッド１１０は、開発者または使用者からの指示によって、異常動作検出８００を実行してもよい。
【０１２１】
なお、異常動作検出８００は、監視対象リスト６１０に格納されるすべての監視情報６２０に行われるが、図６に示す処理は、一つの監視情報６２０に行われる処理を示す。複数の監視情報６２０に異常動作検出８００が行われる場合、監視スレッド１１０は、図６に示す処理を複数の監視情報６２０に対して並列に行ってもよいし、複数の監視情報６２０に順次行ってもよい。
【０１２２】
ステップ８０１の後、監視スレッド１１０は、監視対象リスト６１０を用いてスレッド１２０の監視情報６２０を参照する。そして、各スレッド１２０に本実施形態の生存確認３００を実行し、スレッド１２０の生存確認３００の結果が有効か否かを判定する（８１０）。
【０１２３】
ステップ８１０において行われる生存確認３００の処理の流れは、図１２に示す生存確認３００の処理の流れと同様である。しかし、本実施形態の生存確認３００のステップ３３０において、監視スレッド１１０は、生存フラグ１４０が有効であると判定する。また、本実施形態の生存確認３００のステップ３４０において、監視スレッド１１０は、生存フラグ１４０が無効であると判定する。これは、異常動作検出８００における生存確認３００は、スレッド１２０が正常であるか否かを判定する処理ではないためである。
【０１２４】
ステップ８１０において、生存確認３００の結果が有効であると判定された場合、生存フラグ１４０はスレッド１２０が生存報告２００を正常に行っていることを示す。このため、監視スレッド１１０は、連続ＮＧ回数６２１に０を格納する（８２０）。
【０１２５】
そして、ステップ８２０の後、監視スレッド１１０は、スレッド１２０が正常であると判定する（８６０）。連続ＮＧ回数６２１は、監視周期ごとに実行されるステップ８１０において、生存フラグ１４０が無効であると連続して判定された場合に、無効と判定された回数を示す。
【０１２６】
ステップ８１０において、生存確認３００の結果が無効であると判定された場合、監視スレッド１１０は、スレッド１２０がＮＧであると判定する（８３０）。ステップ８３０の後、連続ＮＧ回数６２１に１を加算する（８４０）。例えば、二つ前の監視周期におけるステップ８１０において有効と判定され、一つ前の監視周期におけるステップ８１０において無効と判定された生存フラグ１４０を、監視スレッド１１０がステップ８１０において無効と判定する場合、ステップ８４０の後の連続ＮＧ回数６２１には、２が格納される。
【０１２７】
ステップ８４０の後、監視スレッド１１０は、連続ＮＧ回数６２１が示す値と所定の保護回数とを比較し、連続ＮＧ回数６２１が示す値が所定の保護回数以下であるか否かを判定する（８５０）。
【０１２８】
ここで、保護回数とは、各監視周期におけるステップ８３０においてＮＧであると連続して判定された場合、すなわち、各監視周期におけるステップ８１０において無効であると連続して判定された場合、監視スレッド１１０がスレッド１２０を異常と判定しない連続ＮＧ回数６２１の上限値である。監視スレッド１１０は、連続ＮＧ回数６２１の値が保護回数の値を超えるまで、スレッド１２０を異常と判定しない。
【０１２９】
例えば、保護回数が１である場合、ステップ８３０における判定が２回連続した後、監視スレッド１１０は、スレッド１２０が異常な動作を行っていると判定（異常動作検出）する。
【０１３０】
ステップ８５０において、連続ＮＧ回数６２１が所定の保護回数以下であると判定された場合、監視スレッド１１０は、ステップ８６０を実行することによって、スレッド１２０が正常であると判定する。
【０１３１】
ステップ８５０において、連続ＮＧ回数６２１が所定の保護回数よりも大きいと判定された場合、監視スレッド１１０は、スレッド１２０が異常であると判定する（８７０）。ステップ８６０またはステップ８７０の後、監視スレッド１１０は、スレッド１２０への異常動作検出８００を終了する（８８０）。
【０１３２】
前述の保護回数は、本実施形態のスレッド監視の処理におけるパラメータとしてあらかじめ開発者または使用者によって、機器４０のメモリ４２０に格納される。保護回数を１以上の値とすることによって、生存報告２００が監視周期内で一度も実行されない場合、開発者または使用者は、スレッド１２０の異常動作の誤判定を防ぐことができる。
【０１３３】
また、連続ＮＧ回数６２１が保護回数以下である場合、監視スレッド１１０は、スレッド１２０がＮＧと判定されたことをログに出力してもよい。これは、開発者または使用者が、出力されたログを参照することによって、スレッド１２０のデバッグまたは性能改善を行うことができるためである。
【０１３４】
スレッド１２０において無限ループまたはデッドロックが発生した場合、スレッド１２０は生存報告２００を行わない。このため、無限ループまたはデッドロックが発生した時点から、異常動作検出８００が２回以上実行された場合、ステップ８１０において生存フラグ１４０は必ず０である。このため、監視スレッド１１０は、無限ループまたはデッドロックが発生したスレッド１２０がＮＧであると判定できる。さらに、連続ＮＧ回数６２１が保護回数を超えた場合、監視スレッド１１０は、スレッド１２０の異常を検出できる。
【０１３５】
前述の図６に示す処理によって、監視スレッド１１０はスレッド１２０の状態が正常であるか否かを判定できる。
【０１３６】
なお、本実施形態において、開発者または使用者が監視スレッド１１０を生成および実行するための定義を共有ライブラリ５００に設定することによって、監視スレッド１１０が生成されてもよい。これによって、機器４０が有するプログラムが監視スレッド１１０を提供していない場合も、共有ライブラリ５００を変更するのみで監視スレッド１１０を生成できるため、容易に本実施形態のスレッド監視方法を機器４０に実装することができる。
【０１３７】
また、本実施形態は、監視方法を監視スレッド１１０による監視方法に限定するものではなく、前述の図６および図１２の処理を実行するためのプロセスまたはスレッドが実行されれば、いかなる監視方法を用いてもよい。
【０１３８】
監視スレッド１１０が、スレッド１２０を異常と判定した場合の処理について説明する。スレッド１２０において無限ループまたはデッドロックが発生した場合、異常であると判定されたスレッド１２０を含むプロセスは、一般的に、スレッド１２０が異常のまま継続する。しかし、異常であると判定されたスレッド１２０が含まれるプロセスを継続しても、スレッド１２０が無限ループまたはデッドロックから自然に回復することはない。
【０１３９】
このため、監視スレッド１１０は、スレッド１２０の異常を検出した場合、スレッド１２０、または、スレッド１２０が含まれるプロセスに、適切な処理を実行してもよい。ここで、適切な処理とは、異常が検出されたスレッド１２０の情報をログに残し、スレッド１２０が含まれるプロセスを終了してから、スレッド１２０が含まれるプロセスを再起動する。異常が検出されたスレッド１２０を含むプロセスを終了することによって、監視スレッド１１０は、スレッド１２０が利用中のメモリ４２０またはロックの解放漏れを、防ぐことができる。
【０１４０】
また、監視スレッド１１０は、異常が検出されたスレッド１２０を終了させてから、再度スレッド１２０を生成してもよい。これによって、プロセスを終了させずに済むため、監視スレッド１１０は、本実施形態のスレッド監視の対象であるプログラムが提供するサービスへの影響を抑えることができる。
【０１４１】
なお、監視スレッド１１０は、図６に示す処理によって異常と判定されたスレッド１２０の識別子に基づいて、その異常と判定されたスレッド１２０を含むプロセスの識別子を、メモリ４２０から読み出すことが可能であり、読み出されたプロセスの識別子を別プロセスに通知することで、スレッド１２０を含むプロセスを再起動する。
【０１４２】
第１の実施形態によれば、スレッド１２０が、無限ループ、デッドロック、またはロック処理を伴わない停止状態であることによって、正常に動作していない場合に、スレッド１２０が異常に動作していることを検出することができる。
【０１４３】
また、第１の実施形態によれば、ＡＰＩ関数フックによってスレッド１２０を監視するための生存フラグ１４０を更新することによって、カーネル１００の変更、スレッド監視の対象であるプログラムのソースコードの変更およびリコンパイル、または、スレッド監視の対象であるプログラムのコンパイル済み実行ファイルへの変更を伴わないスレッド監視方法を実現できる。
【０１４４】
また、第１の実施形態によれば、既存のＡＰＩ関数の処理に生存フラグ１４０が追加されるのみであるため、スレッド監視の対象のプログラムの処理を大きく遅延させることがない。
【０１４５】
（第２の実施形態）
前述の第１の実施形態においては、例えば、図１に示すステップ１２２における命令メッセージのＷＡＩＴ状態が監視周期よりも長い場合、監視スレッド１１０は、正常なＷＡＩＴ状態を異常として誤判定する可能性がある。第２の実施形態の方法は、例えば、スレッド１２０をＷＡＩＴ状態にする処理を含むＡＰＩ関数など、処理が監視周期よりも長い時間かかるＡＰＩ関数を監視するための方法である。
【０１４６】
図７は、本発明の第２の実施形態の異常動作検出の処理を示すシーケンス図である。
【０１４７】
図７は、スレッド１２０による監視情報６２０の更新処理９００、および、更新処理９０２を示し、監視スレッド１１０による異常動作検出９１０〜異常動作検出９１２を示す。また、ＷＡＩＴ状態９０１は、本実施形態のＡＰＩ関数フックされるＡＰＩ関数がＷＡＩＴ状態である期間を示す。
【０１４８】
また、第２の実施形態の監視情報６２０は、生存フラグ１４０、連続ＮＧ回数６２１および処理待ち数６２２を含む。第２の実施形態の生存フラグ１４０および連続ＮＧ回数６２１は、第１の実施形態の生存フラグ１４０および連続ＮＧ回数６２１と同じである。処理待ち数６２２は、スレッド１２０がＷＡＩＴ状態９０１であるか否かを判定するための値を格納する領域である。
【０１４９】
更新処理９００、ＷＡＩＴ状態９０１および更新処理９０２は、本実施形態のＡＰＩ関数フックされる一つのＡＰＩ関数の処理である。スレッド１２０は、ＡＰＩ関数フックされるＡＰＩ関数がＷＡＩＴ状態９０１となる前に、更新処理９００によって生存フラグ１４０に１を格納する。すなわち、更新処理９００は、第１の実施形態における生存報告２００の処理を含む。
【０１５０】
一方、監視スレッド１１０は、更新処理９００後の異常動作検出９１０において生存フラグ１４０を参照し、スレッド１２０が正常であると判定する。そして、スレッド１２０は、更新処理９００後にＷＡＩＴ状態９０１となる。第２の実施形態におけるＷＡＩＴ状態９０１は、監視スレッド１１０が保持する監視周期よりも長い。
【０１５１】
ここで、異常動作検出９１０〜異常動作検出９１２が、第１の実施形態の異常動作検出８００と同じ処理を行う場合、監視スレッド１１０は、異常動作検出９１１において、生存フラグ１４０に０が格納されているため、ＷＡＩＴ状態９０１であるスレッド１２０を異常であると判定する。ＷＡＩＴ状態９０１は、スレッド１２０の異常状態ではないため、異常動作検出９１１によってスレッド１２０を異常と判定する結果は、誤りである。
【０１５２】
そこで、第２の実施形態における監視スレッド１１０は、異常動作検出処理において監視情報６２０が保持する処理待ち数６２２を参照することによって、正常なＷＡＩＴ状態９０１を異常と誤判定しない。第２の実施形態のスレッド１２０は、ＷＡＩＴ状態９０１になる前後において、監視情報６２０の処理待ち数６２２を更新する。
【０１５３】
第２の実施形態の機器４０のハードウェア構成は、図２に示す第１の実施形態のハードウェア構成と同じく、プロセッサ４００、メモリ４２０、ＮＩＦ４４０、バス４１０、および、バス４３０を備える。
【０１５４】
第２の実施形態におけるＡＰＩ関数フック群５１０の決定方法について説明する。第１の実施形態と同じく、本実施形態のスレッド監視の対象のプログラム、すなわち、スレッド１２０を生成するプログラムの開発者または使用者がＡＰＩ関数フック群５１０に含まれるＡＰＩ関数を選択する。また、開発者または使用者が、第１の実施形態と同じく、スレッドプロシージャ５２０からＡＰＩ関数を抜き出すためのスクリプトを用いて、ＷＡＩＴ状態９０１になるＡＰＩ関数を取得し、取得されたＡＰＩ関数をＡＰＩ関数フック群５１０に含めてもよい。
【０１５５】
第２の実施形態においてＷＡＩＴ状態９０１になるＡＰＩ関数には、他のプロセスまたはスレッドから信号を受信するまで、スレッド１２０を停止させるタイマ付き状態同期関数が含まれる。また、使用者からの入力を待つ入力待ち関数、および、指定された時間の間停止するスリープ関数が含まれる。
【０１５６】
第２の実施形態におけるスレッド１２０は、ＷＡＩＴ状態９０１になるＡＰＩ関数にＡＰＩ関数フックする。ここで、ロック取得関数も、ＷＡＩＴ状態９０１になるＡＰＩ関数であるが、一方で、ロック取得関数はデッドロックを引き起こす可能性があるＡＰＩ関数である。
【０１５７】
このため、開発者または使用者は、ＡＰＩ関数フック群５１０に含めることを禁止するためのリスト（ＡＰＩ関数フック禁止リスト）に、ロック取得関数をあらかじめ格納してもよい。そして、開発者または使用者が、ＡＰＩ関数フック禁止リストが示すＡＰＩ関数以外のＡＰＩ関数をＡＰＩ関数フック群５１０に選択することによって、デッドロックにおける監視スレッド１１０の状態の誤判定を回避できる。
【０１５８】
なお、第２の実施形態のＡＰＩ関数フック群５１０には、第１の実施形態と同じくＷＡＩＴ状態９０１にならないＡＰＩ関数が選択されてもよい。ＡＰＩ関数フック群５１０に、ＷＡＩＴ状態９０１になるＡＰＩ関数と、ＷＡＩＴ状態９０１にならないＡＰＩ関数とが含まれる場合、各ＡＰＩ関数がＷＡＩＴ状態９０１になるか否かを示すリストをあらかじめ保持し、前述のリストを参照することによって、各ＡＰＩ関数に追加する処理を決定してもよい。これによって、本実施形態の機器４０は、第１の実施形態と第２の実施形態とを実装することができる。
【０１５９】
次に、共有ライブラリ５００の生成方法について説明する。第１の実施形態と同じく、開発者または使用者が、ＡＰＩ関数フック群５１０に、各ＡＰＩ関数の処理内容として、ＡＰＩ関数固有の処理と、生存報告２００の処理と、処理待ち数６２２を更新する処理とを格納する。また、ＡＰＩ関数フック群５１０の処理内容は、各処理が実行される順番を示す。これによって、共有ライブラリ５００が生成される。
【０１６０】
ＡＰＩ関数フック群５１０の処理内容に含まれる処理待ち数６２２を更新する処理は、処理待ち数６２２をスレッド１２０がＷＡＩＴ状態９０１である間増加させる処理を追加である。
【０１６１】
具体的には、スレッド１２０が、処理待ち数６２２の値を０に初期化してから処理待ち数６２２に１を加算する処理と、生存フラグ１４０に１を格納する処理とを実行し、その後、ＷＡＩＴ状態９０１になるＡＰＩ関数固有の処理を実行するように、開発者または使用者はＡＰＩ関数フック群５１０を生成する。さらに、スレッド１２０が、ＷＡＩＴ状態９０１になるＡＰＩ関数固有の処理の終了直後に処理待ち数６２２から１を減算する処理を実行するように、開発者または使用者は、ＡＰＩ関数フック群５１０を生成する。
【０１６２】
これによって、図７に示すＷＡＩＴ状態９０１の開始直前にスレッド１２０は更新処理９００を実行し、処理待ち数６２２に１を加算する。また、ＷＡＩＴ状態９０１の終了直後にスレッド１２０は更新処理９０２を実行し、処理待ち数６２２を０にする。このため、監視スレッド１１０は、異常動作検出９１１において処理待ち数６２２が０より大きい場合、スレッド１２０がＷＡＩＴ状態９０１であると判定できる。
【０１６３】
次に、第２の実施形態におけるＡＰＩ関数フックによる監視情報６２０の更新処理について説明する。第１の実施形態と同じく、開発者または使用者によって生成された共有ライブラリ５００のパスがＬＤ＿ＰＲＥＬＯＡＤ環境変数５３０に格納された場合、スレッド１２０を生成するプログラムの実行ファイルが起動された後、ＡＰＩ関数フック群５１０に含まれるＡＰＩ関数のフックが有効になる。
【０１６４】
スレッド１２０が実行されると、ＡＰＩ関数フックによって更新処理９００および更新処理９０２が実行され、スレッド１２０はＡＰＩ関数固有の処理の直前に処理待ち数６２２に１を加算し、ＡＰＩ関数固有の処理の直後に処理待ち数６２２から１を減算する。
【０１６５】
次に、異常動作検出９１０〜異常動作検出９１２について説明する。異常動作検出９１０〜異常動作検出９１２は、図６に示す第１の実施形態の異常動作検出８００と同様である。しかし、図６に示すステップ８１０において、第２の実施形態の生存確認３００と、第１の実施形態の生存確認３００とが異なる。
【０１６６】
図８は、本発明の第２の実施形態の生存確認の処理を示すフローチャートである。
【０１６７】
図８に示す処理は、第２の実施形態における図６に示す処理のステップ８１０に含まれる。そして、第１の実施形態のステップ８１０における生存確認３００に相当する。
【０１６８】
第２の実施形態の監視スレッド１１０がステップ８１０によって異常動作検出処理を開始した後、監視スレッド１１０は生存確認処理を開始する（１０００）。監視スレッド１１０は、スレッド１２０に対応する処理待ち数６２２に格納される値が０より大きいか否かを判定する（１０１０）。
【０１６９】
ステップ１０１０において処理待ち数６２２に格納される値が０より大きいと判定された場合、スレッド１２０はＷＡＩＴ状態９０１である。このため、スレッド１２０は正常と判定することが可能であり、監視スレッド１１０はスレッド１２０を監視する必要がないため、生存確認の結果を有効と判定する（１０２０）。
【０１７０】
ステップ１０１０において処理待ち数６２２に格納される値が０であると判定された場合、スレッド１２０はＷＡＩＴ状態９０１ではない。このため、監視スレッド１１０は、スレッド１２０を監視するため、生存フラグ１４０に格納された値が１であるか否かを判定する（１０３０）。
【０１７１】
ステップ１０３０において生存フラグ１４０に格納される値が１であると判定された場合、スレッド１２０は正常に実行されている。このため、監視スレッド１１０は、生存フラグ１４０に０を格納し（１０４０）、ステップ１０２０を実行する。
【０１７２】
ステップ１０３０において生存フラグ１４０に格納される値が１ではないと判定された場合、スレッド１２０は異常である可能性がある。このため、監視スレッド１１０は、生存確認の結果を無効と判定する（１０５０）。
【０１７３】
ステップ１０２０またはステップ１０５０の後、監視スレッド１１０はステップ８１０に含まれる生存確認の処理を終了する（１０６０）。
【０１７４】
図６および図８に示す処理によって、図７に示す異常動作検出９１１を行う場合、監視スレッド１１０は、処理待ち数６２２に１が格納されているため、スレッド１２０が正常であると判定する。
【０１７５】
そして、図６および図８に示す処理によって、図７に示す異常動作検出９１２を行う場合、監視スレッド１１０は、処理待ち数６２２に０が格納されており、かつ、生存フラグ１４０に１が格納されているため、スレッド１２０が正常であると判定する。これは、図８に示す処理によって、生存フラグ１４０は、ＷＡＩＴ状態９０１の間、１を示す値を保持し続けるためである。
【０１７６】
第２の実施形態によれば、監視情報６２０が処理待ち数６２２を保持することによって、監視スレッド１１０は、例えば、スレッド１２０をＷＡＩＴ状態９０１にするＡＰＩ関数などのＡＰＩ関数が、監視周期よりも長い時間処理する場合においても、ＡＰＩ関数の処理中はスレッド１２０を正常であると判定することができる。また、処理待ち数６２２を生存フラグ１４０を参照するよりも先に参照することによって、ＷＡＩＴ状態９０１中は、生存フラグ１４０が０に更新されない。この結果、監視スレッド１１０がＷＡＩＴ状態９０１終了直後に異常動作検出９１２を行っても、生存フラグ１４０には１が格納されているため、監視スレッド１１０はスレッド１２０を正常と判定することができる。
【０１７７】
第２の実施形態の監視スレッド１１０が、スレッド１２０を異常であると判定した場合の処理は、第１の実施形態と同じであり、スレッド１２０またはスレッド１２０が含まれるプロセスを再起動する。
【０１７８】
第２の実施形態によれば、ＷＡＩＴ状態となるＡＰＩ関数をフックすることによって、カーネル１００の変更、スレッド監視の対象であるプログラムのソースコードの変更およびリコンパイル、または、スレッド監視の対象であるプログラムのコンパイル済み実行ファイルへの変更を伴わないスレッド監視方法を実現できる。
【０１７９】
また、第２の実施形態によれば、監視スレッド１１０は、ＷＡＩＴ状態が監視周期よりも長い場合にも、正常なＷＡＩＴ状態を異常として誤判定しない。
【０１８０】
また、第２の実施形態によれば、既存のＡＰＩ関数の処理に処理待ち数６２２が追加されるのみであるため、スレッド監視の対象のプログラムの処理を大きく遅延させることがない。
【０１８１】
なお、開発者または使用者は、ＡＰＩ関数フック群５１０の生成処理、ＬＤ＿ＰＲＥＬＯＡＤ環境変数５３０に共有ライブラリ５００の識別子を設定する処理、および、監視スレッド１１０を実行する処理等の、第１の実施形態および第２の実施形態を行うための設定処理を、機器４０が備えるキーボード等の入力装置を介して行ってもよい。
【０１８２】
また、開発者または使用者は、前述の第１の実施形態および第２の実施形態を行うための設定処理を行うプログラムを生成し、他の計算機から機器４０へＮＩＦ４４０を介して、生成されたプログラムを送信してもよい。そして、機器４０に、送信されたプログラムによって第１の実施形態および第２の実施形態を行うための設定をさせてもよい。
【０１８３】
また、開発者または使用者は、前述の第１の実施形態および第２の実施形態を行うための設定処理を行うプログラムを、計算機によって読み取り可能な非一時的記憶媒体によって、機器４０に入力してもよい。
【０１８４】
また、第１の実施形態および第２の実施形態において、前述の監視スレッド１１０は、メモリ４２０が保持する監視プログラムを実行するためのスレッドであるが、他の機能を有するプログラムに監視スレッド１１０の機能を含められることによって、実行されてもよい。
【０１８５】
（第３の実施形態）
前述した第１の実施形態と第２の実施形態とにおいては、ＡＰＩ関数フック群５１０をスレッド監視の対象であるプログラムの開発者または使用者によって予め選択する必要があった。しかし、第３の実施形態において、定期的または指定された時刻に、ＡＰＩ関数の使用状況に基づいてＡＰＩ関数フック群５１０が自動的に決定される。
【０１８６】
第３の実施形態における機器４０のハードウェア構成は、図２に示す第１の実施形態の機器４０と同じである。また、第３の実施形態のプロセッサ４００は、第１の実施形態および第２の実施形態と同じく、図４に示す監視スレッド１１０およびスレッド１２０を実行する。
【０１８７】
図９は、本発明の第３の実施形態のＡＰＩ関数フック群５１０を決定する処理を示す説明図である。
【０１８８】
ＡＰＩ関数フック群５１０を決定するために、スレッド１２０は、ＡＰＩ関数の使用状況を示す統計情報１１４０を更新する。第３の実施形態において、スレッド１２０は、図９に示す統計情報１１４０を取得するための共有ライブラリ１１００とＬＤ＿ＡＵＤＩＴ機能とを利用し、各ＡＰＩ関数の統計情報１１４０を取得する。
【０１８９】
第３の実施形態におけるＬＤ＿ＡＵＤＩＴ機能とは、第３の実施形態のＬＤ＿ＡＵＤＩＴ環境変数１１２０が保持する機能である。第３の実施形態のＬＤ＿ＡＵＤＩＴ環境変数１１２０には、共有ライブラリ１１００を読み出すための識別子が格納され、共有ライブラリ１１００には、ＡＰＩ関数フックされた際の処理内容が含まれる。ＬＤ＿ＡＵＤＩＴ環境変数１１２０は、第３の実施形態のスレッド監視の対象であるプログラムに含まれるＡＰＩ関数をメモリ４２０にロードする際に読み出される。
【０１９０】
そして、共有ライブラリ１１００を読み出すための識別子が開発者または使用者によってＬＤ＿ＡＵＤＩＴ環境変数１１２０に格納された後、スレッド監視の対象であるプログラムによって実行されるすべてのＡＰＩ関数は、メモリ４２０にロードされる際、共有ライブラリ１１００で指定した処理を追加してロードする。なお、スレッドプロシージャ５２０には、第１の実施形態と同じく、スレッド監視の対象であるプログラムに含まれるＡＰＩ関数が含まれる。
【０１９１】
共有ライブラリ１１００には、ＡＰＩ関数名を統計情報１１４０に出力する処理を示す処理内容１１１０が格納される。このため、各スレッド１２０によって実行されるＡＰＩ関数は、メモリ４２０にロードされる際に処理が追加されることによって、ＡＰＩ関数固有の処理と、ＡＰＩ関数名を統計情報１１４０に出力する処理とを実行する。
【０１９２】
例えば、スレッドプロシージャ５２０がｓｌｅｅｐ  ＡＰＩ関数を含む場合、プロセッサ４００がｓｌｅｅｐ  ＡＰＩ関数固有の処理５６０を実行する前に、スレッド１２０は、メモリ４２０にロードされた追加処理を実行することによって、ｓｌｅｅｐ  ＡＰＩ関数の処理５６０にＡＰＩ関数フック１１２１処理を行う。そして、ＡＰＩ関数フック１１２１がされた後、スレッド１２０はＡＰＩ関数名（すなわち、「ｓｌｅｅｐ」）を統計情報１１４０に出力する処理内容１１１０が示す処理を実行する。
【０１９３】
従って、共有ライブラリ１１００が生成され、ＬＤ＿ＡＵＤＩＴ環境変数１１２０に共有ライブラリ１１００を示す識別子が格納された後に、スレッド監視の対象であるプログラムを起動した場合、統計情報１１４０には、実行されたＡＰＩ関数の使用状況が格納される。
【０１９４】
統計情報１１４０は、メモリ４２０に保持されるデータの集合であり、ＡＰＩ関数名１１４１と使用回数１１４２とを保持する。ＡＰＩ関数名１１４１は、処理内容１１１０の処理によって入力されたＡＰＩ関数名を含む。使用回数１１４２は、ＡＰＩ関数名１１４１が示すＡＰＩ関数が、実行された回数を含む。
【０１９５】
なお、スレッド１２０は、処理内容１１１０が示す処理において、統計情報１１４０に出力するＡＰＩ関数名が統計情報１１４０に既に含まれているか否かを判定する。そして、スレッド１２０は、統計情報１１４０に出力するＡＰＩ関数名が統計情報１１４０に既に含まれていた場合、スレッド１２０によって出力されるＡＰＩ関数名をＡＰＩ関数名１１４１に含むエントリの使用回数１１４２に１を加算する。
【０１９６】
また、統計情報１１４０に出力するＡＰＩ関数名が統計情報１１４０に含まれていない場合、スレッド１２０は、処理内容１１１０が示す処理において、統計情報１１４０に新たなエントリを生成し、新規ＡＰＩ関数としてＡＰＩ関数名を生成されたエントリに格納する。そして、生成されたエントリの使用回数１１４２に１を格納する。これによって、統計情報１１４０は、ＡＰＩ関数が実行された回数を、ＡＰＩ関数毎に保持できる。
【０１９７】
次に、ＡＰＩ関数決定プログラム１１７０は、更新された統計情報１１４０からスレッド監視処理におけるＡＰＩ関数フック群５１０を決定する。ＡＰＩ関数決定プログラム１１７０は、機器４０がメモリ４２０に保持するプログラムであり、プロセッサ４００によって実行される。ＡＰＩ関数決定プログラム１１７０は、ＡＰＩ関数決定プログラム１１７０の処理が可能であれば、別の機能を含むプログラムによって実装されても、複数のプログラムによって実装されてもよい。
【０１９８】
ここで、ＡＰＩ関数決定プログラム１１７０は、統計情報１１４０に含まれるＡＰＩ関数名１１４１をすべてＡＰＩ関数フック群５１０に決定してもよい。しかし、ＡＰＩ関数決定プログラム１１７０がデッドロックを起こすＡＰＩ関数を決定した場合、監視スレッド１１０がスレッド１２０の状態を正確に判定できなくなる可能性がある。
【０１９９】
そこで、第３の実施形態において、機器４０はメモリ４２０にＡＰＩ関数フック禁止リスト１１３０を保持する。ＡＰＩ関数フック禁止リスト１１３０には、開発者または使用者によって、ＡＰＩ関数フック群５１０として決定されてはいけないＡＰＩ関数を示す値が格納される。
【０２００】
ＡＰＩ関数決定プログラム１１７０は、ＡＰＩ関数フック禁止リスト１１３０および統計情報１１４０を参照し、ＡＰＩ関数名１１４１が示すＡＰＩ関数のうち、ＡＰＩ関数フック禁止リスト１１３０に含まれていないＡＰＩ関数を、ＡＰＩ関数フック群５１０に決定する。例えば、ＡＰＩ関数フック禁止リスト１１３０にｃｏｎｄ＿ｗａｉｔ  ＡＰＩ関数が格納される場合、ＡＰＩ関数決定プログラム１１７０は、ＡＰＩ関数名１１４１にｃｏｎｄ＿ｗａｉｔ  ＡＰＩ関数が含まれていても、ｃｏｎｄ＿ｗａｉｔ  ＡＰＩ関数をＡＰＩ関数フック群５１０に決定しない。
【０２０１】
第３の実施形態の共有ライブラリ５００およびＡＰＩ関数フック群５１０は、第１の実施形態および第２の実施形態の共有ライブラリ５００およびＡＰＩ関数フック群５１０と同じである。
【０２０２】
ＡＰＩ関数フック禁止リスト１１３０は、開発者または使用者によって生成される。デッドロックを引き起こす可能性があるＡＰＩ関数を、開発者または使用者は事前に取得できるため、開発者または使用者が、本実施形態のスレッド監視の対象であるプログラムのソースコードを閲覧できない場合も、開発者または使用者は、ＡＰＩ関数フック禁止リスト１１３０を生成できる。
【０２０３】
図１０は、本発明の第３の実施形態のＡＰＩ関数決定プログラム１１７０の処理を示すフローチャートである。
【０２０４】
図１０は、統計情報１１４０からＡＰＩ関数フック群５１０を決定する処理を示す。
【０２０５】
まず、ＡＰＩ関数決定プログラム１１７０は、定期的、または、開発者もしくは使用者等の指示に従って、ＡＰＩ関数フック群５１０を決定する処理を開始する（１２００）。
【０２０６】
ステップ１２００の後、ＡＰＩ関数決定プログラム１１７０は、統計情報１１４０の一つのエントリからＡＰＩ関数Ｘを抽出する（１２１０）。なお、ステップ１２１０におけるＡＰＩ関数決定プログラム１１７０は、ＡＰＩ関数フック群５１０にまだ含まれていない関数であれば、統計情報１１４０のいかなるＡＰＩ関数を抽出してもよい。
【０２０７】
ステップ１２１０の後、ＡＰＩ関数決定プログラム１１７０は、ステップ１２１０によって統計情報１１４０からＡＰＩ関数Ｘが抽出されたか否かを判定する（１２２０）。ＡＰＩ関数Ｘが抽出されない場合、ＡＰＩ関数フック群に決定するべきＡＰＩ関数がないため、ＡＰＩ関数決定プログラム１１７０は、図１０に示す処理を終了する。
【０２０８】
ステップ１２２０において、ＡＰＩ関数Ｘが抽出されたと判定された場合、ＡＰＩ関数決定プログラム１１７０は、ＡＰＩ関数ＸをＡＰＩ関数名１１４１に含む統計情報１１４０のエントリの使用回数１１４２を抽出し、抽出された使用回数１１４２が所定の閾値Ｔより大きいか否か判定する（１２３０）。ここで、所定の閾値Ｔとは統計情報１１４０に含まれるＡＰＩ関数を、ＡＰＩ関数フック群５１０に含めるか否かを判定するための閾値であり、ここでは統計情報１１４０の各エントリの使用回数１１４２の値の平均値である。
【０２０９】
ステップ１２３０において、抽出された使用回数１１４２が所定の閾値Ｔ以下であると判定された場合、ＡＰＩ関数Ｘは、監視スレッド１１０によって監視されるほど、頻繁に実行される関数ではない。このため、ＡＰＩ関数決定プログラム１１７０は、ＡＰＩ関数ＸをＡＰＩ関数フック群５１０に決定しない。そして、ＡＰＩ関数決定プログラム１１７０は、ステップ１２１０に戻り、ＡＰＩ関数Ｘを抽出しなおす。
【０２１０】
ステップ１２３０において、抽出された使用回数１１４２が所定の閾値Ｔよりも大きいと判定された場合、ＡＰＩ関数Ｘは、監視スレッド１１０によって監視されるべきＡＰＩ関数である可能性が高い。このため、ＡＰＩ関数決定プログラム１１７０は、ＡＰＩ関数ＸがＡＰＩ関数フック禁止リスト１１３０に含まれているか否かを判定する（１２４０）。
【０２１１】
ステップ１２４０において、ＡＰＩ関数ＸがＡＰＩ関数フック禁止リスト１１３０に含まれていると判定された場合、ＡＰＩ関数Ｘは、ＡＰＩ関数フック群５１０として決定されるべきＡＰＩ関数ではない。このため、ＡＰＩ関数決定プログラム１１７０は、ステップ１２１０に戻り、ＡＰＩ関数Ｘを抽出しなおす。
【０２１２】
ステップ１２４０において、ＡＰＩ関数ＸがＡＰＩ関数フック禁止リスト１１３０に含まれていないと判定された場合、ＡＰＩ関数決定プログラム１１７０は、ＡＰＩ関数ＸをＡＰＩ関数フック群５１０に追加する（１２５０）。そして、新しいＡＰＩ関数Ｘを抽出するため、ステップ１２１０に戻る。
【０２１３】
具体的には、図９に示す統計情報１１４０において、ｓｌｅｅｐ  ＡＰＩ関数を示すエントリの使用回数１１４２は１００回を示し、ｐｒｉｎｔｆ  ＡＰＩ関数の使用回数１１４２は１０回である。このため、使用回数１１４２の平均値は５５であり、ステップ１２３０における閾値Ｔは５５である。そして、ＡＰＩ関数決定プログラム１１７０は、ステップ１２３０によってｓｌｅｅｐ  ＡＰＩ関数のみを決定し、ステップ１２５０によってｓｌｅｅｐ  ＡＰＩ関数をＡＰＩ関数フック群５１０に追加する。
【０２１４】
なお、処理内容１１１０は、統計情報１１４０にＡＰＩ関数の使用時刻またはＡＰＩ関数のスレッドＩＤなど追加する処理を含んでもよい。そして、ＡＰＩ関数決定プログラム１１７０は、統計情報１１４０に格納される値に基づいて、監視スレッド１１０が保持する監視周期と、図６に示すステップ８５０において監視スレッド１１０によって用いられる保護回数とを算出してもよい。
【０２１５】
例えば、ＡＰＩ関数が頻繁に実行される時間帯が、統計情報１１４０のＡＰＩ関数の使用時刻から取得できる場合、ＡＰＩ関数決定プログラム１１７０は、ＡＰＩ関数が頻繁に実行される時間帯において監視スレッド１１０が頻繁に監視情報６２０を参照するように、監視スレッド１１０の監視周期を定めてもよい。
【０２１６】
また、統計情報１１４０にＡＰＩ関数のスレッドＩＤが含まれる場合、ＡＰＩ関数決定プログラム１１７０は、スレッド毎にＡＰＩ関数の使用状況を考慮してＡＰＩ関数フック群５１０を決定してもよい。
【０２１７】
なお、第３の実施形態と、第１の実施形態と、第２の実施形態とを併用し、開発者または使用者が統計情報１１４０からＡＰＩ関数フック群５１０に格納されるＡＰＩ関数を選択してもよい。また本実施形態は、統計情報１１４０を取得する方法をＬＤ＿ＡＵＤＩＴ環境変数１１２０によるＡＰＩ関数フックに限定しなくてもよく、プロセスまたはスレッド１２０によって読み出される変数を介して、ＡＰＩ関数フック処理を読み出せれば、いかなる変数を用いてもよい。
【０２１８】
第３の実施形態の共有ライブラリ５００の生成処理、ＡＰＩ関数フックによる生存報告処理、異常動作検出処理、異常検出時の処理については、第１の実施形態または第２の実施形態と同じである。すなわち、ＡＰＩ関数決定プログラム１１７０がＷＡＩＴ状態になるＡＰＩ関数をＡＰＩ関数フック群５１０に含める場合、第３の実施形態の監視スレッド１１０およびスレッド１２０は、第２の実施形態と同じ処理を行い、ＡＰＩ関数決定プログラム１１７０がＷＡＩＴ状態になるＡＰＩ関数を含めない場合、第３の実施形態の監視スレッド１１０およびスレッド１２０は、第１の実施形態と同じ処理を行う。
【０２１９】
第３の実施形態によれば、カーネル１００の変更、スレッド監視の対象であるプログラムのソースコードの変更およびリコンパイル、スレッド監視の対象であるプログラムのコンパイル済み実行ファイルへの変更を伴わずに、ＡＰＩ関数フック群５１０を自動的に決定でき、さらに、スレッド監視を自動的に実行することができる。
【０２２０】
また、第３の実施形態によれば、開発者または使用者がソースコードを閲覧できない場合も、ＡＰＩ関数決定プログラム１１７０によって、ＡＰＩ関数フック群５１０が自動的に決定される。また、統計情報１１４０にＡＰＩ関数の使用状況を示す値を格納することによって、開発者または使用者の環境に従って、最適なＡＰＩ関数フック群５１０が決定される。
【０２２１】
また、第３の実施形態によれば、ＡＰＩ関数フック禁止リスト１１３０を用いることによって、呼ばれる回数が多く、実行速度に影響がある排他制御（例えば、ロック取得の処理またはアンロックの処理など）をＡＰＩ関数フック群５１０に決定しないことができる。このため、第３の実施形態のスレッド監視方法を提供するために、スレッド監視の対象であるプログラムの処理を遅延させることがない。
【０２２２】
なお、第３の実施形態における開発者または使用者は、ＡＰＩ関数フックを決定するために、スレッド監視の対象となるプログラムを含むソフトウェアを、ＡＰＩ関数フック群５１０を決定するために起動し、さらに、決定されたＡＰＩ関数フック群５１０を読み出すために共有ライブラリ５００を起動する必要がある。このため、第３の実施形態における機器４０は、スレッド監視の対象となるプログラムを含むソフトウェアを連続して起動するためのプログラムを、メモリ４２０に保持してもよい。
【０２２３】
また、開発者または使用者は、共有ライブラリ１１００および処理内容１１１０の生成処理、ＬＤ＿ＡＵＤＩＴ環境変数１１２０に共有ライブラリ１１００の識別子を設定する処理、および、ＡＰＩ関数決定プログラム１１７０を実行する処理等の第３の実施形態を実行するための設定処理を、機器４０が備えるキーボード等の入力装置を介して行ってもよい。
【０２２４】
また、第３の実施形態において、開発者または使用者は、前述の第３の実施形態を行うための設定処理を行うプログラムを生成し、他の計算機から機器４０へＮＩＦ４４０を介して、生成されたプログラムを送信してもよい。そして、機器４０に、送信されたプログラムを実行させてもよい。
【０２２５】
また、第３の実施形態において、開発者または使用者は、前述の第３の実施形態を行うための設定処理を行うプログラムを、計算機によって読み取り可能な非一時的記憶媒体によって、機器４０に入力してもよい。
【０２２６】
本実施形態によれば、スレッド１２０が、無限ループ、デッドロック、またはロック処理を伴わない停止状態であることによって、正常に動作していない場合に、スレッド１２０が異常に動作していることを検出することができる。
【０２２７】
また、本実施形態によれば、ＡＰＩ関数フックによってスレッド１２０を監視するための生存フラグ１４０を更新することによって、カーネル１００の変更、スレッド監視の対象であるプログラムのソースコードの変更およびリコンパイル、または、スレッド監視の対象であるプログラムのコンパイル済み実行ファイルへの変更を伴わないスレッド監視方法を実現できる。
【０２２８】
また、本実施形態によれば、既存のＡＰＩ関数の処理に監視情報６２０を更新する処理が追加されるのみであるため、スレッド監視の対象のプログラムの処理を大きく遅延させることがない。さらに、図１１に示すステップ１２３における監視命令メッセージが不要であるため、プログラムサイズの縮小とプロセッサの処理時間の削減とが可能になる。
【符号の説明】
【０２２９】
１００  カーネル
１１０  監視スレッド
１２０  スレッド
１３０  命令メッセージキュー
１４０  生存フラグ
４００  ＣＰＵ
４２０  メモリ
４４０  ＮＩＦ
５００  共有ライブラリ
５１０  ＡＰＩ関数フック群
５２０  スレッドプロシージャ
５３０  ＬＤ＿ＰＲＥＬＯＡＤ環境変数
６１０  監視対象リスト
６２０  監視情報
１１００  共有ライブラリ
１１２０  ＬＤ＿ＡＵＤＩＴ環境変数
１１３０  ＡＰＩ関数フック禁止リスト
１１４０  統計情報
【図１】
0005648187.tif 000002
【図２】
0005648187.tif 000003
【図３】
0005648187.tif 000004
【図４】
0005648187.tif 000005
【図５】
0005648187.tif 000006
【図６】
0005648187.tif 000007
【図７】
0005648187.tif 000008
【図８】
0005648187.tif 000009
【図９】
0005648187.tif 000010
【図１０】
0005648187.tif 000011
【図１１】
0005648187.tif 000012
【図１２】
0005648187.tif 000013