Linux 对齐掩码

对齐宏的位运算描述
#define alignment_mask(size) (~(size-1))
#define alignment_down(a, size) (a & alignment_mask(size) )
#define alignment_up(a, size)   ((a+size-1) & alignment_mask(size))

一般对齐都是按照 2 的指数值来对齐的,~(size-1) 本质是 size 的相反数。如果 size 是2的指数,那么 ~(size-1) 就是符号位从 0 变为 1。前边是连续的 1,后边是连续的 0 这种形式,例如 1111111100000.

位运算特性
1 0
& 保持 置0
| 置1 保持
异或 ^ 取反 保持

3种运算,每种都有一个结果是保持,刚好利用这个特性来针对特定的位来进行操作 – 置1,置0,取反

对于任意的 int x,在内存中都是使用补码表示。~x + 1 肯定就是 x 的相反数。x + ~x + 1 的结果肯定是0(x + ~x 肯定是全 1,值是 - 1)。

~(x - 1) 求相反数,取反加 1 即可。~(~(x - 1)) + 1 = x,所以 ~(x - 1)x 的相反数。

size 是2的指数时, (~(size-1)) 是前边全 1,后边全 0 的形式,所以 a & (~(size-1)) ,相当于将右边低位多余对齐单位的全部置 0,高位保持不变,就是向下对齐。如果是向上对齐,需要加上越过一个对齐单位,通过加上 ~(size-1) 来实现进 1 向上对齐。

对齐宏的算术运算描述
#define zero_or_one(x) ((x > 0) ? 1 : 0)
#define alignment_down(a, size) (a - a % size )
#define alignment_up(a, size)   (a - (a % size)  + zero_or_one(a % size) *  size)

结果

    printf("up align %d\n", alignment_down(6, 8)); //0
    printf("up align %d\n", alignment_down(8, 8)); //8
    printf("up align %d\n", alignment_down(14, 8)); //8

    printf("up align %d\n", alignment_up(6, 8));  //8
    printf("up align %d\n", alignment_up(8, 8));  //8
    printf("up align %d\n", alignment_up(14, 8));  //16

Linux 编程相关

recvmsg 和 sendmsg 函数接口中的 struct msghdr 消息头结构中的 struct cmsghdr.

           struct cmsghdr {
               size_t cmsg_len;    /* Data byte count, including header
                                      (type is socklen_t in POSIX) */
               int    cmsg_level;  /* Originating protocol */
               int    cmsg_type;   /* Protocol-specific type */
           /* followed by
              unsigned char cmsg_data[]; */
           };

消息头结构中的辅助信息的设置,涉及到对齐的两个宏操作:

  • CMSG_SPACE() returns the number of bytes an ancillary element with payload of the passed data length occupies. This is a constant expression.
  • CMSG_LEN() returns the value to store in the cmsg_len member of the cmsghdr structure, taking into account any necessary alignment. It takes the data length as an argument. This is a constant
    expression.
    里边都是间接的操作 CMSG_ALIGN 结构。一条消息可以有多条辅助数据,辅助数据构成辅助数组,所以此时必须按数组中的对齐,使用 CMSG_SPACE. 消息头中的 msg_controllen 字段是所有的辅助信息的总长度。
#define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \
			 & (size_t) ~(sizeof (size_t) - 1))

猜你喜欢

转载自blog.csdn.net/zhouguoqionghai/article/details/109726788