在内核代码中经常会看到unlikely和likely的踪影。他们实际上是定义在 linux/compiler.h 中的两个宏。

  #define likely(x)    __builtin_expect(!!(x), 1)

  #define unlikely(x)  __builtin_expect(!!(x), 0)

  这里的__built_expect()函数是gcc的內建函数。

  至于为什么要在内核代码中使用这两个宏,主要的目的是为了进行代码的优化,提高系统执行速度。

  比如 :

  if (likely(a>b)) {

  fun1();

  }

  if (unlikely(a<b)) {

  fun2();

  }

  这里就是程序员可以确定 a>b 在程序执行过程中出现的可能相比较大,因此使用了likely()告诉编译器将fun1()函数的二进制代码紧跟在前面程序的后面,这样就cache在预取数据时就可以将fun1()函数的二进制代码拿到cache中。这样,也就增加了cache的命中率。

  同样的,unlikely()的作用就是告诉编译器,a<b 的可能性很小所以这里在编译时,将fun2()的二进制代码尽量不要和前边的编译在一块。

  我们不用对likely和unlikely感到迷惑,需要知道的就是 if(likely(a>b)) 和 if(a>b)在功能上是等价的,同样 if(unlikely(a<b)) 和 if(a<b) 的功能也是一样的。不一样的只是他们声称的二进制代码有所不同,这一点我们也可以从他们的汇编代码中看到。

  比如下面的代码:

  #include <stdio.h>

  #define unlikely(x) __builtin_expect(!!(x), 0)

  #define likely(x) __builtin_expect(!!(x), 1)

  int main()

  {

  int a=2,b=4;

  if(unlikely(a<b)) {

  printf("in the unlikely,is not your expecting!\n");

  } else {

  printf("in the unlikely, is your expecting\n");

  }

  if(likely(a<b)) {

  printf("in the likely, is your expecting\n");

  }

  return 0;

  }

  执行结果:

  in the unlikely,is not your expecting!

  in the likely, is your expecting

  总之,likely和unlikely的功能就是增加cache的命中率,提高系统执行速度。

内核中likely和unlikely宏定义的更多相关文章

  1. C中的预编译宏定义

     可以用宏判断是否为ARC环境 #if _has_feature(objc_arc) #else //MRC #endif C中的预编译宏定义 -- 作者: infobillows 来源:网络 在将一 ...

  2. iOS --- 总结Objective-C中经常使用的宏定义(持续更新中)

    将iOS开发中经常使用的宏定义整理例如以下,仅包括Objective-C. 而对于Swift,不能使用宏,则能够定义全局函数或者extension.请參考博客iOS - 总结Swift中经常使用的全局 ...

  3. linux中offsetof与container_of宏定义

    linux内核中offsetof与container_of的宏定义 #define offsetof(TYPE, MEMBER)    ((size_t) &((TYPE *)0)->M ...

  4. Linux内核驱动基础(一)常用宏定义【转】

    转自:http://blog.csdn.net/tommy_wxie/article/details/9427081 一: __init和__initdata  : __exit和__exitdata ...

  5. VC中预处理指令与宏定义详解

    刚接触到MFC编程的人往往会被MFC 向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具.使用它们可以进行简单的源代码控制,版本控制,预警或者完成一些特殊的功能. 一个 ...

  6. C++ 中 #ifndef, #define, #endif 宏定义

    目的:为了保证包含的内容只被程序(include) 和编译了一次.判断预处理器常量是否已被定义. 预编译将所有头文件(#include"XXX.h")用头文件中的内容来替换,头文件 ...

  7. 在oc中一些常用的宏定义总结

    1.打印CGRect,Size,Point #define NSLogRect(rect) NSLog(@"%s x:%.4f, y:%.4f, w:%.4f, h:%.4f", ...

  8. IOS开发,知识点小结,ios开发中经常使用的宏定义总结

    IOS开发,从应用跳转到用浏览器打开网页: [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http:// ...

  9. iOS开发中常用到的宏定义

    1.首次启动判断: #define First_Launched @"firstLaunch" 2.ios7系统判断: #define IsIOS7 ([[[UIDevice cu ...

随机推荐

  1. poj 1017 装箱子(模拟+贪心)

    Description A factory produces products packed in square packets of the same height h and of the siz ...

  2. Codeforces Round #201.C-Alice and Bob

    C. Alice and Bob time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  3. 二分mid的取法

    二分的两种形式: 1.范围缩小时,r = mid,l = mid + 1,取中间值时,mid = (l + r) >> 1. 2.范围缩小时,l = mid,r = mid - 1,取中间 ...

  4. oracle中更新关键字merge和 with as关键字

    merge是oracle特有的语句,两表关联操作(增.删.改)就效率非常高 merge into table_name alias1 using (table|view|sub_query) alia ...

  5. JS框架_(JQuery.js)文章全屏动画切换

    百度云盘 传送门 密码:anap 文章全屏动画切换效果 <!doctype html> <html lang="zh"> <head> < ...

  6. scrollWidth、clientWidth、offsetWidth、width的区别

    scrollWidth:对象的实际内容的宽度,不包边线宽度,会随对象中内容超过可视区后而变大. clientWidth:对象内容的可视区的宽度,不包滚动条等边线,会随对象显示大小的变化而改变. off ...

  7. 当 LAST_INSERT_ID() 带有参数时# 清空重来

    [root@yejr.me]> truncate table t; # 插入1条新记录[root@yejr.me]> insert into t select 0,rand()*1024; ...

  8. sql server关键字大全

    保留关键字 Microsoft® SQL Server™ 2000 使用保留关键字定义.操作和访问数据库.保留关键字是 SQL Server 使用的 Transact-SQL 语言语法的一部分,用于分 ...

  9. C# base64 加密解密

    1.base64  to  string string strPath = "aHR0cDovLzIwMy44MS4yOS40Njo1NTU3L1 9iYWlkdS9yaW5ncy9taWR ...

  10. 怎样用 Bash 编程:逻辑操作符和 shell 扩展

    学习逻辑操作符和 shell 扩展,本文是三篇 Bash 编程系列的第二篇. Bash 是一种强大的编程语言,完美契合命令行和 shell 脚本.本系列(三篇文章,基于我的 三集 Linux 自学课程 ...