C LANGUAGE TECHNOLOGY

【C言語】タイマと割り込み処理の書き方

悩んでいる人

C言語でタイマと割り込み処理の書き方を教えて!

こういった悩みにお答えします.

本記事の信頼性

  • リアルタイムシステムの研究歴12年.
  • 東大教員の時に,英語でOSの授業.
  • 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校コンピュータサイエンス学部2021年の世界大学学術ランキングで20位)で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発
  • プログラミング歴15年以上,習得している言語: C/C++Solidity,Java,Python,Ruby,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
  • 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」GitHubにオープンソースとして公開

こういった私から学べます.

タイマと割り込み

タイマとは,予め設定した時間を経過した後に,その旨を通知するためのハードウェアの仕組みです.

タイマを利用することで,周期もしくは非周期にタスクを起床することができます.

また,タイマにより発生したソフトウェア割り込み(シグナル)をタイマ割り込みと呼び,タイマ割り込みが発生した時の処理をする関数をシグナルハンドラと呼びます.

シグナルハンドラ内では非同期安全な関数しか呼び出すことができませんので注意して下さい.

例えば,シグナルハンドラ内ではprintf関数を利用できないので,標準出力や標準エラー出力にデータを書き込みたい場合はwrite関数を利用しましょう.

sigaction関数

sigaction関数は,シグナルの動作の確認と変更を行う関数です.

actはNULL以外であれば,シグナルsignumの新しい動作(action)としてactが設定されます.

oldactがNULLでなければ,今までの動作がoldactに格納されます.

※sigaction関数と似た処理をするsignal関数がありますが,Linuxのバージョンにより動作が異なるので利用を控えましょう.

sigaction構造体は以下になります.

※sa_handlerとsa_sigactionはunionで定義されていない場合があるので注意して下さい.

以降の説明では,sigaction関数を利用したタイマと割り込み処理の書き方を解説していきます.

getitimer/setitimer関数

getitimer/setitimer関数は,インターバルタイマの値を取得または設定する関数です.

struct itimeval構造体の定義は以下になります.

getitimer関数は,whichで指定されたタイマ(ITIMER_REAL,ITIMER_VIRTUAL,ITIMER_PROFのいずれか)の現在の値(次のタイマ満了までの残り時間)をcurr_valueで指定された構造体に格納します.

it_valueフィールドのにはタイマの残り時間,it_intervalフィールドにはタイマのインターバル(期間)が設定されます.

setitimer関数は指定されたタイマにnew_valueの値を設定します.

old_valueがNULL以外の場合,タイマの古い値(すなわち getitimer関数で返されるのと同じ情報)がold_valueに格納されます.

new_value.it_value のいずれかのフィールドが非ゼロの場合,タイマは指定された時間で開始するために待機します.

new_value.it_valueの両方のフィールドがゼロであれば,タイマは解除されます.

new_value.it_intervalフィールドは,タイマの新しい間隔を指定します.

そのサブフィールド(new_value.it_interval.tv_secとnew_value.it_interval.tv_usec)の両方がゼロの場合,タイマはシングルショットになります.

getitimer/setitimer関数を利用するコードは以下になります.

実行結果は以下になります.

最初に2秒待機した後,「timer_handler() is called.」が1秒間隔で表示されて,3回表示されたら終了します.

実際にタイマが正常にカウントダウンされているかどうか不安になりますよね.

そんなあなたはgetitimer関数でカウントダウンしているタイマの値を表示してみましょう.

以下のように-DCOUNTDOWNオプションを付けてコンパイルして実行してみて下さい.

カウントダウンタイマの値が表示されることがわかります.(とても長いので注意して下さい.)

timer_create/timer_gettime/timer_settime/timer_delete関数

timer_create関数は,プロセスごとのインターバルタイマを新しく作成します.

新しいタイマのIDは,timeridが指すバッファに格納されます(IDはタイマが削除されるまではプロセス内でユニーク).

また,新しいタイマは初期状態は未起動になります.

引数clockidは,新しいタイマが時間を計測するために使用する時計を指定します.

引数sevpはsigevent構造体を指し,タイマが時間切れ(タイムアウト)した時に呼び出し側にどのように通知するかを指定します.

timer_gettime/timer_settime関数は,timeridで識別されるタイマを起動または停止します.

引数new_valueは,タイマの新しい初期値と新しい間隔を指定するitimerspec構造体へのポインタです.

struct itimerspec構造体の定義は以下になります.

timer_delete関数は,timeridで指定されたIDのタイマを削除します.

タイマの削除に成功すると0,失敗すると-1を返します.

timer_create/timer_gettime/timer_settime/timer_delete関数を利用するコードは以下になります.

実行結果は以下になります.

setitimer関数と同様です.

コンパイルする時に-rtオプションを付けることを忘れないようにして下さい.

-DCOUNTDOWNオプションを付けてコンパイルした場合も同様です.

timerfd_create/timerfd_gettime/timerfd_settime関数

timerfd_create関数は,タイマオブジェクトを生成し,そのタイマを参照するファイルディスクリプタを返します.

引き数clockidは,タイマの進捗を管理するためのクロックを指定するもので,CLOCK_REALTIMEかCLOCK_MONOTONICのどちらかを設定します.

引数flagsは,以下のフラグを設定できます.

  • TFD_NONBLOCK:ファイルディスクリプタの操作をノンブロッキングに設定します.
  • TFD_CLOEXEC:明示的にファイルディスクリプタをクローズするのではなく,他のプログラムを実行する際に自動でファイルディスクリプタをクローズするように指定するclose-on-execオプションを設定します.

timerfd_gettime関数は, ファイルディスクリプタfdで参照されるタイマの現在の設定が入ったitimerspec構造体を,curr_valueに格納して返します.

it_value フィールドはタイマが次に満了するまでの残り時間,it_intervalフィールドはタイマの間隔を返します.

timerfd_settime関数は,ファイルディスクリプタfdにより参照されるタイマを起動または停止します.

引数new_valueはタイマの満了時間の初期値と間隔を指定します.

timerfd_create/timerfd_gettime/timerfd_settimeシステムコールは,上記で紹介したsetitimer関数やtimer_create関数の代替になるものです.

この理由として,timerfd_create関数で生成したファイルディスクリプタをread関数select関数poll関数epoll関数で監視できるメリットがあるからです.

timerfd_create/timerfd_gettime/timerfd_settime関数を利用するコードは以下になります.

sigaction関数を利用しないことで,シンプルなコードになっていることがわかります.

また,タイマ割り込みの発生は51行目のread関数で待機し,割り込みが発生したらread関数から返ります.

実行結果は以下になります.

-DCOUNTDOWNオプションを付けた場合の実行結果は以下になります.

まとめ

C言語でタイマと割り込み処理の書き方を紹介しました.

具体的には,以下の関数の使い方を解説しました.

  • getitimer/setitimer関数
  • timer_create/timer_gettime/timer_settime/timer_delete関数
  • timerfd_create/timerfd_gettime/timerfd_settime関数

C言語を独学で習得することは難しいです.

私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.

友だち追加

独学が難しいあなたは,C言語を学べるおすすめのオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!

-C LANGUAGE, TECHNOLOGY
-, , , ,