Interesting Tricks
Preface
其实内核有非常有意思的宏,函数。它们的实现都值得好好学习,这里把遇到的整合在一起吧,也做一个参考~
Hoooh
大小端
first, uapi/linux/byteorder/little_endian.h
or, xxx/big_endian.h
会定义不同的宏,比如 __le32_to_cpu 对于小端的CPU
自然就是不做处理,反而则做处理
这个宏会在这俩个文件都定义,然后只会 include 一个
很容易理解 so, xxx_to_cpu 具体的宏在编译的时候就确定了~对于 小端
#define __cpu_to_le64s(x) do { (void)(x); } while (0)
#define __le64_to_cpus(x) do { (void)(x); } while (0)
#define __cpu_to_le32s(x) do { (void)(x); } while (0)
#define __le32_to_cpus(x) do { (void)(x); } while (0)
#define __cpu_to_le16s(x) do { (void)(x); } while (0)
#define __le16_to_cpus(x) do { (void)(x); } while (0)
#define __cpu_to_be64s(x) __swab64s((x))
#define __be64_to_cpus(x) __swab64s((x))
#define __cpu_to_be32s(x) __swab32s((x))
#define __be32_to_cpus(x) __swab32s((x))
#define __cpu_to_be16s(x) __swab16s((x))
#define __be16_to_cpus(x) __swab16s((x))
而 大端
#define __cpu_to_le64s(x) __swab64s((x))
#define __le64_to_cpus(x) __swab64s((x))
#define __cpu_to_le32s(x) __swab32s((x))
#define __le32_to_cpus(x) __swab32s((x))
#define __cpu_to_le16s(x) __swab16s((x))
#define __le16_to_cpus(x) __swab16s((x))
#define __cpu_to_be64s(x) do { (void)(x); } while (0)
#define __be64_to_cpus(x) do { (void)(x); } while (0)
#define __cpu_to_be32s(x) do { (void)(x); } while (0)
#define __be32_to_cpus(x) do { (void)(x); } while (0)
#define __cpu_to_be16s(x) do { (void)(x); } while (0)
#define __be16_to_cpus(x) do { (void)(x); } while (0)
正好相反大小端的切换是一样的操作,所以两者函数都调用的一样,最终来到这,如果没有CPU自带的指令切换大小端的话(有些架构有自带的,就采用内嵌汇编)
是很粗暴的就解决,对于常数,也就是说编译就确定的数值,直接处理就好了,对于传进来的参数是不确定的,我们调用函数处理,但是本质还是一样的,都是做位移处理,也就是不是我们想象的做什么交换,那些都太复杂了,直接用位与操作即可解决,这也说明了,对于一些复杂的位操作,就应该直接暴力解决,而不是思考算法。
IO_操作
这里提提 io mmio 那些resource吧,其实只是设置一块内存是不可用的而已(page结构),因为页表做映射不可能再页内继续修改映射的,而物理内存的映射,一般也是以页为单位的,x86 的 IO 地址一般也是固定的,对于 ARM 来说,没有IO地址,一般都是硬布线改变的,而且所谓的 IO 地址,只是地址线上加一根使能线而已,独立或者统一编址都差不多。
先看 ARM 吧,最近再看这方面的,本质就是下面几个函数,可能加上一些内存屏障,当然,上面也说了,ARM 也对 x86 特有的 inb() outb() 等也定义了相关宏。
Inline Assembly - msr_s
一些内置汇编的 Tricks 也是宏用到的
之所以要俩层的原因已经解释了,下次来试试
这个 Macro 写的非常的漂亮,这是 4.19 的代码,在最早阅读的 3.17 的时候,使用的是自己定义的宏命令,非常难阅读,似乎是利用了硬指令编码来生成的。
对比另外一个版本,只需要
非常容易阅读,所以宏也是一门技术啊~~
CPU id
# ## __VA_ARGS__
Last updated