在Linux内核中可能()和不可能()

在2.6内核中,您可以看到任何可能()和不可能()的影子,所以它们为什么要使用它们之间的差异呢



首先,它应该是明确的:



如果(可能(值))等于(值)



如果(不可能的(值))也等价于如果(值)



也就是说,从阅读和理解代码的角度来看,可能()和不可能()是相同的!



这两个宏在内核中定义如下:



#定义可能(x)__builtin_expect((x),1)



#定义可能__builtin_expect((x)(x),0)



__builtin_expect(GCC)(版本> = 2.96)程序员使用,目的是分支;编译器提供的信息,编译器可以对代码进行优化,减少跳转指令引起的性能退化。



__builtin_expect((x),1)表明,x的值是更真实。



__builtin_expect((x),0)表明,x的值是更可能是错误的。



也就是说,使用可能的(),在后面执行语句的机会更大,使用不太可能(),在后面执行更多语句的机会。



例如,下面的代码,作者认为,沪指不等于可能性下。



如果(可能(沪指!=下一步){



接下来>时间戳=现在;







其他{ }



…;



}



这样,在编译过程中,编译器将遵循更可能遵循更可能的代码的代码,从而减少指令跳转造成的性能下降。



下面是两个加深理解的例子:



第一个例子:1。C



Int testfun(int x)



{



如果(__builtin_expect(x,0)){



我们指导编译器,其他块更可能



x=5;



x=x;



其他{ }



x=6;



}



返回x;



}



在这个例子中,我们认为x更可能是0。



编译后的汇编指令,观察通过objdump。在我的2.4内核机器上,结果如下:



GCC O2- C C # 1。



# objdump -d example1. O



拆卸部分.文本:



00000000:



0:55推EBP



1:89 E5 MOV EBP ESP,



3:8B 4508 MOV 0x8(EBP),êx



6:85 C0测试êx,êx



8:7507 JNE 11



06000000乐章:B8 0x6美元,êx



F:C9离开



10:C3 RET



11:B8 19000000乐章为0x19,êx



16:EB F7 JMP F



你可以看到,编译器使用JNE(不等跳转)指令,并在其他块中的代码进行编码。



8:7507 JNE 11



06000000乐章:B8 0x6美元,êx



第二例子:例子。C



Int testfun(int x)



{



如果(__builtin_expect(x,1)){



我们指导编译器,块更可能



x=5;



x=x;



其他{ }



x=6;



}



返回x;



}



在这个例子中,我们认为x更可能小于0。



编译后的汇编指令,观察通过objdump。在我的2.4内核机器上,结果如下:



GCC O2- C C #例子。



# objdump -d例子啊



拆卸部分.文本:



00000000:



0:55推EBP



1:89 E5 MOV EBP ESP,



3:8B 4508 MOV 0x8(EBP),êx



6:85 C0测试êx,êx



8:7407乙脑11



19000000乐章:B8 0x19美元,êx



F:C9离开



10:C3 RET



11:B8 06000000乐章0x6美元,êx



16:EB F7 JMP F



编译器使用乙脑(等跳转)指令,if块中的代码后面跟着代码。



8:7407乙脑11



19000000乐章:B8 0x19美元,êx