Linux Kernel内核字节序源代码分析-swab.h和big_endian.h — ... smart swab

Linux Kernel内核字节序源代码分析-swab.h和big_endian.h

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)

Linux Kernel内核字节序源代码分析-swab.h和big_endian.h — ... smart swab
#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()

  

爱华网本文地址 » http://www.aihuau.com/a/25101011/102336.html

更多阅读

晴雯“嚣张”与袭人“隐忍”的心理分析 晴雯和袭人的辩论

《红楼笔记》之二百一十九晴雯,因了她的火爆的性子和一张利嘴,为人诟病,说是其悲剧,乃性格使然(见拙文《红楼梦中晴雯的悲剧是性格悲剧吗》)。袭人,因了她隐忍的性格和一张善口,被人喜爱,谓其成功,乃做人之功(见拙文《《红楼梦》里袭人为什么

原创:实例分析清明梦和出体产生的9种情况

重要:请先了解什么是清明梦和出体对人类意识和灵魂进化的重要意义《致马云史玉柱一封信》(原创)梦修者实例分析产生清明梦和出体的几种不同情况,欢迎讨论和补充真修者受到追梦蚂蚁博客的启蒙,严肃认真的练习清明梦已经很久了,这几天经

声明:《Linux Kernel内核字节序源代码分析-swab.h和big_endian.h — ... smart swab》为网友一见如故的人分享!如侵犯到您的合法权益请联系我们删除