同期と相互排他変数_percpu

キー変数は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 + =サイズ; 
	} 
}

1552095558772

だから、どのようにそれ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変数が格納されたアドレスである、同定コンパイル。次のように図です。

1552104630074

もっと(庚)新しいカーネル(2.6.32)では、変数percpu(DEFINE_PER_CPU)の定義とアクセス(per_cpu(VAR、CPUは))方法を変更しない、主に初期化された配列__per_cpu_offsetは、変更しました関数内のアーチ\ X86 \カーネルの\ setup_percpu.cを参照してください。setup_per_cpu_areasを()。そして、あなたは以下のリンクを参照することができます:

おすすめ

転載: www.cnblogs.com/still-smile/p/11655208.html