gcc packeted and aligned的作用

在shared memory的驱动中看到一个诡异的现象,从AP侧看BP的写指针有时会变小,例如:

read/write = 0x44f0, 但write忽然会变为0x4400,正常情况下是write增加,read在后面跟随。这样就会出现异常。

后来发现,读写操作不是按照预想的一次完成,而是按字节多次进行的。

假设AP 读却写指针(BP维护),当AP读第一个字节后,BP发生了变化,又更改了第一个字节,但是AP不知道,这样组合出来的4字节就有问题。

【简单的说就是两者没有同步】

虽然看上去是细节,但影响还是很严重的。

为什么执行的代码是按字节访问的哪?

其实原因很简单,数据结构的定义使用packeted进行了修饰。

__attrubte__ ((packed)) 的作用就是告诉编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

如果packeted只是简单的理解为编译器不要填充字节,那么生成的代码也不会按字节操作啊?应该是编译器还会按照字节的方式进行处理。

typedef struct smd_tx_stream_tag
{
    unsigned int write;
    const unsigned int read;
    unsigned int size; /*The buffer size, must be the power of 2*/
    const unsigned char res[20];
    unsigned char   buffer[SMD_BUFFER_SIZE];
    const unsigned char   protection[32];
} __attribute__ ((packeted)) T_SMD_TX_STREAM;


unsigned int smd_stream_write_avail(T_SMD_STREAM_CHANNEL *ch)
{
    T_SMD_TX_STREAM *stream=&ch->tx_stream;
    return (stream->size - stream->write + stream->read);
}
crash> dis smd_stream_write_avail
0xc024219c <smd_stream_write_avail>:    mov     r12, sp
0xc02421a0 <smd_stream_write_avail+4>:  push    {r4, r5, r6, r11, r12, lr, pc}
0xc02421a4 <smd_stream_write_avail+8>:  sub     r11, r12, #4
0xc02421a8 <smd_stream_write_avail+12>: ldrb    r12, [r0, #37]  ; 0x25
0xc02421ac <smd_stream_write_avail+16>: ldrb    r3, [r0, #36]   ; 0x24
0xc02421b0 <smd_stream_write_avail+20>: ldrb    r1, [r0, #41]   ; 0x29
0xc02421b4 <smd_stream_write_avail+24>: ldrb    r2, [r0, #40]   ; 0x28
0xc02421b8 <smd_stream_write_avail+28>: orr     r12, r3, r12, lsl #8
0xc02421bc <smd_stream_write_avail+32>: ldrb    r4, [r0, #38]   ; 0x26
0xc02421c0 <smd_stream_write_avail+36>: ldrb    r3, [r0, #42]   ; 0x2a
0xc02421c4 <smd_stream_write_avail+40>: orr     r1, r2, r1, lsl #8
0xc02421c8 <smd_stream_write_avail+44>: ldrb    r2, [r0, #39]   ; 0x27
0xc02421cc <smd_stream_write_avail+48>: ldrb    r6, [r0, #33]   ; 0x21
0xc02421d0 <smd_stream_write_avail+52>: orr     r12, r12, r4, lsl #16
0xc02421d4 <smd_stream_write_avail+56>: ldrb    r5, [r0, #43]   ; 0x2b
0xc02421d8 <smd_stream_write_avail+60>: orr     r1, r1, r3, lsl #16
0xc02421dc <smd_stream_write_avail+64>: ldrb    r4, [r0, #34]   ; 0x22
0xc02421e0 <smd_stream_write_avail+68>: orr     r12, r12, r2, lsl #24
0xc02421e4 <smd_stream_write_avail+72>: ldrb    r3, [r0, #32]
0xc02421e8 <smd_stream_write_avail+76>: ldrb    r2, [r0, #35]   ; 0x23
0xc02421ec <smd_stream_write_avail+80>: orr     r1, r1, r5, lsl #24
0xc02421f0 <smd_stream_write_avail+84>: orr     r3, r3, r6, lsl #8
0xc02421f4 <smd_stream_write_avail+88>: add     r0, r12, r1
0xc02421f8 <smd_stream_write_avail+92>: orr     r3, r3, r4, lsl #16
0xc02421fc <smd_stream_write_avail+96>: orr     r3, r3, r2, lsl #24
0xc0242200 <smd_stream_write_avail+100>:        rsb     r0, r3, r0
0xc0242204 <smd_stream_write_avail+104>:        ldm     sp, {r4, r5, r6, r11, sp, pc}


怎样使用字的方式访问?

aligned什么用途?这里不用aligned也可以,它本身就是在4的边界上。可以从生成的vmlinux验证

在编译目录下:

arm-none-linux-gnueabi-objdump -D vmlinux | less
然后查找即可。

aligned ( alignment )
This attribute specifies a minimum alignment (in bytes) for variablesof the specified type. For example, the declarations:
          struct S { short f[3]; } __attribute__ ((aligned (8)));
          typedef int more_aligned_int __attribute__ ((aligned (8)));
     

force the compiler to insure (as far as it can) that each variable whosetype is struct S or more_aligned_int will be allocated andaligned at least on a 8-byte boundary.

typedef struct smd_tx_stream_tag

{
    unsigned int write;
    const unsigned int read;
    unsigned int size; /*The buffer size, must be the power of 2*/
    const unsigned char res[20];
    unsigned char   buffer[SMD_BUFFER_SIZE];
    const unsigned char   protection[32];
} __attribute__ ((aligned(4))) T_SMD_TX_STREAM;


unsigned int smd_stream_write_avail(T_SMD_STREAM_CHANNEL *ch)
{
    T_SMD_TX_STREAM *stream=&ch->tx_stream;
    return (stream->size - stream->write + stream->read);
}

c029b054 <smd_stream_write_avail>:
c029b054:       e1a0c00d        mov     ip, sp
c029b058:       e92dd800        push    {fp, ip, lr, pc}
c029b05c:       e24cb004        sub     fp, ip, #4
c029b060:       e92d4000        push    {lr}
c029b064:       ebf5ccf7        bl      c000e448 <__gnu_mcount_nc>
c029b068:       e5901024        ldr     r1, [r0, #36]   ; 0x24
c029b06c:       e5902028        ldr     r2, [r0, #40]   ; 0x28
c029b070:       e5903020        ldr     r3, [r0, #32]
c029b074:       e0810002        add     r0, r1, r2
c029b078:       e0630000        rsb     r0, r3, r0
c029b07c:       e89da800        ldm     sp, {fp, sp, pc}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值