第四章 第四节 per_cpu
我們上一章說(shuō)了
實(shí)現(xiàn)內(nèi)核同步的方法很多,如下表
技術(shù) | 說(shuō)明 | 適用范圍 |
每CPU變量 | 在CPU之間復(fù)制數(shù)據(jù)結(jié)構(gòu) | 所有CPU |
原子操作 | 對(duì)一個(gè)計(jì)數(shù)器原子地“讀-修改-寫(xiě)”的指令 | 所有CPU |
內(nèi)存屏障 | 避免指令重新排序 | 本地CPU或所有CPU |
自旋鎖 | 加鎖時(shí)忙等 | 所有CPU |
信號(hào)量 | 加鎖時(shí)阻塞等待 | 所有CPU |
順序鎖 | 基于訪問(wèn)計(jì)數(shù)器的鎖 | 所有CPU |
本地中斷的禁止 | 禁止單個(gè)CPU上的中斷處理 | 本地CPU |
本地軟中斷的禁止 | 禁止單個(gè)CPU上的可延遲函數(shù)處理 | 本地CPU |
讀-復(fù)制-更新(RCU) | 通過(guò)指針而不是鎖來(lái)訪問(wèn)共享數(shù)據(jù)結(jié)構(gòu) | 所有CPU |
但是這個(gè)每CPU變量,讓我看起來(lái)非常的拗口,什么是每CPU變量,我剛開(kāi)始看的時(shí)候,以為別人寫(xiě)錯(cuò)了,后面又查了很多資料,確定是對(duì)的,才放心,原來(lái)是翻譯的問(wèn)題
優(yōu)點(diǎn)
per_cpu的好處是訪問(wèn)它不需要加鎖,而且這個(gè)變量存在CPU的cache里,訪問(wèn)速度會(huì)非常快
原英文是 per_cpu
/* * Add a offset to a pointer but keep the pointer as is. * * Only S390 provides its own means of moving the pointer. */ #ifndef SHIFT_PERCPU_PTR /* Weird cast keeps both GCC and sparse happy. */ #define SHIFT_PERCPU_PTR(__p, __offset) ({ \ __verify_pcpu_ptr((__p)); \ RELOC_HIDE((typeof(*(__p)) __kernel __force *)(__p), (__offset)); \ }) #endif /* * A percpu variable may point to a discarded regions. The following are * established ways to produce a usable pointer from the percpu variable * offset. */ #define per_cpu(var, cpu) \ (*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu))) |
既然這么拗口,我覺(jué)得就沒(méi)有必要翻譯了,直接說(shuō)明是per_cpu 就好了
怎么使用這個(gè) per_cpu 呢?
在源碼
drivers\cpufreq\cpufreq_userspace.c
下面有一個(gè)使用的歷程
聲明一個(gè) per_cpu
static DEFINE_PER_CPU(unsigned int, cpu_is_managed); #define DEFINE_PER_CPU(type, name) \ DEFINE_PER_CPU_SECTION(type, name, "") |
使用一個(gè)per_cpu
get_cpu_var(var) 和 set_cpu_var(var) |
使用另一個(gè)CPU的per_cpu變量
per_cpu(cpu_cur_freq, freq->cpu) = freq->new; |
導(dǎo)出一個(gè)per_cpu 變量供其他模塊使用
EXPORT_PER_CPU_SYMBOL(per_cpu_var); EXPORT_PER_CPU_SYMBOL_GPL(per_cpu_var); |
注意!!
在使用per_cpu的時(shí)候,記得禁止內(nèi)核搶占
DECLARE_PER_CPU(int, mycounter); ● int cpu; ● preempt_disable(); //禁止搶占 ● cpu = smp_processor_id(); ● per_cpu(mycounter, cpu) += 1; ● preempt_enable(); //開(kāi)啟內(nèi)核搶占 |
SMP系統(tǒng)chcae 命中
什么是smp 系統(tǒng)呢?就是有幾個(gè) CPU組成的芯片,就是我們通常說(shuō)的幾核幾核的說(shuō)法,大概的圖像這樣
? ? ? ? ? ? ? ? ? ? ? ?
per_cpu解決的是多個(gè)CPU上共享數(shù)據(jù)的問(wèn)題,如果聲明了一個(gè)變量A,這個(gè)變量A在每個(gè)CPU下都有自己的副本,使用的堆棧地址也不一樣,但是如果改變了A的值,其他的CPU同樣能獲取這個(gè)改變的值。
這樣的話每個(gè)CPU只要關(guān)心單個(gè)CPU的并發(fā)問(wèn)題,不用考慮多CPU的互斥加鎖并發(fā)問(wèn)題。
聲明和定義Per-CPU變量的API | 描述 |
DECLARE_PER_CPU(type, name)? DEFINE_PER_CPU(type, name) | 普通的、沒(méi)有特殊要求的per cpu變量定義接口函數(shù)。沒(méi)有對(duì)齊的要求 |
DECLARE_PER_CPU_FIRST(type, name)? DEFINE_PER_CPU_FIRST(type, name) | 通過(guò)該API定義的per cpu變量位于整個(gè)per cpu相關(guān)section的最前面。 |
DECLARE_PER_CPU_SHARED_ALIGNED(type, name)? DEFINE_PER_CPU_SHARED_ALIGNED(type, name) | 通過(guò)該API定義的per cpu變量在SMP的情況下會(huì)對(duì)齊到L1 cache line ,對(duì)于UP,不需要對(duì)齊到cachine line |
DECLARE_PER_CPU_ALIGNED(type, name)? DEFINE_PER_CPU_ALIGNED(type, name) | 無(wú)論SMP或者UP,都是需要對(duì)齊到L1 cache line |
DECLARE_PER_CPU_PAGE_ALIGNED(type, name)? DEFINE_PER_CPU_PAGE_ALIGNED(type, name) | 為定義page aligned per cpu變量而設(shè)定的API接口 |
DECLARE_PER_CPU_READ_MOSTLY(type, name)? DEFINE_PER_CPU_READ_MOSTLY(type, name) | 通過(guò)該API定義的per cpu變量是read mostly |
per_cpu 在內(nèi)存中固定的section
? ? ? ? ? ? ? ? ? ? ? ?
參考資料:(公眾號(hào)后臺(tái)回復(fù) per_cpu ?獲取)
? ? ? ? ? ? ? ? ? ? ? ?
推薦閱讀:
第4章 第三節(jié) 內(nèi)核同步
第4章 原子操作 第二節(jié)
總結(jié)
以上是生活随笔為你收集整理的第四章 第四节 per_cpu的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用Scikit Learn的分类器探索
- 下一篇: pdfminer将pdf转为csv