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

                                                                                                                                                                                                                迟 代码随笔 即日

  • 相关阅读:
    打造自己的性能测试类
    网站配置之最佳实践
    C#控制台窗口居中显示(转)
    将PDM文件导出成CHM帮助文件
    分享使用NPOI导出Excel树状结构的数据,如部门用户菜单权限
    Oracle 给已创建的表增加自增长列
    托管调试助手“NonComVisibleBaseClass”检测到问题
    翻页效果
    Excel表格转Json数据结构
    关于2D渲染的一些小想法
  • 原文地址:https://www.cnblogs.com/lt47/p/5890066.html
Copyright © 2011-2022 走看看