C LANGUAGE TECHNOLOGY

【C言語】LinuxにおけるリアルタイムスケジューリングRMとEDFの実装

2022年4月27日

悩んでいる人

C言語でLinuxにおけるリアルタイムスケジューリングRMとEDFの実装を教えて!

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

本記事の信頼性

  • リアルタイムシステムの研究歴12年.
  • 東大教員の時に,英語でOS(Linuxカーネル)の授業.
  • 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
  • プログラミング歴15年以上,習得している言語: C/C++PythonSolidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Assembler (x64,ARM).
  • 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」GitHubにオープンソースとして公開
  • 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
  • 最近は自然言語処理AIイーサリアムに関する有益な情報発信に従事.
    • (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
    • (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.

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

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

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

私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!

友だち追加

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

C言語でLinuxにおけるリアルタイムスケジューリングRMとEDFの実装

C言語でLinuxにおけるリアルタイムスケジューリングRMとEDFの実装を紹介します.

結構難しい内容なので,じっくり読み進めて下さい.

RMとEDFの理論や比較を知りたいあなたはこちらからどうぞ.

本記事では,以下の記事の内容を理解していることを前提とします.

sched_attr構造体とsched_setattr/sched_getattrシステムコール

sched_setattr/sched_getattrシステムコールは,スケジューリングポリシーと属性の設定と取得を行います.

これらのシステムコールは非標準のLinuxによる拡張であることに注意して下さい.

sched_attr構造体は,指定したスレッドの新しいスケジューリングポリシーと属性を定義した構造体で,sched_setattr/sched_getattrシステムコールの第2引数で利用します.

  • size:この構造体のサイズ
  • sched_policy:ポリシー(SCHED_*)
  • sched_flags:フラグ
  • sched_nice:nice値(SCHED_OTHER,SCHED_BATCH)
  • sched_priority:静的優先度(SCHED_FIFO,SCHED_RR)
  • sched_runtime:SCHED_DEADLINEの実行時間
  • sched_deadline:SCHED_DEADLINEの相対デッドライン
  • sched_period:SCHED_DEADLINEの周期
  • sched_util_min:SCHED_DEADLINEのCPU利用率の最小値
  • sched_util_max:SCHED_DEADLINEのCPU利用率の最大値

標準ライブラリのヘッダファイルsched.hにsched_setattr/sched_getattrシステムコールのプロトタイプ宣言とsched_attr構造体の定義があるという記載ですが,Ubuntu 22.04 LTSのヘッダファイルにはありません.

※sched_setattr/sched_getattrシステムコールは非標準のLinuxによる拡張であるからだと考えられます.

また,linux/sched/types.hヘッダファイルにsched_setattr/sched_getattrシステムコールのプロトタイプ宣言とsched_attr構造体の定義はありますが,linux/sched/types.hヘッダファイルをインクルードすると標準ライブラリのヘッダファイルsched.hとの整合性が取れていないため,ビルドエラーが発生します.

なので,自作コードでsched_attr構造体の定義とsched_setattr/sched_getattrシステムコールのプロトタイプ宣言が必要になりますので注意しましょう!

LinuxにおけるリアルタイムスレッドはCPUを100%利用できない!?

Linuxにおけるリアルタイムスレッドは,デフォルトではCPUを100%利用できない設定になっています.

catコマンドで実行すると以下のようになります.

  • sched_rt_period_usは1,000,000マイクロ秒(1秒)
  • sched_rt_runtime_usは950,000マイクロ秒(0.95秒)

つまり,リアルタイムスレッドは1秒あたり0.95秒までしか実行できません(1秒あたりのCPUの実行割合は95%).

この理由として,リアルタイムスレッドが暴走した場合の安全装置としての役割があるからです.(コアが1つしかない場合,そのコアでリアルタイムスレッドが暴走したらOSが制御不能になり,強制的に再起動しなければなりません.)

参考までに,上記の値はLinuxカーネルのkernel/core/sched.cファイルのsysctl_sched_rt_periodとsysctl_sched_rt_runtime変数に設定されています.

もしリアルタイムスレッドでCPUを100%利用したい場合は以下のコマンドを実行しましょう.

ここで,「sched_rt_runtime_us=-1」は無制限の意味です.

sched_rt_runtime_usを表示してみると,-1になっていることがわかります.

※この設定をした場合,実行するリアルタイムスレッドは注意して下さい.

LinuxにおけるRMとEDFの実装

LinuxにおけるRMとEDFの実装を紹介します.

RMはSCHED_FIFOスケジューリングポリシー,EDFはSCHED_DEADLINEスケジューリングポリシーを利用して実装します.

ここで,SCHED_FIFO/SCHED_DEADLINEスケジューリングポリシーは,管理者権限でないと利用できないことに注意して下さい(sudoコマンドで実行).

RMとEDFでスケジューリングするタスクセットは以下になります.

  • タスク数:2(RMを考慮してタスクIDが小さいほど周期が短いことを想定)
    • タスク1:実行時間0.6秒,周期1秒
    • タスク2:実行時間0.5秒,周期1.5秒
  • 実行時間は安全マージンを考慮して80%を実行(0.6秒の場合は0.6 * 80% = 0.48秒)
  • タスクセットの実行時間は3秒
  • RMの場合はタスクの実行するCPUはCPU 0で固定(migrate_thread_to_cpu関数でCPU 0にマイグレーション)
  • EDFはSCHED_DEADLINEの特性上,affinityマスクを設定できません(理由はこちら).特定のコアでSCHED_DEADLINEを実行したい場合は,以下の方法でLinuxが利用するコア数を1にしましょう!
    • VMでLinuxをゲストOSとして利用している場合,VMでLinuxが利用するコアを1コアに設定
    • ホストOSとしてLinuxを利用している場合,BIOSでLinuxが利用するコアを1コアに設定
    • CPUのホットプラグで動的にプロセッサを無効して1コアに設定

CPUのホットプラグで動的にプロセッサを無効に設定する方法を知りたいあなたはこちらからどうぞ.

実装方法は以下の2種類を紹介します.

  • 1プロセス,マルチスレッドの実装
  • マルチプロセスの実装(コマンドラインでタスク数分のプログラムを実行)

コード一式は,こちらからrm_and_edf.zipをダウンロードして,解凍して下さい.

解凍したrm_and_edf.zipファイルの構成は以下になります.

  • Makefile:以下のRMとEDFの2種類の実装(合計4種類)をビルドするMakefile
  • fifo.c:RMの1プロセス,マルチスレッドの実装
  • fifo2.c:RMのマルチプロセスの実装(コマンドラインでタスク数分のプログラムを実行)
  • deadline.c:EDFの1プロセス,マルチスレッドの実装
  • deadline2.c:EDFのマルチプロセスの実装(コマンドラインでタスク数分のプログラムを実行)

以下のようにrm_and_edfディレクトリに移動してmakeでビルドすると,上記の4つのプログラムの実行ファイル(fifo,fifo2,deadline,deadline2)が作成されます.

1プロセス,マルチスレッドのRMの実装

1プロセス,マルチスレッドのRMの実装は以下になります.

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

マルチプロセスのRMの実装(コマンドラインでタスク数分のプログラムを実行)

マルチプロセスのRMの実装(コマンドラインでタスク数分のプログラムを実行)は以下になります.

実行結果の例は以下になります.(プロセスIDは実行時により変動)

1プロセス,マルチスレッドのEDFの実装

1プロセス,マルチスレッドのEDFの実装は以下になります.

実行結果の例は以下になります.(実行するCPU IDは実行時により変動)

マルチプロセスのEDFの実装(コマンドラインでタスク数分のプログラムを実行)

マルチプロセスのEDFの実装(コマンドラインでタスク数分のプログラムを実行)は以下になります.

実行結果の例は以下になります.(プロセスIDや実行するCPU IDは実行時により変動)

まとめ

C言語でLinuxにおけるリアルタイムスケジューリングRMとEDFの実装を紹介しました.

具体的には,RMとEDFで,「1プロセス,マルチスレッド」と「マルチプロセス」の実装(合計4種類)を解説しました.

これらの4種類をゼロから実装するのは結構大変ですので,是非参考にして下さい.

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

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

私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!

友だち追加

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

-C LANGUAGE, TECHNOLOGY
-, , , , , ,