在 2.6 内核中,随处能够见到 likely() 和 unlikely() 的身影,那么为什么要用它们?它们之间有什么差别?

首先要明白:

     if(likely(value)) 等价于 if(value)

     if(unlikely(value)) 也等价于 if(value)

也就是说 likely() 和 unlikely() 从阅读和理解代码的角度来看。是一样的!。!

#define likely(x)       __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)

__builtin_expect() 是 GCC (version >= 2.96)提供给程序猿使用的,目的是将“分支转移”的信息提供给编译器,这样编译器能够对代码进行优化。以降低指令跳转带来的性能下降。

__builtin_expect((x),1) 表示 x 的值为真的可能性更大;

__builtin_expect((x),0) 表示 x 的值为假的可能性更大。

也就是说,使用 likely() ,运行 if 后面的语句 的机会更大,使用unlikely(),运行else 后面的语句的机会更大。

比如以下这段代码,作者就觉得 prev 不等于 next 的可能性更大,

if (likely(prev != next)) {
next->timestamp = now;
...
} else {
...;
}

通过这样的方式,编译器在编译过程中,会将可能性更大的代码紧跟着起面的代码,从而降低指令跳转带来的性能上的下降。

另外内核2.6.31.5中likely和unlikely另一种定义:
# ifndef likely
# define likely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1))
# endif # ifndef unlikely
# define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0))
# endif

举个样例(内核版本号2.6.22.6):/kernel/shed.c中有一段:

if (likely(!active_balance)) {
/* We were unbalanced, so reset the balancing interval */
sd->balance_interval = sd->min_interval;
} else {
/*
* If we've begun active balancing, start to back off. This
* case may not be covered by the all_pinned logic if there
* is only 1 task on the busy runqueue (because we don't call
* move_tasks).
*/
if (sd->balance_interval max_interval)
sd->balance_interval *= 2;
}

编译过程中,会将if后面{}里的内容编译到前面。else 后面{}里的内容编译到后面。若将likely换成unlikely 则正好相反。

总之,likely与unlikely互换或不用都不会影响程序的正确性。

但可能会影响程序的效率。

Linux 内核中 likely 与 unlikely 的宏定义解析的更多相关文章

  1. Linux内核中的fastcall和asmlinkage宏

    代码中看见:#define _fastcall 所以了解下fastcall -------------------------------------------------------------- ...

  2. 《linux 内核全然剖析》 笔记 CODE_SPACE 宏定义分析

    在memory.c里面.遇到一个宏定义,例如以下: #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \ current->sta ...

  3. Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法与解析【转】

    转自:http://blog.csdn.net/hzn407487204/article/details/7995041 在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设 ...

  4. Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法与解析

    ref from : http://blog.csdn.net/zhuxiaoping54532/article/details/49680537 main 在驱动程序里, ioctl() 函数上传送 ...

  5. Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法

    #define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0) #define _IOR(type,nr,size)    _IOC(_IOC_RE ...

  6. (十)Linux内核中的常用宏container_of

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...

  7. Linux内核中的常用宏container_of

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...

  8. Linux内核中的常用宏container_of其实很简单【转】

    转自:http://blog.csdn.net/npy_lp/article/details/7010752 开发平台:Ubuntu11.04 编 译器:gcc version 4.5.2 (Ubun ...

  9. 嵌入式C语言自我修养 01:Linux 内核中的GNU C语言语法扩展

    1.1 Linux 内核驱动中的奇怪语法 大家在看一些 GNU 开源软件,或者阅读 Linux 内核.驱动源码时会发现,在 Linux 内核源码中,有大量的 C 程序看起来“怪怪的”.说它是C语言吧, ...

随机推荐

  1. Ubuntu下安装JDK1.7

    Ubuntu操作系统下如何手动安装JDK1.7呢?本文是我经历的全过程. Ubuntu版本:12.04 LTS JDK版本:1.7.0_04 安装目录:/usr/local/development/j ...

  2. awk打印指定列以后的所有内容

    (1)使用awk将文件的前12列替换为空 awk '{for(i=1;i<=12;i++)$i="";print $0}' localhost_access_log //写法 ...

  3. JAVA-JAVA WEB开发工具下载与安装

    1.JAVA SE(JDK下载)程序名:jdk-8u141-windows-x64.exe下载地址:http://www.oracle.com/technetwork/java/javase/down ...

  4. Oracle 外键约束子表、父表

    CREATE TABLE employees(     employee_id      NUMBER(6),     last_name        VARCHAR2(25) NOT NULL, ...

  5. 【WPF/C#】拖拽Image图片控件

    需求:使得Image图片控件能够被拖动. 思路:关键是重写Image控件的几个鼠标事件,实现控制. 前台: <Image Source="C:\Users\Administrator\ ...

  6. Java并发(四)多线程开销

    从单线程应用转变为多线程应用并不只是带来好处.这种转变也会带来一定得开销得.并不是所有时候都要把你的应用编程多线程的.你应该明白这样做确实会带来好处,而且这种好处要比开销大.如果你不确定的话,要试着去 ...

  7. [uart]2.tty和uart的函数调用流程

    以下是在include/uapi/linux/tty.h中定义了现有的线规号,如果需要定义新的,则需要在后面添加新的 /* line disciplines */ #define N_TTY 0 #d ...

  8. CentOS ext4 磁盘分区 格式化 挂载

    [root@appserver ~]# df -h /*查看现有分区情况*/文件系统 容量 已用 可用 已用%% 挂载点/dev/vda1 9.9G 8.2G 1.2G 88% /tmpfs 3.9G ...

  9. linux 内核参数调整优化网络

    Linux系统内核设置优化tcp网络,# vi /etc/sysctl.conf,添加以下内容 net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies.当出现SYN等待 ...

  10. iOS开发小技巧--富文本字典集合中的Key都是OC中的常量字符串