当前位置: 首页 > GNU/Linux程序 > 正文

ARMLinux下Alignment trap的一些测试

项目中有时会遇到字节对齐的问题,英文为“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\n”sizeof(unpacked), sizeof(packed));

printf(“Addr of unpacked: %p\n”, &unpacked);

printf(“Addr of unpacked.c1: %p\n”, &unpacked.c1);

printf(“Addr of unpacked.i: %p\n”, &unpacked.i);

printf(“Addr of unpacked.c2: %p\n”, &unpacked.c2);

printf(“Addr of unpacked.s1: %p\n”, &unpacked.s1);

printf(“Addr of unpacked.c3: %p\n”, &unpacked.c3);

printf(“Addr of packed: %p\n”, &packed);

printf(“Addr of packed.c1: %p\n”, &packed.c1);

printf(“Addr of packed.i: %p\n”, &packed.i);

printf(“Addr of packed.c2: %p\n”, &packed.c2);

printf(“Addr of packed.s1: %p\n”, &packed.s1);

printf(“Addr of packed.c3: %p\n”, &packed.c3);

}

short* rte_get_s1(void)

{

return &unpacked.s1;

}

void case2()

{

print_addr();

int* val = (int *)rte_get_s1();

printf(“val = %d\n”, *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\n”sizeof(foo));

    // 注意!!此处将short*强制转换为int*,造成出错

int* val = (int *)get_foo_c();

printf(“val: %d\n”, *val);

}

// case 3 end

//////////////////////////////////////////////////////////////

/// case 4

void case4()

{

char* str = “01234567”;

unsigned* u = (unsigned *)(str+1);

printf(“0x%08x\n”, *u);

}

/// case 4 end

int main()

{

printf(“test of alignment trap…\n”);

//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

迟 代码随笔 即日
本文初发表在CSDN博客,2012-08-09

本文固定链接: http://www.latelee.org/programming-under-linux/arm-linux-alignment-trap.html

如无特别说明,迟思堂工作室文章均为原创,转载请注明: ARMLinux下Alignment trap的一些测试 | 迟思堂工作室

目前暂无评论

发表评论

*

快捷键:Ctrl+Enter