ホームページ  >  記事  >  システムチュートリアル  >  高精度タイマーの導入・運用フレームワーク関連分析

高精度タイマーの導入・運用フレームワーク関連分析

WBOY
WBOYオリジナル
2024-07-20 08:36:00474ブラウズ

高精度タイマーの導入・運用フレームワーク関連分析

高精度のタイマーについて突然言及すると、少なくとも初心者は混乱するでしょう。そして、それを文字通り理解すれば、タイマーの精度が低ければ、それ以上はありません。これで大まかですが、その他の詳細が含まれるだけです。

労働者が仕事をうまくやりたいなら、まず自分の道具を研ぐ必要があります。話を始める前に、まず自分の道具を研ぎましょう:

2 いくつかの関連するソース コード ファイルとそのパスは次のとおりです:

Hrtimers.txt(linux-3.2.12documentationtimers)

Hrtimer.c(linux-3.2.12kernel)

Hrtimer.h(linux-3.2.12includelinux)

2 高精度タイマーモードで高精度タイマーを操作するだけ 全体の操作フレームワークは次のとおりです。

hrtimer_init を初期化し、タイミング期間などの hetimer 構造体を介して関連データを設定します。-> タイマーをオンにします。 hrtimer_start-> 割り込みをトリガーし、割り込みリバウンド関数を呼び出します。 hrtimer_interrupt-> 高精度タイマーの削除remove_hrtimer.

読者の頭の中にフレームワークができました。具体的なドライバーの詳細については、以下で 1 つずつ説明します。

まず概要を説明します。理解するのが難しい部分があるかもしれませんが、それを説明するために関連するコードと例があります。

?高精度のタイマーが時間に応じて黒赤の木をソートします。

? これらは周期クロック

Linux アプリケーション タイマー から独立しており、ジフィー時間次元の代わりにパルス幅のタイムスタンプを使用します。

まず、Linux コード内の高精度タイマーに関連するドキュメントを取り出し、後で説明するドキュメント パス: Hrtimers.txt (linux-3.2.12documentationtimers) を見てください。

ドキュメントの内容… 正直に言うと、ドキュメントは少し長いですが、Linux ドキュメントのメンテナンス性はそれほど高くありません。上記からいくつかの文を見つけて翻訳し、説明しました。

?Thispatchintroducesa newsubsystemforhigh-resolutionkerneltimers. この文の「patch」というフレーズは、2.6.16 より前には高精度タイマーがパッチ パッケージとしてシステムにインストールされることを意味します。

2 番目の点は、英語が長すぎるため、高精度のタイマーを使用する必要があるためです。実際には、精度は高くありません。低精度タイマーと呼ばれます。端的に言えば、高い精度が求められます。

? 3 番目の点は、高精度タイマーのもう 1 つの特徴は、コンパイル時にそのフレームワークがカーネル内にあり、高精度タイマーが設定されていない場合、そのような高精度タイマーは通常のタイマーの実行に基づいていることです。

?最後のポイント、高精度タイマーはブラック マングローブ アルゴリズムを使用して実装され、通常のタイマーはタイム ラウンド ロビン アルゴリズムを使用して実装されます。

?さらに、このドキュメントでは、クロック ソース、データ構造、赤黒ツリーなどの多くの問題についても説明しています。これらの問題については、以下で個別に説明します。

应用定时器程序-1PLC_linux 应用定时器_应用定时器21. 関連するデータ構造

高フレームレートタイマーに関係するデータ構造は、次の側面から検討します:

ソースについて: このクロックはどのようにして得られるのでしょうか? 構造体は hrtimer.h で定義されており、コードは次のとおりです:

structhrtimer_lock_base{

structhrtimer_cpu_base*cpu_base;

intindex; //時計を区別するための属性(全部で2種類あり、後述)

Clockid_t Clockid;// 各 CPU がサポートするクロックの ID

structtimerqueue_headactive;//有効になっているタイマーの黒と赤のブランチ ノード

ktime_tresolution;//クロックのフレームレート、ミリ秒

ktime_t(*get_time)(void);//現在の時計を復元するために使用されます

ktime_tsoftirq_time;//ソフト割り込みで広精度タイマーキューを実行する時間

ktime_toffset;//タイマークロックのオフセット量を変更します

};

前の要素について、いくつか説明してください。

高フレーム レート タイマーは 2 つのクロック (クロックベース) に基づくことができます。1 つはシステムの起動時に 0 から始まる単調クロック (CLOCK_MONOTONIC) で、もう 1 つのクロック (CLOCK_REALTIME) はシステムのリアルタイムを表します。上記の構造体 structhrtimer_lock_base では、インデックス要素は、CLOCK_MONOTONIC クロックであるか CLOCK_REALTIME クロックであるかを区別するために使用されます。システムの各 CPU には、これら 2 つのクロック ベースを含むデータ構造が提供され、各合計クロック ベースには保留中のすべての高精度タイマーlinux アプリケーション タイマー を並べ替える黒赤色のツリーがあり、各 CPU は 2 つのクロック ベース (単調) を提供します。クロックとリアルタイム)、すべてのタイマーが有効期限によって黒赤ツリー上で並べ替えられます。タイマーが期限切れになったが、そのハンドラー リバウンド関数がまだ実行されていない場合は、黒マングローブから配列に移行します。リアルタイム クロックを調整する場合、CLOCK_REALTIME クロックに保存されているタイマーの有効期限値と現在の実際の時刻の間に誤差が生じます。オフセット配列は、これらの状況を修正するのに役立ちます。これは、タイマーが調整する必要があるオフセットの量を表します。これは一時的な効果にすぎず、めったに発生しないためです。

クロックソースを理解する前に、構造体 structhrtimer についても知る必要がある場合があります。コードは次のとおりです。

構造タイマー{

structtimerqueue_nodenode;//タイマー キュー ノードは、node.expires も管理します。高精度タイマーの絶対有効期限は、その内部アルゴリズムに基づいています (上記の 2 つの時間基準)。 )).

应用定时器2_linux 应用定时器_应用定时器程序-1PLC

ktime_t_softexpires;//絶対的に最も早い有効期限

enumhrtimer_restart(*)(structhrtimer*);//タイマー期限切れリバウンド関数

structhrtimer_lock_base*base;//タイムベースを指す針 (CPU ごと、クロックごと)

unsignedlongstate;//ビット値を確認するために使用されるステータス情報

#ifdefCONFIG_TIMER_STATS

intstart_pid; //タイマー統計領域に保存されるタイミングを開始するタスクの pid

void*start_site;//タイマーは現在のタイミングの開始値を保存します

charstart_comm[16];//タイマ統計領域名のタイミング開始の格納処理

#endif

};

上記の構造では、ユーザーは 3 つの点に注意するだけで済みます。1 つ目は、タイマーの期限が切れた後のリバウンド関数です。2 つ目は、有効期限を表します。高精度タイマー構造体を使用するには、hrtimer_init() 関数によって初期化する必要があります。hrtimer_init() 関数はアプリケーション ソケットに属するため、前述しました。ここには別の問題があり、これは高精度タイマーの中核問題でもあります。それは、高精度タイマーへのブラック マングローブの応用です。実際、これについて今話すのは少し時期尚早であり、読者の皆様に知っていただきたいと思います。 Linux の従来のタイミング タイマーはタイム ホイール アルゴリズム (timer.c) を通じて実装されますが、hrtimer はブラック マングローブ アルゴリズムを通じて実装されます。 structhrtimer にはノード フィールドがあり、そのタイプは structtimerqueue_node です。このフィールドは、黒赤ツリー内の hrtimer の位置を表します。バージョン 2.6.X のソース コードであることに注意してください。フィールドはstructrb_nodeです。最初に読者の皆様にご挨拶させていただきます。具体的に使用する際には、その実装方法についてお話します。

2 つの重要な構造体はマルチコアプロセッサと互換性がある必要があるため、各 CPU のクロックを定義するために使用されます。モノトニッククロックとリアルタイムクロックの構造は次のとおりです:

structhrtimer_cpu_base{//単一 CPU タイムベース構造

raw_spinlock_tlock;//ロック関連のタイムベースとタイマー、キャリアロック

unsignedlongactive_bases;//ベースビット配列をアクティブタイマーでマークします

#ifdefCONFIG_HIGH_RES_TIMERS

ktime_texpires_next;//次回期限切れになる絶対時刻

inthres_active; //高フレームレートモードのステータス、ブール変数

应用定时器2_linux 应用定时器_应用定时器程序-1PLC

inthang_detected;//最後に検出された保留中の高精度タイマー割り込み

unsignedlongnr_events;//高精度タイマー割り込みの総量

unsignedlongnr_retries;//高精度タイマー割り込みのリトライ総数

unsignedlongnr_hangs;//高精度タイマー割り込みのハングの総量

ktime_tmax_hang_time;//高精度タイマー割り込みがトリガーされるまでの最大時間

#endif

structhrtimer_lock_baselock_base[HRTIMER_MAX_CLOCK_BASES] //この CPU タイムベース ニードル

};

内部の 3 つの構造体は、高精度タイマーに関連する関数と要素を定義する最も基本的なものである必要があり、各 CPU には定義された構造体の完全なセットがあり、hrtimer を初期化します。

基本的な構造についての説明が終わったので、API ソケットについて説明しましょう。

最初は、hrtimer の API を構成して初期化することです。冒頭で structhrtimer について説明したときに、structhrtimer を使用するには、最初にそれを初期化する必要があると述べました。関数宣言コードは次のとおりです。

voidhrtimer_init(structhrtimer*timer, Clockid_tlock_id,

enumhrtimer_modemode)//指定されたクロック初期化タイマー

debug_init(タイマー,クロックID,モード);

__hrtimer_init(タイマー,クロックID,モード);

上記の関数は高精度タイマーの初期化を実装します。以下は関連する要素の説明です。

/**

*hrtimer_init – 指定されたクロックでタイマーを初期化します

应用定时器2_应用定时器程序-1PLC_linux 应用定时器*@timer: 初期化されようとしているタイマー

*@ Clock_id: 使用される時計

*@mode: タイマーモード abs/rel

*/

モードでは次のように 5 つの定数を使用できます:

enumhrtimer_mode{

HRTIMER_MODE_ABS=0x0,/*時間は絶対値です*/

HRTIMER_MODE_REL=0x1,/*時間は相対値です*/

HRTIMER_MODE_PINNED=0x02,/*タイマーは CPU にバインドされています*/

HRTIMER_MODE_ABS_PINNED=0x02,

HRTIMER_MODE_REL_PINNED=0x03,

};

hrtimer_init() 関数は __hrtimer_init() 関数を呼び出します。 以下はこの関数のプロトタイプです。

staticvoid__hrtimer_init(structhrtimer*timer,lockid_tlock_id,enumhrtimer_modemode)

structhrtimer_cpu_base*cpu_base;

intbase;

memsettimer,0,sizeof(structhrtimer));

cpu_base=&__raw_get_cpu_var(hrtimer_bases);

if(lock_id==CLOCK_REALTIME&&mode!=HRTIMER_MODE_ABS)应用定时器程序-1PLC_应用定时器2_linux 应用定时器

Clock_id=CLOCK_MONOTONIC;

base=hrtimer_lockid_to_base(lock_id);

timer->base=&cpu_base-> Clock_base[base];

timerqueue_init(&timer->node);

#ifdefCONFIG_TIMER_STATS

timer->start_site=NULL;

timer->start_pid=-1;

memset(timer->start_comm,0,TASK_COMM_LEN);

#endif

__hrtimer_init()函數呼叫了structhrtimer_cpu_base結構體對CPU進行相關的初始化,並使用memset()函數,原型如下:

void*memset(void*s,intc,size_tn)

inti;

char*ss=s;

for(i=0;i

ss[i]=c;

returns;

這個函數清空了memory上面的東西,完成了初始化,memset(timer,0,sizeof(structhrtimer))。

在這裡注意一下,還是上面說到的一個問題,我用的源代碼是3.2.12的,而2.6.X的源代碼裡所提供的,雖然只有兩個常數

以上が高精度タイマーの導入・運用フレームワーク関連分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。