時間処理の落とし穴 - 時間精度とtick

「旦那様、旦那様、起きて下さいませ。睡眠薬を飲む時間です」

マルチメディア関連のソフトウェアやデバイスドライバ、組み込み系のようなリアルタイム処理が必要なプログラム等を書いていると、タイミング制御や経過時間の取得等、時間に関する処理が必要になってきます。時間処理については、正しく理解していないと陥りがちな落とし穴がいくつかありますので、今回はそのあたりについて書いておこうと思います。


sleep系関数の精度と挙動

一定時間ごとの周期処理や、リソース競合時の遅延リトライ。そんな時に用いられるのがsleep系関数(sleep/usleep/nanosleep)です。一定時間呼び出しスレッドを停止させる関数(システムコール)であり、sleepなら秒、usleepならマイクロ秒(1/1000000秒)、nanosleepならナノ秒精度(1/1000000000秒)の指定が可能になっています。
しかし、実際この精度で、次に起床されるタイミングを制御できるわけではありません。実際、x86系のLinuxの実装では10ms以下の精度の指定は、10ms精度に丸めらてしまいます(※1)。これは、sleepによって、待ちキューに入ったスレッド(プロセス)を起床させるタイミングが、tick単位であるためです。tickは、上位アプリケーションの開発者にはあまり馴染みがないかもしれませんが、OSが周期的な処理間隔であり、x86 Linuxの場合、これが10msになのです。
大抵のOSでは、tick単位で、タイマ割り込みが発生し、このタイマ割り込みのタイミングで、時間指定でsleepしていたスレッド(プロセス)が起床されるという実装になっています。このため、tick以下のsleep時間を指定しても起こされるタイミングがないのです。

こう書くと、何でtickはそんなに大きな(※2)数字になっているんだという疑問もでそうなのですが、これには理由があります。このtickを小さくすればするほど、定期的なタイマ割り込みの頻度があがるため、システム全体の負荷に影響が出てしまいます。それをおしてでもということであれば、カーネルソース内のtick定義を変更すれば、sleep精度を改善することは可能です。但し、非常の根本にかかわるところなので、変更には十分な注意が必要です。

以上は、POSIXのsleep関数の問題ですが、ITRON系のwai_tsk()システムコールではもともとsleep時間をtick単位で指定するような仕様であるため、このような勘違いは起こりにくい仕様になっています。こういうところに、もともと組み込み等のリアルタイム処理向けの仕様として作られたか、汎用システムの仕様として作られたかという点に起因する思想の違いが見てとれます。

※1 Linuxのnanosleepでは、リアルタイムスレッドで2ms以下のsleep指定をするとbusy waitによるsleepを行います。よって、2ms以下の精度のsleepも可能にはなっていますが、busy waitのため、他のスレッドは動作できません。
※2 10msというと十分短いと感じる人もいるでしょうが、リアルタイム処理系にとっては、非常に長い時間です


時間情報取得関数の精度

sleep以外の時間処理としては、時刻や経過時間等の時間情報を取得するというケースがあります。リアルタイム系の処理では、定期的なポーリングで経過時間を取得しつつ処理を行ったりする時等に用いられます。リアルタイム処理以外でも、処理の実行時間等のプロファイル計測に用いられることが多いでしょう。
さて、この時間情報取得関数、POSIX準拠のC言語ライブラリだけでもいくつか種類があります。時間情報を正しく取得するためには、これらの違いとメリット・デメリットを正しく理解しておく必要があります。

◎clock()
clock()はANSI Cで定義されており、その返り値の型はclock_tです。clock_tの単位はCLOCKS_PER_SECtとして定義されており、POSIXではこれ(CLOCKS_PER_SEC)が1000000(1us)である亊を要求しています。しかし、この精度があるというわけではなく、実際大抵はtick精度しかでません。なお、clockは実行中のプロセスの処理経過時間を返すため、APIのプロファイル等には便利です。
◎gettimeofday()
時間情報取得の定番です。現在の時刻情報が取得できます。これも単位はusecだが、こちらはtick以下の精度もでる。但し、実行中以外のスレッドも含む全システムでの経過時間を返すため、プロファイリングで用いる時には注意が必要です。また、現在時刻を取得するというものであるため、バックグラウンドでntp等が動いていると、時刻情報に補正が入ったために経過時間計測が狂うことがあるのでこれも注意が必要です。
◎times()
clock()同様にスレッドの実行時間をtick精度で取得できます。tick精度の情報であれば十分です。
◎getrusage
POSIX系ならこれば一番無難でしょう。gettimeofday同様精度が高く、times、clockのようにプロセス単位の経過時間も取得できます。


【関連リンク】
Manpage of sleep/usleep/nanosleep
Manpage of gettimeofday/clock
C言語: 実行時間測定の方法
Linuxによる一定周期実行


【関連書籍】
リアルタイム組込みOS基礎講座 Qing Li
RTLinuxテキストブック―ハードリアルタイム機能を使いこなす Matt Sherer FSMLabs
リアルタイムJavaプログラミング ピーター・C・ディブル
詳解Linuxカーネル 第2版 ダニエル・P・ボベット 他
Linuxデバイスドライバ 第2版 Alessandro Rubini 他
組み込みLINUXシステム構築 カリム・ヤフマー

つかむ技術・目立つ技術

噂されることよりももっと悪いことがある。それは噂にもされないことだ。
オスカー・ワイルド
去年のベストセラーになった「さおだけ屋はなぜ潰れないのか? 身近な疑問からはじめる会計学」。今さらながらですが、借りて読んでみました。字も大きめで、ページ数もそんなにないので、一回の行き帰りの電車で読み終わりました。良くも悪くも「分かりやすい」本です (^^)。

それにしてもこの題名。うまいですね。「なぜ○○は、××なのか」といったタイトルの本は多い(特に新書。例えば、「怪獣の名はなぜガギグゲゴなのか」とか「暗証番号はなぜ4桁なのか?」とか)ですが、この本は「多くの人が一度は疑問に思ったことがあり、改めて知りたいと思わせる」絶妙な疑問をもってきたところがよかったのでしょう。こういうと著者に失礼かもしれませんが、これが「やさしい会計学入門」なら、売り上げは10分の1もなかったでしょう。もちろん、これだけ売れているのですから中身を否定しているわけではありません。中身がどんなにいい本であっても、まずはその一端を知ってもらわなければ始まりません。知名度のない段階で、中身を見てもらえる可能性を高めるには、本のタイトルやデザインで「目立つ」「気をひく」ことが何より重要でしょう。

そんなことを考えていて、ふと思い出したことがあります。それは、大学の就職活動の時期に送られてきた会社案内資料のひとつ。通常封筒といえば長方形ですが、某企業の封筒だけはなんと三角形だったのです。三角形だから、資料を山積みにしたりしても、どうしても角が飛び出します。この形によって、意表をついた形という「つかみ」、他と混ざった後も「目立つ」という効果が得られているのです。正直迷惑だなぁと思いつつも、この「目立ち方」には感心しました。

アフィリエイトブームもあって、SEO(検索エンジン最適化)についての解説本や解説サイトは数多く出てきました。その弊害か、あきらかに内容がなさそうなサイトが上位表示されることがあります。このような検索結果の数が膨大な状況に出くわすと、サイトのタイトルである程度ふるいわけを行ってしまいます。こういう状況を考えると、Webサイトにおいても目をひくタイトルをつけるということの重要だなと強く感じます。

本ページのタイトル「職業としてのプログラミング」はドイツの経済学者・社会学者であるマックス・ウェーバーの「職業としての学問」をもじってみたもの。何だか名前負けしてそうなので、何度か変えようかと思っていたのですが、結局そのままになっています。「目立つ」という点では、よかったのか悪かったのか・・(^^;)

【関連書籍】
街で目立つ小型パンフレット
ネーミング発想法 横井 惠子
ヒット商品をつくるネーミング辞典 学研辞典編集部
すべてはネーミング 岩永 嘉弘
さおだけ屋はなぜ潰れないのか? 身近な疑問からはじめる会計学 山田 真哉
怪獣の名はなぜガギグゲゴなのか 黒川 伊保子
暗証番号はなぜ4桁なのか? セキュリティを本質から理解する 岡嶋 裕史

※SEOに触れてみたこともあって、ひさびさにアクセス解析を見ました。すると、数日前を境に、急にgoogleからのアクセスが1/10以下になっていました!。更新頻度が下がったせい?
人気エントリ
最近の記事
本のおすすめ

4274065979

4844337858

482228493X

4904807057

4873114799


最近のコメント
Links
プロフィール
  • Author:proger
  • 組み込み関係で仕事してます
ブログ内検索