Linux Kernel内核字节序源代码分析-swab.h和big_endian.h — ... smart swab
Linux Kernel 2.6.14-内核字节序源代码分析-swab.h和big_endian.h
转载
**************************************************
-----------------------------------------------------
分析1:
以下据Linux Kernel中的注释:it doesn't pollute the POSIX namespace. Use these in the header files exported to user space.说明可用于用户空间。
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
------------自己加上的,为了后面的分析用
typedef __signed__ long long __s64;
typedef unsigned long long __u64;
------------------------------------------------------
分析2:
以下据Linux Kernel中的注释:These aren't exported outside the kernel to avoid name space clashes.只用于内核空间,以防命名冲突。
typedef signed char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
附:typedef 的使用说明:
1.typedef跟变量一样有可视范围,并且内层的可以覆盖外层的。
例如:
int main(void)
{
typedef int INT32;
INT32 a;
...
}
void fun()
{
typedef long INT32;
INT32 B;
...
}
main中的INT32为int型,而fun中的INT32为long型,但它们在自己的作用范围里独立起作用,互不干扰。
2.在同一作用范围内,不能用相同的名字来定义不同的数据类型。
如:
int main(void)
{
typedef int INT32;
typedef long INT32;//--->错误
...
}
即使是一模一样的也不能重复出现。
int main(void)
{
typedef int INT32;
typedef int INT32;//--->错误
...
}
但在c++中,一模一样的可以重复出现。即:c++允许完全相同的typedef表达式多次出现。
3.比较1:
3-1.
#define String char *
String input,output;
其展开后的结果为:
char * input,output;这时input为char *型,而output为char 型。因为*是右结合的。
3-2.
typedef char * String;
String input,output;
其展开后的结果为:
char * input, *output; input ,output均为char *型。
typedef定义的类型对每一个变量都起作用。
比较2:
#define INT32 int
unsigned INT32 a;-------->这是对的。可以组合使用。
typedef int INT32;
unsigned INT32 a;-------->这是错的,typedef不可以组合使用。
4.一个难点:
typedef char * String;
const String s;
问:展开后到底是const char * s; 还是char * const s;
答:展开后是char * const s;
原因:const 修饰的为String,而String为一个指针,所以const就修饰指针去了。
***************************************************
-------------------__swab16()----------------------
byteorderswab.h的源代码
#define ___swab16(x)
({
__u16 __x = (x);
((__u16)(
(((__u16)(__x) & (__u16)0x00ffU) << 8) |
(((__u16)(__x) & (__u16)0xff00U) >> 8) ));
})
分析:
1.__x与x,中间临时变量用同名,但前面加上“__”
2.U为无符号数,0x00ffU,注意数字部分用小写,U用大写,前面加0x
3.代码精彩之处为:先用(__u16)(__x) & (__u16)(0x00ffU)进行类型转换,再用移位运算。
((__u16)(__x) & (__u16)0x00ffU) << 8)
和((__u16)(__x) & (__u16)0xff00U) >> 8)
两者结果再用或运算。
4.___swab16()前面有三个下划线,而不是两根下划线。
5.此处的宏定义为小写,即是将其视为函数来处理。
-----------------------___swab32()--------------------
#define ___swab32(x)
({
__u32 __x = (x);
((__u32)(
(((__u32)(__x) & (__u32)0x000000ffUL) << 24) |
(((__u32)(__x) & (__u32)0x0000ff00UL) << 8) |
(((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) |
(((__u32)(__x) & (__u32)0xff000000UL) >> 24) ));
})
分析:
1.为长整型,UL,比如说:0x000000ffUL
2.这种很长的宏:
一要注意强制类型转换;
二要注意U,UL,ULL标志其数据类型;
三要注意宏内最后用‘;’结尾,宏外用({ 宏体部分});
四要注意每行用 来表示续行。
3.写法上注意对称。中间临时变量用双下划线__x,而函数则用三下划线,如:___swab32()。
----------------------___swab64()----------------
#define ___swab64(x)
({
__u64 __x = (x);
((__u64)(
(__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) |
(__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) |
(__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) |
(__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) |
(__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) |
(__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) |
(__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) |
(__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) ));
})
主干部分源代码分析同上。
#if defined(__KERNEL__)
#define swab16 __swab16
#define swab32 __swab32
#define swab64 __swab64
... ...
#endif
Linux Kernel代码风格:
1.先对__fun()或___fun()编写实现代码;
2.再用宏定义fun()来替换__fun() ___fun();
*****************************************************
----------------___constant_swab16()----------------
#define ___constant_swab16(x)
((__u16)(
(((__u16)(x) & (__u16)0x00ffU) << 8) |
(((__u16)(x) & (__u16)0xff00U) >> 8) ))
-----------___constant_swab32()-----------------------
#define ___constant_swab32(x)
((__u32)(
(((__u32)(x) & (__u32)0x000000ffUL) << 24) |
(((__u32)(x) & (__u32)0x0000ff00UL) << 8) |
(((__u32)(x) & (__u32)0x00ff0000UL) >> 8) |
(((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
------------___constant_swab64()---------------------
#define ___constant_swab64(x)
((__u64)(
(__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) |
(__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) |
(__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) |
(__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) |
(__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) |
(__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) |
(__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) |
(__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) ))
分析:
算法与上面的___swab16(),___swab32(),___swab64()一样。
只不过这里里是常量而矣。
*****************************************************
------__arch__swab16()--__arch__swab16()--__arch__swab16()------
Linux Kernel 2.6.14中的对以下的源代码的解释: provide defaults when no architecture-specific optimization is detected。用于无体系结构优化的字节交换代码。
#ifndef __arch__swab16
#define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); })
#endif
#ifndef __arch__swab32
#define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); })
#endif
#ifndef __arch__swab64
#define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); })
#endif
*****************************************************
------------------指针型的字节交换宏---------------------
#ifndef __arch__swab16p
#define __arch__swab16p(x) __arch__swab16(*(x))
#endif
#ifndef __arch__swab32p
#define __arch__swab32p(x) __arch__swab32(*(x))
#endif
#ifndef __arch__swab64p
#define __arch__swab64p(x) __arch__swab64(*(x))
#endif
分析同上,只是这里将x视为一个指针。
*****************************************************
-----------------存放字节交换结果型宏-----------------
#ifndef __arch__swab16s
#define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0)
#endif
#ifndef __arch__swab32s
#define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0)
#endif
#ifndef __arch__swab64s
#define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0)
#endif
分析:
1.x为一个指针,将该指针所指向的内存单元数据送入指针型的字节交换宏__arch_swab??p(),将交换后的结果又存入该指针所指向的内存单元。
*****************************************************
----------------__fswab16(__u16 x)-------------------------------
static __inline__ __attribute_const__ __u16 __fswab16(__u16 x)
{
return __arch__swab16(x);
}
--------------__swab16p(const __u16 *x)-------------------------
static __inline__ __u16 __swab16p(const __u16 *x)
{
return __arch__swab16p(x);
}
--------------------__swab16s(__u16 *addr)----------------------
static __inline__ void __swab16s(__u16 *addr)
{
__arch__swab16s(addr);
}
分析:
1.对比: const __u16 * 和 __u16*不同之处。查看一下前面的代码就懂了。
------------------------__fswab32(__u32 x)-----------------
{
static __inline__ __attribute_const__ __u32 __fswab32(__u32 x)
{
return __arch__swab32(x);
}
-------------------__swab32p(const __u32 *x)----------------
static __inline__ __u32 __swab32p(const __u32 *x)
{
return __arch__swab32p(x);
}
说明:typedef unsigned int __u32;然后在这里将const__u32*进行组合使用。前面已经说明,typedef 不能组合使用。这里,将const 与typedef组合运用,自己好好注意这一个细节。
-------------------------__swab32s(__u32 *addr)-----------------
static __inline__ void __swab32s(__u32 *addr)
{
__arch__swab32s(addr);
}
#if defined(__KERNEL__)
... ...
#define swab16p __swab16p
#define swab32p __swab32p
#define swab64p __swab64p
#define swab16s __swab16s
#define swab32s __swab32s
#define swab64s __swab64s
#endif
对const的解释:
1.对const的讨论:
1-1.
const int a=1;
a++;-------------->错,a定义为一个常量了,所以a值不能改变。
1-2.
int a=0;
const int *p = &a;
(*p)=1;------------>error,const修饰p所指向的对象,所以(*p)值不能改变。
1-3.
int a=0,b=1;
int * const p=&a;
(*p)=1;----------->Ok
p=&b;------------->Error
此处const修饰p,p所指向的值可以改变,但p自身的值不能被改变。
1-4.
int a=0,b=1;
const int * const p=&a;
(*p)=1;----------->error
p=&b;------------->Error
这里有两个const,一个修饰指针p,另一个修饰p所指向的int值。
2.对const的应用
在函数的参数中,如果我们希望函数只能引用指针所指向的内容,而不能改变其,这时可动用const
比如:
int memcpy(const void *s1,const void *s2,size_t n);
s1,s2所指向的内容只能读取,而不能被修改。若程序员不小心修改了其值,编译器会报错。
3.比较c++和c对const用法的不同之处:
3-1.c++能够把已用常量赋值的const变量看作编译时期的常数,c没有这种功能。
如:
const int BUFSIZE = 1024;
char buf[BUFSIZE];---------->Valid in C++ but illegal in C
3-2.c++默认const变量的链接性质为内部的,而c则相反,默认是外部的。
const int a=0;
int main(){}
在c中,a为外部的链接,即其他的文件在代码 能够访问到它。而在c++中,a就默认为内部的链接,除非加上extern修饰词,否则其它的文件是看不到const变量a的。
3-3.c只能允许用常量来初始化const外部变量,c++则没有这种限制。
int f(void)
const int a=f();--------->Valid in C++,but illegal in c
int main()
更多阅读
日照绿茶品牌“笪云峰”营销策略及市场分析 日照绿茶和西湖龙井
“笪云峰”茶品牌营销策略日照笪云峰商贸有限公司(2010年成立)是山东省日照市的一家专业茶叶企业,通过对日照独特自然、人文资源的调查研究,以及借势日照市多年来旅游推广策略,日照笪云峰商贸有限公司对茶叶品牌“笪云峰”的定位,及“无
晴雯“嚣张”与袭人“隐忍”的心理分析 晴雯和袭人的辩论
《红楼笔记》之二百一十九晴雯,因了她的火爆的性子和一张利嘴,为人诟病,说是其悲剧,乃性格使然(见拙文《红楼梦中晴雯的悲剧是性格悲剧吗》)。袭人,因了她隐忍的性格和一张善口,被人喜爱,谓其成功,乃做人之功(见拙文《《红楼梦》里袭人为什么
原创:实例分析清明梦和出体产生的9种情况
重要:请先了解什么是清明梦和出体对人类意识和灵魂进化的重要意义《致马云史玉柱一封信》(原创)梦修者实例分析产生清明梦和出体的几种不同情况,欢迎讨论和补充真修者受到追梦蚂蚁博客的启蒙,严肃认真的练习清明梦已经很久了,这几天经
分析齐家网和篱笆网,糯米网等团购网的成功特点 齐家网团购靠谱吗
关于团购网,我一直都在关注,从篱笆网的建材团购到爱帮网的团购甚至到千橡的糯米网团购,可是说在团购网很不乏成功的案例,可是试问一下成功的比例是多少。首先请看一下这个数据:宫光勇统计后发现,团购网站前五名的销售量能占到整个市场60%
推荐给股民朋友的两本书《风险投资实用分析技巧》和《短线是金》 老股民最简单炒股技巧
推荐给股民朋友的两本书《风险投资实用分析技巧》和《短线是金》,值得好好学习!内容简介该书全面引介了当今世界各种有影响的投资分析方法,巳计尽人微、准确精到。作者在充分掌握期货、股票交易活动的专业理论、人法的同时,以其丰富