日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转】内核代码摘记

發(fā)布時間:2025/3/15 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】内核代码摘记 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

atomic_inc_not_zero(),atomic_add_unless(), atomic_cmpxchg()

atomic_表示原子操作,不被任何其他操作打擾,一次完成。

------------------------------------------------------------------------------------------------------------

#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

?//atomic_add_unless(v,a,u)表示如果v的值不等于u就加a,返回1。如果v的值等于u就返回0。

//也就是說,v的值要滿足不等于u的條件才加a,否則v的值不變。返回值呢就是加了就返回1,沒加就返回0。

static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
?int c, old;
?c = atomic_read(v);
?for (;;) {
??if (unlikely(c == (u)))
???break;
??old = atomic_cmpxchg((v), c, c + (a)); //如果v的值等于c就加a,old=c。如果v的值不等于c,old=v的值;
??if (likely(old == c))
???break;
??c = old;
?}
?return c != (u);
}

//?__raw_cmpxchg(ptr, old, new)表示,如果*ptr等于old, *ptr=new, 返回old;如果*ptr不等于old,*ptr不變,返回*ptr。

//也就是說,ptr的值要滿足等于old的條件才改變,不滿足條件不改變。返回值始終是原來*ptr的值。

#define __raw_cmpxchg(ptr, old, new, size, lock)???\
({?????????\
?__typeof__(*(ptr)) __ret;?????\
?__typeof__(*(ptr)) __old = (old);????\
?__typeof__(*(ptr)) __new = (new);????\
?switch (size) {???????\
??case 4:????????\
??asm volatile(lock "cmpxchgl %1,%2"???\
??????? : "=a"(__ret)????\
??????? : "r"(__new), "m"(*__xg(ptr)), "0"(__old)?\
??????? : "memory");????\
??break;???????\
??}????????\
?__ret;????????\
})

//cmpxchgl? %src,%dest

//Compares the accumulator (8-32 bits) with "dest". If equal the"dest" is loaded with "src", otherwise the accumulator is loaded with "dest".

------------------------------------------------------------------------------------------------------------

smp_processor_id()

涉及到per_cpu變量定義和訪問

------------------------------------------------------------------------------------------------------------

DECLARE_PER_CPU(int, cpu_number);

# define smp_processor_id() raw_smp_processor_id()

#define raw_smp_processor_id() (percpu_read(cpu_number))

#define percpu_read(var)?percpu_from_op("mov", per_cpu__##var,?\
??????????? "m" (per_cpu__##var))

#define percpu_from_op(op, var, constraint)??\
({???????\
?typeof(var) pfo_ret__;????\
?switch (sizeof(var)) {????\
?case 4:??????\
??asm(op "l "__percpu_arg(1)",%0"??\
????? : "=r" (pfo_ret__)???\
????? : constraint);???\
??break;?????\
??}??????\
?pfo_ret__;?????\
})

其中

?#define __stringify_1(x...)?#x?
?#define __stringify(x...)?__stringify_1(x)
?#define __percpu_seg??fs
?#define __percpu_arg(x)??"%%"__stringify(__percpu_seg)":%P" #x
?//printf("__percpu_arg(x)=%s\n",__percpu_arg(1)); //輸出?("__percpu_arg(x)=%%fs:%P1
?//printf("__stringify(__percpu_seg)=%s\n",__stringify(__percpu_seg));?//輸出?__stringify(__percpu_seg)=fs

// 最后smp_processor_id()匯編部分展開為

??asm("movl %%fs:%P1,%0"??//fs: cpu_number表示fs段中cpu_number偏移處
????? : "=r" (pfo_ret__)??//pfo_ret__是輸出部%0,q,表示寄存器eax、ebx、ecx或edx中的一個
????? : "m"(per_cpu__cpu_number));

//“加載全局/中斷描述符表”中把__KERNEL_PERCPU段選擇子賦給了fs了嗎,fs: cpu_number就獲得了當前存放在__KERNEL_PERCPU段中cpu_number偏移的內(nèi)存中
------------------------------------------------------------------------------------------------------------

這里主要是宏的運用

?#define __stringify_1(x...)?#x?
?#define __stringify(x...)?__stringify_1(x)??//如果這里直接定義#define __stringify(x...)?#x不行,__percpu_seg沒法替換成fs
?#define __percpu_seg??fs

注意__percpu_seg在?__stringify(x...)?里被解析成__stringify_1(fs),再被解析成"fs"。

參考??激活第一個CPU

asmlinkage_protect(n, ret, args...)

防止編譯器在調(diào)用函數(shù)前后改變caller()的寄存器值

------------------------------------------------------------------------------------------------------------

#define asmlinkage_protect(n, ret, args...) \
?? ?__asmlinkage_protect##n(ret, ##args)
#define __asmlinkage_protect_n(ret, args...) \
?? ?__asm__ __volatile__ ("" : "=r" (ret) : "0" (ret), ##args)
#define __asmlinkage_protect3(ret, arg1, arg2, arg3) \
?? ?__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3))

------------------------------------------------------------------------------------------------------------

例子:

------------------------------------------------------------------------------------------------------------

externintcallee(inta,intb);
staticintc;
intcall(inta,intb){? ? ? ?intret=callee(c, b);? ? ? ? __asm__("":"=r"(ret):"0"(ret),"g"(a),"g"(b)); //這句沒有任何實質(zhì)操作,卻影響編譯器行為,強迫把ret,a,b放入棧中。
? ? ? ?returnret;

}

//gcc -fomit-frame-pointer -fno-inline -O2 -S tail_call.c

//看它對應(yīng)的匯編代碼

------------------------------------------------------------------------------------------------------------

例子:系統(tǒng)調(diào)用sys_open()

------------------------------------------------------------------------------------------------------------

SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, int, mode)
{
?? ?long ret;
?? ?if (force_o_largefile())
?? ??? ?flags |= O_LARGEFILE;

?? ?ret = do_sys_open(dfd, filename, flags, mode);
?? ?/* avoid REGPARM breakage on x86: */
?? ?asmlinkage_protect(4, ret, dfd, filename, flags, mode);
?? ?return ret;
}

//其中asmlinkage_protect展開為__asm__ __volatile__ ("" : "=r" (ret) : "0" (ret), "g" (filename), "g" (flags), "g" (mode));

------------------------------------------------------------------------------------------------------------

參考尾部調(diào)用優(yōu)化

宏#和##的區(qū)別

一般,宏中用#組合字符串,用##組合變量名。

例子:

------------------------------------------------------------------------------------------------------------

#include <stdio.h>
#define str(n) "str"#n
#define dat(n) dat##n
#define max(x,y) (x)>(y)?(x):(y)

void main()
{
?int a = 1;
?int b = 2;
?int dat(1) = 3;
?int c = max(a,b);?
?printf("str(n)=%s,dat(n)=%d",str(8),dat(1)); //輸出 str(n)=str8,dat(n)=3

?}

------------------------------------------------------------------------------------------------------------

container_of(ptr, type, member)

ptr是結(jié)構(gòu)類型type的成員名member,container_of(ptr, type, member) 得到地址ptr所在結(jié)構(gòu)體的地址。

------------------------------------------------------------------------------------------------------------

#define container_of(ptr, type, member) ({???\
?const typeof( ((type *)0)->member ) *__mptr = (ptr);?\?
?(type *)( (char *)__mptr - offsetof(type,member) );})

------------------------------------------------------------------------------------------------------------

定義一個指針變量__mptr,它的類型是typeof( ((type *)0)->member ) *。

typeof( ((type *)0)->member ),通過結(jié)構(gòu)類型一個成員名稱可以得到該成員的數(shù)據(jù)類型。

offsetof(type,member) ,結(jié)構(gòu)類型和一個成員名稱的offsetof,得到該成員離結(jié)構(gòu)頭的距離。?

smp_mb(),mb(),barrier()

#define barrier() __asm__ __volatile__("": : :"memory")

內(nèi)存屏障,memory強制gcc編譯器假設(shè)RAM所有內(nèi)存單元均被匯編指令修改,這樣cpu中的registers和cache中已緩存的內(nèi)存單元中的數(shù)據(jù)將作廢。cpu將不得不在需要的時候重新讀取內(nèi)存中的數(shù)據(jù)。這就阻止了cpu又將registers,cache中的數(shù)據(jù)用于去優(yōu)化指令。

參考 內(nèi)存屏障(memory barrier)

hi~,北風(fēng)北的豬最后編輯于2011.03.08

轉(zhuǎn)載于:https://www.cnblogs.com/mull/archive/2013/06/03/4477812.html

總結(jié)

以上是生活随笔為你收集整理的【转】内核代码摘记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。