DEFINE_PER_CPU
轉自 http://www.unixresources.net/linux/clf/linuxK/archive/00/00/47/91/479165.html
首先,在arch/i386/kernel/vmlinux.lds中有
/*will be free after init*/
.=ALIGN(4096);
__init_begin=.;
/*省略*/
.ALIGN(32);
__per_cpu_start=.;
.data.percpu:{*(.data.percpu)}
__per_cpu_end=.;
.=ALIGN(4096);
__init_end=.;
/*freed after init ends here*/
這說明__per_cpu_start和__per_cpu_end標識.data.percpu這個section的開頭和結尾
并且,整個.data.percpu這個section都在__init_begin和__init_end之間,
也就是說,該section所占內存會在系統啟動后釋放(free)掉
因為有
#define DEFINE_PER_CPU(type, name)?
__attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
所以
static DEFINE_PER_CPU(struct runqueue, runqueues);?
會擴展成
__attribute__((__section__(".data.percpu"))) __typeof__(struct runqueue)
per_cpu__runqueues;
也就是在.data.percpu這個section中定義了一個變量per_cpu__runqueues,
其類型是struct runqueue。事實上,這里所謂的變量per_cpu__runqueues,
其實就是一個偏移量,標識該變量的地址。
--------------------
其次,系統啟動后,在start_kernel()中會調用如下函數
在該函數中,為每個CPU分配一段專有數據區,并將.data.percpu中的數據拷貝到其中,
每個CPU各有一份。由于數據從__per_cpu_start處轉移到各CPU自己的專有數據區中了,
因此存取其中的變量就不能再用原先的值了,比如存取per_cpu__runqueues
就不能再用per_cpu__runqueues了,需要做一個偏移量的調整,
即需要加上各CPU自己的專有數據區首地址相對于__per_cpu_start的偏移量。
在這里也就是__per_cpu_offset[i],其中CPU i的專有數據區相對于
__per_cpu_start的偏移量為__per_cpu_offset[i]。
這樣,就可以方便地計算專有數據區中各變量的新地址,比如對于per_cpu_runqueues,
其新地址即變成per_cpu_runqueues+__per_cpu_offset[i]。
經過這樣的處理,.data.percpu這個section在系統初始化后就可以釋放了。
--------------------
再看如何存取per cpu的變量
對于__get_cpu_var(runqueues),將等效地擴展為
__per_cpu_offset[smp_processor_id()] + per_cpu__runqueues
并且是一個lvalue,也就是說可以進行賦值操作。
這正好是上述per_cpu__runqueues變量在對應CPU的專有數據區中的新地址。
由于不同的per cpu變量有不同的偏移量,并且不同的CPU其專有數據區首地址不同,
因此,通過__get_cpu_var()便訪問到了不同的變量。
--END
總結
以上是生活随笔為你收集整理的DEFINE_PER_CPU的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 调试与分析
- 下一篇: 女人梦到西瓜是什么意思