linux核心中的每cpu變數

2021-09-06 12:34:21 字數 2053 閱讀 4898

一、linux中的每cpu變數

看linux核心**的時候,會發現大量的per_cpu(name, cpu),get_cpu_var(name)等出現cpu字眼的語句。從語句的意思可以看出是要使用與當前cpu相關的乙個變數,不過檢視這個變數的定義,總是有這樣乙個巨集:define_per_cpu(type, name),將這個巨集展開成下面的語句:

__attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name

,這個語句就是在.data.percpu段中定義type型別的per_cpu##name變數。看到這裡,我就不明白了,既然只是在乙個段中定義了乙個變數,那為什麼每個cpu都有乙個這樣的變數呢?

二、linux中的每cpu變數的實現

這應該算是linux核心產生每cpu變數的乙個技巧吧!首先我們來看下鏈結linux核心的鏈結指令碼,這個指令碼主要用來控制gcc怎樣鏈結linux中的各個段並最終產生linux核心映像檔案的,不明白鏈結指令碼的可以到網上搜下,大把的資料。這個指令碼檔案叫vmlinux.lds.s,放在arch/i386/kernel目錄中,在這個檔案中有下面一段**:

__per_cpu_start =.;

.data.percpu :

__per_cpu_end = .;

這段**定義了兩個符號,分別是__per_cpu_start和_per_cpu_end,它們標識了段data.percpu的起始和結束位址。而段.data.percpu是通過各個物件檔案中的.data.percpu段合併起來的,也就是說前面我們定義的per_cpu##name變數終止都會放在.data.percpu段中,而這個段的起始位址和結束位址分別是__per_cpu_start和_per_cpu_end。到了這一步,貌似還是沒有看出per_cpu##name變數怎麼會對每個cpu都有乙個。

在linux初始化的時候,會呼叫函式setup_per_cpu_areas來真正的把per_cpu##name變數賦值給每個cpu,具體**如下:

static

void __init setup_per_cpu_areas(void)}

#endif /* !__generic_per_cpu */

**中引用了由鏈結器產生的變數__per_cpu_start和 __per_cpu_end,在它們之間的記憶體空間存放了所有的每cpu變數,總大小為size。然後核心通過alloc_bootmem給每個cpu都分配了乙個這麼大小的記憶體空間。下面的for迴圈把__per_cpu_start和 __per_cpu_end之間的所有cpu變數拷貝乙份到每個cpu對應的記憶體空間中,並用__per_cpu_offset[i]來存放第i個cpu對應的每cpu變數的起始位址。

不過為什麼__per_cpu_offset[i]存放的是ptr - __per_cpu_start,而不是ptr,原因很簡單,當我們用per_cpu##name來訪問某個cpu上的每cpu變數時,我們應該這樣訪問:獲取該cpu對應每cpu變數的起始位址+per_cpu##name的偏移量。我們現在展開巨集per_cpu(var, cpu):

*(&per_cpu__##var + __per_cpu_offset[cpu])=*(ptr+&per_cpu__##var- __per_cpu_start)

這樣就訪問了在cpu上的var變數了。

三、每cpu變數的作用

從上面可以看出,為了定義乙個變數,繞了乙個很大的彎,為什麼要定義這樣的每cpu變數?這其實和linux內部的同步有關,因為如果我們把變數定義成所有cpu都可以訪問的,那麼就必須用同步機制來保證cpu對這個變數的互斥訪問,很明顯這是要花費時間的,linux核心為了能夠減少這種時間開銷,就在每個cpu都定義了乙個一模一樣的變數,這樣每個cpu都使用自己的變數,而不會去訪問其它cpu上的變數,也就沒有了同步的開銷。不過在使用每cpu變數時,必須保證禁用核心搶占。因為核心搶占還是會使每cpu變數產生競爭條件,例如乙個核心控制路徑獲得了它的每cpu變數本地副本的位址,然後它又被搶占跑到另乙個cpu上去了,但仍然使用原來cpu上的每cpu變數。

linux核心中的每cpu變數

摘自 一 linux中的每cpu變數 看linux核心 的時候,會發現大量的per cpu name,cpu get cpu var name 等出現cpu字眼的語句。從語句的意思可以看出是要使用與當前cpu相關的乙個變數,不過檢視這個變數的定義,總是有這樣乙個巨集 define per cpu t...

每 CPU 的變數

每 cpu 變數是乙個有趣的 2.6 核心的特性.當你建立乙個每 cpu變數,系統中每個處理器獲得它自己的這個變數拷貝.這個可能象乙個想做的奇怪的事情,但是它有自己的優點.訪問每 cpu變數不需要 幾乎 加鎖,因為每個處理器使用它自己的拷貝.每 cpu 變數也可存在於它們各自的處理器快取中,這樣對於...

每 CPU 的變數

每 cpu 變數是乙個有趣的 2.6 核心的特性.當你建立乙個每 cpu變數,系統中每個處理器獲得它自己的這個變數拷貝.這個可能象乙個想做的奇怪的事情,但是它有自己的優點.訪問每 cpu變數不需要 幾乎 加鎖,因為每個處理器使用它自己的拷貝.每 cpu 變數也可存在於它們各自的處理器快取中,這樣對於...