Chinaunix首页 | 论坛 | 博客
  • 博客访问: 851854
  • 博文数量: 119
  • 博客积分: 2493
  • 博客等级: 大尉
  • 技术积分: 2363
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-03 14:00
文章分类

全部博文(119)

文章存档

2013年(19)

2012年(100)

分类: LINUX

2012-06-04 10:34:39

        linux kernel中定义了很多的带参宏,而那些宏完全可以复用到用户态编程中,比如说kernel中的contain_of这个宏,还有ARRAY_SIZE这个宏,这些宏都设计的很精典,其实有时我觉得编程主要还是复用人家的代码。
----------------------------------------------------------------------
1, ARRAY_SIZE
This macro is defined in include/linux/kernel.h ARRAY_SIZE(x) is used to get the number 
of elements in an array.
  1. #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
以后再用户态下编程如果需要求数组的长度就可以把这个宏拷贝过去。
----------------------------------------------------------------------
2,contain_of
The container_of macro is defined in include/linux/kernel.h as following:

  1. /**
  2.  * container_of - cast a member of a structure out to the containing structure
  3.  * @ptr: the pointer to the member.
  4.  * @type: the type of the container struct this is embedded in.
  5.  * @member: the name of the member within the struct.
  6.  *
  7.  */
  8. #define container_of(ptr, type, member) ({ \
  9.         const typeof( ((type *)0)->member ) *__mptr = (ptr); \
  10.         (type *)( (char *)__mptr - offsetof(type,member) );})

  1. #define offsetof(type, field) ((long) &((type *)0)->field)
其实这个宏随便百度一下就有很多解释,这个宏的作用就是,当有两个结构体嵌套的时候,如果现在
有一个指针指向里面的结构体,如何由这个指针获得外层结构体的指针。这个宏就可以。

其实这个宏最经典地方就是求那个偏移量的方法。它假定外层结构体的地址为0,那么内层结构体的地址
就和内层结构体到外层结构体的距离相等。

还有在内核中链表的使用,就有list_entry()这个宏,这个宏就是调用了contain_of这个宏。
比如你要遍历内核PCB的链表。就要用到。可以参考:

该宏更深入的理解可以参考:
--------------------------------------------------------------------------------------
3,min(x,y)  位置:include/linux/kernel.h
  1. 490 #define min(x, y) ({ \
  2. 491 typeof(x) _min1 = (x); \
  3. 492 typeof(y) _min2 = (y); \
  4. 493 (void) (&_min1 == &_min2); \
  5. 494 _min1 < _min2 ? _min1 : _min2; })
3,1,typeof这个可以求一个数的类型。
3.2,
(void) (&_min1 == &_min2);这句是为了判断这两个数类型是否一致。

开始以为不要这一句(void)(&_min1 == &_min2); 编译的过程中也会出现编译警告,以为
选择运算符a < b ? a : b遇到类型不一致的比较会提示编译警告,后来想了下,这个运算符
不会提示警告,它会将其强制类型转化,比如说4.0 < 5 ? 4.0 : 5它会转化为4.0 < 5.0 ?
4.0 : 5.0

(void)(&_min1 == &_min2);这一句实际上是用了指针的比较来判断两个数是否类型一致,
两个类型不一致的指针比较就会出现编译警告,这儿不一定要用"==",用 "<" 或 ">" 都可以。
-------------------------------------------------------------------------------------------
4,swap 位置:include/linux/kernel.h    

  1. 603 #define swap(a, b) \
  2. 604 do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
这是linux kernel中实现两个数交换的宏,它并没有用指针传递,而是用的值传递,之所以用值传递
也能成功,是这儿用的不是函数,而是用的带参宏实现的。
我觉得用带参宏要比函数实现要好,因为这个函数比较小,如果频繁调用将会影响执行效率。
-------------------------------------------------------------------------------------------
以后在kernel中发现好的宏再往后添加吧。
 
阅读(1072) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~