seclan のほえほえルーム

| |

・勇者は唱えた!「ねーむれ」 (1999/04/06 [])
 マルスタスクを実現している OS 上で動くプログラムでは、常に CPU 資源について考えてプログラミングをする必要があります。それはプリエンプティブ方式であろうが、ノンプリエンプティブ方式であろうが変わりありません。
 で、具体的にはどんな時に気をつけなければいけないかというと、CPU 資源を単に何かの状態に変わるまでループするだけのような場合です。例えば、二つスレッドを立ち上げて同期を取りつつ動作させるために、フラグ変数とそれが変更されまで待ち続けるループを使うといった方法は、プリエンプティブでは無駄な CPU 資源の消費になるし、ノンプリエンプティブではプログラムが止まってしまいます。このようなときには OS の提供している同期プリミティブを使用すると CPU の効率化を図ることができます。
 しかし、時にはそのようなプリミティブを使用できず、どうしてもフラグが変更するまでループする必要がある場合があります。例えば、秒まで表示する時計を考えた場合、秒が変わったときに OS が通知してくれる OS はなかなか存在しません。また、秒は 1 秒毎だからと、1 秒プログラムを眠らせる、という方法もありますが、この方法では誤差の蓄積の問題で必ずしも、正しい1秒を表示できそうではありません。そこで、ループでフラグの変更を検出する、つまりポーリングする必要があります。
 とは言っても、プリエンプティブ方式でもこれは CPU 資源の無駄です。そこで、フラグを検査した後、すぐに CPU を他のスレッドに渡してしまうという方法が考えられます。このようにすれば、CPU を前の方法よりは有効に活用できます。
 16bit の Windows ではこの CPU 明け渡しを Yield() という関数で行うことができました。しかし!、Win32 API では Yield() はもはや存在しなくなりました。Yield() と書いても、消されてしまいます(Windowsのヘッダファイルで Yield() は空マクロとして定義されている)。では、CPU を明け渡す方法はないのかというと実は、存在しています。それが現在のスレッド(プログラム)を n 秒眠らせる Sleep 関数を使う方法です。具体的には、Sleep 関数の引数は眠らせるミリ秒を指定するのですが、単に明け渡す場合には、0 を指定すればよいことになっています。
 で、いったい何を言いたいのかというと 同じ動作の関数があるなら #define Yield() Sleep(0) となぜしてくれないんだ! これを調べるために無駄な時間を使ってしまったではないか!ということです。ぜーぜー。
 では今日はここまで。
 *祝 100 アクセス突破!


by seclan


| |

 

配信

6.41 msec