キー変数はpercpuある:CPUの数に応じて要求は、メモリ内の複数のコピーを生成し、変数名に応じて、CPUとCPUの数に対処するために、各変数を修正します。
CPUごとの変数を使用すると、次のような利点があります。必要なデータがプロセッサのキャッシュに存在する可能性あり、それはより迅速にアクセスすることができます。複数のCPUにもマルチプロセッサシステム内の変数にアクセスする場合、それはいくつかの通信の問題、ちょうどこの問題を回避するため、変数percpuの使用を原因となります。
各CPUは、ライン上の変数を持っているpercpuここでは、読者が唯一覚えている必要が、この記事を読んだ後、戻ってくると大胆なフロントを読んで、私はより深い理解があるだろうと信じています。
変数percpuを定義する方法を初めて目:
DEFINE_PER_CPU(int型、cpu_number)。 #define DEFINE_PER_CPU(種類、名)\ __attribute __((__セクション__( "data.percpu")))__typeof __(タイプ)per_cpu __名##
コード上Percpuはint型、per_cpu_cpu_numberの名前の変数を定義します。__typeof __(タイプ)は、INTを得ている、とper_cpuは__ ##名がper_cpu_cpu_numberを得て、この__section__の.data.percpuすることにより、データ・セグメントへの変数の名前。したがって、コンパイル時にすべての変数は、カーネルの起動時に、.data.percpuのpercpuデータセグメントに統合され、CPUの検出数に応じて、データとは別に、各セクションのコピー.data.percpu CPU。start_kernelの関数が呼び出されますsetup_per_cpu_areasを()この作業を完了するために、setup_per_cpu_areas次のように定義されました:
// __ per_cpu_offsetアレイ保存CPUのpercpuセグメントに対応する相対PTRオフセット のunsigned long __per_cpu_offset [NR_CPUS] __read_mostly、 静的ボイド__initのsetup_per_cpu_areas(ボイド) { unsigned long型サイズ、I; チャー*のPTRと、 CPUの数取ら//は 長い符号なし= num_possible_cpus nr_possible_cpus(); / *各CPUのためのコピーsectionTop(WEオリジナルを破棄)* / / *必要なCPU percpu当たりのセグメントサイズの計算。 * * @PERCPU_ENOUGH_ROOM:__ per_cpu_end - __per_cpu_start + PERCPU_MODULE_RESERVE * @ALIGN():percpu整列セグメントサイズアップします * / サイズ= ALIGN(PERCPU_ENOUGH_ROOM、PAGE_SIZE); //割り当てるメモリ PTR = alloc_bootmem_pages(nr_possible_cpus *サイズ); for_each_possible_cpu(I) { / *各CPUのため__Per_cpu_start用語は固定値であり、それは__per_cpu_endがリンカーによって生成される *実記憶アドレスがpercpu線形セグメントをオフセット__per_cpu_start各CPUに対して計算 *コード下概略をご参照ください *のmemcpyは、独自percpuセグメントに各CPU percpuすべての変数をコピー * / ; __per_cpu_start - __per_cpu_offset [I] = PTR のmemcpy(PTR、__per_cpu_start、__per_cpu_end - __per_cpu_start); PTR + =サイズ; } }
だから、どのようにそれpercpuコンパイル時変数でソースコードにアクセスするには?カーネルはpercpu変数へのアクセスを実現するために、いくつかのマクロを定義しています。
// smp_processor_id()CPU以下のパラメータとして、現在アクティブなプロセッサのIDを返すことができます。 per_cpuのに#define(VAR、CPU)(*({\ にextern int型_ ## simple_identifierのVAR(無効); \ RELOC_HIDE(##&per_cpu __ VAR、__per_cpu_offset(CPU));}))
ここでは一例について説明する与える:per_cpu_varにDEFINE_PER_CPUから解舒を定義する場合と仮定アクセスper_cpuを(VARは、1)、percpu変数ので、そうRELOC_HIDE最初のパラメータは、コンパイル時per_cpu_varアドレス、第2のパラメータ__per_cpu_offset(あります差分コピー実行時データ領域先頭アドレスとpercpuの先頭アドレスを表す正面setup_per_cpu_areasについて計算CPU)は、2つの値を追加すると、実際にpercpu変数が格納されたアドレスである、同定コンパイル。次のように図です。
もっと(庚)新しいカーネル(2.6.32)では、変数percpu(DEFINE_PER_CPU)の定義とアクセス(per_cpu(VAR、CPUは))方法を変更しない、主に初期化された配列__per_cpu_offsetは、変更しました関数内のアーチ\ X86 \カーネルの\ setup_percpu.cを参照してください。setup_per_cpu_areasを()。そして、あなたは以下のリンクを参照することができます: