zoukankan      html  css  js  c++  java
  • ARMLinux下Alignment trap的一些测试 【转自 李迟的专栏 CSDN http://blog.csdn.net/subfate/article/details/7847356

    项目中有时会遇到字节对齐的问题,英文为“Alignment trap”,如果直译,意思为“对齐陷阱”,不过这个说法不太好理解,还是直接用英文来表达。

    ARM平台下一般是4字节对齐,可以参考文后的给出的文章链接。此处不细说。后面提及“字节对齐”

    下面的例子使用了几种重现Alignment trap的方法,例子1是将char*指针直接转换成int*指针,经测试,未发现有字节对齐的问题。例子2和例子3相似,主要是结构体中的字段没有进行对齐(或者访问的地址没有4字节对齐)。例子4是直接访问了没有字节对齐的指针。后3个例子在测试时均出现了错误。

    /**
     *
     Linux下对Alignment trap的处理有下面几种方式:
     0 (ignored)
     1 (warn)
     2 (fixup)
     3 (fixup+warn)
     4 (signal)
     5 (signal+warn)

     使用方法:
     # echo 3 > /proc/cpu/alignment
     */

    #include <stdio.h>
    #include <stdlib.h>

    /// case 1
    void fool(unsigned char* buf, int len)
    {
        unsigned int* p = (unsigned int*)buf;
        int i;

        for (i = 0; i < len; i++)
        {
            *p++ = i+1;
            printf("%d ", *p);
        }
    }

    void foolish()
    {
        unsigned char poor[100];

        fool(poor, sizeof(poor)/sizeof(int));
        
    }

    // case 1 end
    ////////////////////////////////////////////////////////////////

    /// case 2

    struct rte_unpacked_struct_t
    {
        char c1;
        int i;
        char c2;
        short s1;
        char c3;
    };

    struct rte_packed_struct_t
    {
        char c1;
        int i;
        char c2;
        short s1;
        char c3;
    }__attribute__((__packed__));

    struct rte_unpacked_struct_t unpacked;
    struct rte_packed_struct_t packed;

    void print_addr()
    {
        printf("sizeof(unpacked) = %d sizeof(packed) = %d ", sizeof(unpacked), sizeof(packed));
        printf("Addr of unpacked: %p ", &unpacked);
        printf("Addr of unpacked.c1: %p ", &unpacked.c1);
        printf("Addr of unpacked.i: %p ", &unpacked.i);
        printf("Addr of unpacked.c2: %p ", &unpacked.c2);
        printf("Addr of unpacked.s1: %p ", &unpacked.s1);
        printf("Addr of unpacked.c3: %p ", &unpacked.c3);

        printf("Addr of packed: %p ", &packed);
        printf("Addr of packed.c1: %p ", &packed.c1);
        printf("Addr of packed.i: %p ", &packed.i);
        printf("Addr of packed.c2: %p ", &packed.c2);
        printf("Addr of packed.s1: %p ", &packed.s1);
        printf("Addr of packed.c3: %p ", &packed.c3);

    }

    short* rte_get_s1(void)
    {
        return &unpacked.s1;
    }

    void case2()
    {
        print_addr();

        int* val = (int *)rte_get_s1();
        printf("val = %d ", *val);    
    }
    /// case 2 end
    ////////////////////////////////////////////////////////////////

    /// case 3
    struct foo_t
    {
        short a;
        short b;
        short c;
        short d;
    };

    struct foo_t foo;

    short* get_foo_c(void)
    {
        return &foo.c;
    }

    void case3()
    {
        printf("sizeof(foo) = %d ", sizeof(foo));
        // 注意!!此处将short*强制转换为int*,造成出错
        int* val = (int *)get_foo_c();
        printf("val: %d ", *val);
    }

    // case 3 end
    //////////////////////////////////////////////////////////////

    /// case 4

    void case4()
    {
        char* str = "01234567";
        unsigned* u = (unsigned *)(str+1);
        printf("0x%08x ", *u);
    }

    /// case 4 end

    int main()
    {
        printf("test of alignment trap... ");

        //foolish();

        //case2();
        //case3();
        case4();

        return 0;
    }



    以下是在某ARMLinux平台下的测试结果,依次将错误处理等级设置为0到5,出现不的结果,如下:

    # echo 0 >  /proc/cpu/alignment 
    # ./a.out 
    test of alignment trap...
    0x30333231
    # echo 1 >  /proc/cpu/alignment 
    # ./a.out 
    testAlignment trap: a.out (1125) PC=0x000086c8 Instr=0xe5931000 Address=0x00008961 FSR 0x001
     of alignment trap...
    0x30333231
    # echo 2 >  /proc/cpu/alignment 
    # ./a.out 
    test of alignment trap...
    0x34333231
    # echo 3 >  /proc/cpu/alignment 
    # ./a.out 
    testAlignment trap: a.out (1127) PC=0x000086c8 Instr=0xe5931000 Address=0x00008961 FSR 0x001
     of alignment trap...
    0x34333231
    # echo 4 >  /proc/cpu/alignment 
    # ./a.out 
    test of alignment trap...
    Bus error
    # echo 5 >  /proc/cpu/alignment 
    # ./a.out 
    testAlignment trap: a.out (1129) PC=0x000086c8 Instr=0xe5931000 Address=0x00008961 FSR 0x001
     of alignment trap...
    Bus error


    常用的是使用等级3来处理,即提示错误并进行修复。

    上面只讲到如何使用代码出现字节对齐错误,但没涉及如何排查问题。示例代码十分简单,很容易定位错误地方,但如果在大型项目中,就很难定位,尤其是在嵌入 式中,——嵌入式的调试也相对比较困难、麻烦。以我的经验,与其用gdbserver来调试,不如靠经验及printf大法解决问题来得更快(当然,仅个 人看法)。

    本来想用工具调试来发现出错的代码位置,但尝试了,没结果。

    在代码编写中,需要注意一下以下的事:
    1、结构体尽量使用4字节对齐,比如设置一个传输长度len的类型时,用short表示的范围已经足够,当然也可以用int。像制定一些网络协议,最好考虑一下4字节对齐。
    2、分配内存时也尽量4字节对齐,无论是申请的内存还是定义数组大小。
    3、对指针进行访问的时候也要十分注意4字节对齐,特别是一些为了避免编译警告的强制类型转换。

    参考资料:

    http://www.rt-embedded.com/blog/archives/resolving-alignment-traps/
    http://simplemachines.it/arm-linux/book/afaq.html

                                                                                                                                                                                                                迟 代码随笔 即日

  • 相关阅读:
    hdu 1290 献给杭电五十周年校庆的礼物 (DP)
    hdu 3123 GCC (数学)
    hdu 1207 汉诺塔II (DP)
    hdu 1267 下沙的沙子有几粒? (DP)
    hdu 1249 三角形 (DP)
    hdu 2132 An easy problem (递推)
    hdu 2139 Calculate the formula (递推)
    hdu 1284 钱币兑换问题 (DP)
    hdu 4151 The Special Number (DP)
    hdu 1143 Tri Tiling (DP)
  • 原文地址:https://www.cnblogs.com/lt47/p/5890066.html
Copyright © 2011-2022 走看看