linux中的likely与unlikely简介

likely() 与 unlikely()是内核(2.6的版本应该都有)中定义的两个宏。位于/include/linux/compiler.h中,
具体定义如下:
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

__builtin_expect是gcc(版本>=2.96,网上写的,我没验证过)中提供的一个预处理命令(这个名词也是网上写的,我想叫函数更好些),有利于代码优化。gcc(version 4.4.0)具体定义如下:
long __builtin_expect (long exp, long c) [Built-in Function]

注解为:
You may use __builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (‘-fprofile-arcs’), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect.The return value is the value of exp, which should be an integral expression. The semantics of the built-in are that it is expected that exp == c.

它的意思是:我们可以使用这个函数人为告诉编绎器一些分支预测信息“exp==c” 是“很可能发生的”。

#define likely(x) __builtin_expect(!!(x), 1)也就是说明x==1是“经常发生的”或是“很可能发生的”。
使用likely ,执行if后面语句的可能性大些,编译器将if{}是的内容编译到前面, 使用unlikely ,执行else后面语句的可能性大些,编译器将else{}里的内容编译到前面。这样有利于cpu预取,提高预取指令的正确率,因而可提高效率。

举个例子(内核版本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;
}

返回栏目页:http://www.bianceng.cnhttp://www.bianceng.cn/OS/Linux/

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

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

if(likely(foo))  //认为foo通常为1

if(unlikely(foo)) //认为foo通常为0

说到底,这个宏的作用在于更好的编译,以获得更高的执行效率。

另外,likely或是unlikely要定义成__builtin_expect(!!(x), 1),而不直接用__builtin_expect(x, 1)?" !!(x) "与" x "的不同在于c中没有bool类型,这里是为了将x变为0或1真假类型。

另外内核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

原版blog.csdn.net/tommy_wxie/article/details/7384641,有改动

时间: 2024-08-02 19:12:06

linux中的likely与unlikely简介的相关文章

Linux中的stat命令使用简介

  ls 命令可能是每一个 Unix 使用者第一个学习的命令之一, 但它仅仅显示了 stat 命令能给出的信息的一小部分. stat 命令从文件的索引节点获取信息. 正如你可能已经了解的那样, 每一个系统里的文件都存有三组日期和时间, 它们包括最近修改时间(即使用 ls -l 命令时显示的日期和时间), 最近状态改变时间(包括对文件重命名)和最近访问时间. 使用长列表模式查看文件信息, 你会看到类似下面的内容: 代码如下: $ ls -l trythis -rwx------ 1 shs uni

简介Linux中cp和mv搭配{,}在shell当中的用法

  这篇文章主要介绍了简介Linux中cp和mv搭配{,}在shell当中的用法,作者举了四个这样的大括号扩展示例,需要的朋友可以参考下 经常会在博客或者论坛看到类似下面的命令 大括号扩展 Brace expansion { } shell 作用 ? 1 cp /etc/httpd/httpd.{,.bakup} 或者是 ? 1 mv resume{z,}.doc 那么,在uinx / linux shell命令中是什么意思?起什么作用呢? { } 并没有什么实际的含义,但是却可以作为Brace

Linux 中的静态库和动态库简介及生成过程示例

在实际的软件开发项目中,不是每一行代码都需要我们亲自写.在我们的软件产品中,有一些代码(尤其是函数)的出现频率很高,它们可以被当作公共代码来反复使用.为了避免重复劳动,我们就把这些公共代码编译为库文件,供需要的程序调用.在Linux中,库分为静态库和动态库两种. 本文对静态库和动态库进行了详细的介绍,并用实际的C代码演示了这两种库的生成过程. 一.静态库和动态库简介 众所周知,程序一般需要经过预处理.编译.汇编和链接这几个步骤才能变成可执行的程序.在实际的软件开发中,对于一些需要被许多模块反复使

Linux中的静态库和动态库简介及生成过程示例

[文章摘要] 在实际的软件开发项目中,不是每一行代码都需要我们亲自写.在我们的软件产品中,有一些代码(尤其是函数)的出现频率很高,它们可以被当作公共代码来反复使用.为了避免重复劳动,我们就把这些公共代码编译为库文件,供需要的程序调用.在Linux中,库分为静态库和动态库两种. 本文对静态库和动态库进行了详细的介绍,并用实际的C代码演示了这两种库的生成过程. 一.静态库和动态库简介 众所周知,程序一般需要经过预处理.编译.汇编和链接这几个步骤才能变成可执行的程序.在实际的软件开发中,对于一些需要被

Unix/Linux中/usr目录简介

在Linux系统中,有一个很重要的目录--/usr目录.关于这个目 录名称的由来,网上主要有下面几种说法: user的缩写 User Shareable Read-only的缩写 Unix/User System Resources的缩写 Unix/User Software Resources的缩写 目前大多数版本的Linux中/usr目录主要放置的是可执行文件和先关库文件, 因此user好像不太可能. 查阅了相关的资料,关于/usr目录起源的说法如下: /usr usually contai

linux中的strip命令简介------给文件脱衣服【转】

转自:http://blog.csdn.net/stpeace/article/details/47090255 版权声明:本文为博主原创文章,转载时请务必注明本文地址, 禁止用于任何商业用途, 否则会用法律维权. 作为一名Linux开发人员, 如果没有听说过strip命令, 那是很不应该的. strip这个单词, 大家应该早就学过了, 你就记住是脱衣服就行了, 别的不要多想. 在linux中, strip也有脱衣服的含义, 具体就是从特定文件中剥掉一些符号信息和调试信息. 我们来看main.c

浅析Linux中的时间编程和实现原理(一) Linux应用层的时间编程

引子 我们都生活在时间中,但却无法去思考它.什么是时间呢?似乎这是一个永远也不能被回答的问题.然而作为一个程序员,在工作中,总有那么几次我必须思考什么是时间.比如,需要知道一段代码运行了多久:要在 log 文件中记录事件发生时的时间戳:再比如需要一个定时器以便能够定期做某些计算机操作.我发现,在计算机世界中,时间在不同场合也往往有不同的含义,让试图思考它的人感到迷茫.但值得庆幸的是,Linux 中的时间终究是可以理解的.因此我打算讨论一下有关时间的话题,尝试着深入理解 Linux 系统中 C 语

Linux中用于进程控制的exec函数族

1.简介 在Linux中,并不存在exec()函数,exec指的是一组函数,一共有6个,分别是: #include <unistd.h> extern char **environ; int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *path, const char *arg, ..., cha

如何在Linux中列出通过RPM或者DEB包安装的文件

你是否想要了解安装包中各个文件在 Linux 系统中安装(位于)的位置?我们将在本文介绍如何列出文件的来源,或存在于某个特定包或者一组软件包中的文件. 这篇文章可以帮你轻松地找到重要的软件包文件,如配置文件.帮助文档等.我们来看看找出文件在哪个包中或者从哪个包中安装的几个方法: 如何列出 Linux 中全部已安装软件包的文件 你可以使用 repoquery 命令,它是 yum-utils 的一部分,用来列出给定的软件包在 CentOS/RHEL 系统上安装的文件. 要安装并使用 yum-util