zoukankan      html  css  js  c++  java
  • 内核 addr_bit_set之LE, BE奇招BITOP_BE32_SWIZZLE

    /*
     *    test bit
     */
    #if defined(__LITTLE_ENDIAN)
    # define BITOP_BE32_SWIZZLE    (0x1F & ~7)
    #else
    # define BITOP_BE32_SWIZZLE    0
    #endif

    static __inline__ __be32 addr_bit_set(void *token, int fn_bit)
    {
        __be32 *addr = token;
        /*
         * Here,
         *     1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)
         * is optimized version of
         *    htonl(1 << ((~fn_bit)&0x1F))
         * See include/asm-generic/bitops/le.h.
         */
        return (__force __be32)(1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f)) &
               addr[fn_bit >> 5];
    }


    注释中说明了关于掩码位的计算,下面更进一步解释一下

     

    令:

    M1 = 1 << ((~fn_bit ^BITOP_BE32_SWIZZLE) & 0x1f);

    M2 = htonl(1<<((~fn_bit)&0x1F));

     

    M1M2等价原因:

     

    4字节为例,BELE比特序也是倒过来的,测试IP地址第0位,相当于测试BE格式的第31位,即有:~fn_bit &0x1f,等价于31-fn_bit。测试IP地址第31位,相当于测试BE格式的第0位,即时~fn_big&0xlf,等价于31-fn_bit1<<((~fn_bit)&0x1F)这个是LE32位掩码,所以转成BE格式掩码,即htonl(1<<((~fn_bit)&0x1F))

     

    htonl就是把字节03对调,字节12对调。所以~fn_bit ^BITOP_BE32_SWIZZLE(~fn_bit)3位不变,高2位按位取反,即与BITOP_BE32_SWIZZLE=11000B即可实现。

     

    注:异或运算,与1异或相当取反,与0异或保持不变。



    不仅字节存在顺序,位域也存在顺序:

    #include <stdio.h>
    #include <netinet/in.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <memory.h>

    struct st_bits {
        unsigned char s1:1;
        unsigned char s2:1;
        unsigned char s3:1;
        unsigned char s4:1;
        unsigned char s5:1;
        unsigned char s6:1;
        unsigned char s7:1;
        unsigned char s8:1;
    };
        
    int main(int argc,char* argv[])
    {
        unsigned int a=0x12345678;
        unsigned int b;
        struct st_bits* ptr;
        int i;
        int addr;
        struct in6_addr addr6;
        int err;
        char* saddr4 = "192.168.10.1";
        char* saddr6 = "2013:4::119";
        
        
        
        b = htonl(a);
        ptr = (struct st_bits*) &b;
        
        printf("Little Endian a=0x%0x\n", a);
         
        ptr = (struct st_bits*) &a;
        for(i=0; i<4; i++) {
            printf("%1x %1x %1x %1x %1x %1x %1x %1x \n", ptr[i].s1, ptr[i].s2, ptr[i].s3, ptr[i].s4, ptr[i].s5, ptr[i].s6, ptr[i].s7, ptr[i].s8);
        }
        
        printf("Big Endian b=0x%0x\n", b);
        ptr = (struct st_bits*) &b;
        for(i=0; i<4; i++) {
            printf("%1x %1x %1x %1x %1x %1x %1x %1x \n", ptr[i].s1, ptr[i].s2, ptr[i].s3, ptr[i].s4, ptr[i].s5, ptr[i].s6, ptr[i].s7, ptr[i].s8);
        }
        
        //返回的地址已经是网络字节格式,所以你无需再调用 函数htonl
        addr = inet_addr(saddr4);
            printf("ipv4:%s, BE addr=0x%0x\n", saddr4, addr);
        ptr = (struct st_bits*) &addr;
        for(i=0; i<4; i++) {
            printf("%1x %1x %1x %1x %1x %1x %1x %1x \n", ptr[i].s1, ptr[i].s2, ptr[i].s3, ptr[i].s4, ptr[i].s5, ptr[i].s6, ptr[i].s7, ptr[i].s8);
        }
        
        memset(&addr6, 0, sizeof(addr6));
        
        err = inet_pton(AF_INET6, saddr6, &addr6);
        if (err < 0) {
            printf("call inet_pton error, err=%d, errno=%d\n", err, errno);
        }
        
            printf("ipv6:%s\n", saddr6);
            ptr = (struct st_bits*) &addr6;
            for(i=0; i<16; i++) {
            printf("%02x %1x %1x %1x %1x %1x %1x %1x %1x \n", addr6.s6_addr[i], ptr[i].s1, ptr[i].s2, ptr[i].s3, ptr[i].s4, ptr[i].s5, ptr[i].s6, ptr[i].s7, ptr[i].s8);
        }
        
        return 0;
    }


    #运行结果(LE平台)

    Little Endian a=0x12345678
    0 0 0 1 1 1 1 0 
    0 1 1 0 1 0 1 0 
    0 0 1 0 1 1 0 0 
    0 1 0 0 1 0 0 0 
    Big Endian b=0x78563412
    0 1 0 0 1 0 0 0 
    0 0 1 0 1 1 0 0 
    0 1 1 0 1 0 1 0 
    0 0 0 1 1 1 1 0 
    ipv4:192.168.10.1, BE addr=0x10aa8c0
    0 0 0 0 0 0 1 1 
    0 0 0 1 0 1 0 1 
    0 1 0 1 0 0 0 0 
    1 0 0 0 0 0 0 0 
    ipv6:2013:4::119
    20 0 0 0 0 0 1 0 0 
    13 1 1 0 0 1 0 0 0 
    00 0 0 0 0 0 0 0 0 
    04 0 0 1 0 0 0 0 0 
    00 0 0 0 0 0 0 0 0 
    00 0 0 0 0 0 0 0 0 
    00 0 0 0 0 0 0 0 0 
    00 0 0 0 0 0 0 0 0 
    00 0 0 0 0 0 0 0 0 
    00 0 0 0 0 0 0 0 0 
    00 0 0 0 0 0 0 0 0 
    00 0 0 0 0 0 0 0 0 
    00 0 0 0 0 0 0 0 0 
    00 0 0 0 0 0 0 0 0 
    01 1 0 0 0 0 0 0 0 
    19 1 0 0 1 1 0 0 0 




  • 相关阅读:
    sklearn之线性回归
    机器学习概述
    scipy之定积分计算和简单图像处理
    scipy之插值器
    numpy之排序
    spring mvc 实现文件上传
    Maven安装本地jar包到本地仓库
    spring mvc实现转发和重定向
    sprign mvc 解决中文乱码问题
    spring mvc 中使用session
  • 原文地址:https://www.cnblogs.com/mull/p/4477832.html
Copyright © 2011-2022 走看看