__attribute__ ((packed))的意思是什么

如果变量使用packed修饰,告诉编译器不要为了对齐等,在里面填充字节;

更重要的一点是生成的代码,将以字节形式处理结构体中的变量。

typedef struct smd_tx_stream_tag

{
    unsigned int write;
    const unsigned int read;
    unsigned int size;
    const unsigned char res[20];
    unsigned char   buffer[SMD_BUFFER_SIZE];
    const unsigned char   protection[32];

} __attribute__ ((packed)) T_SMD_TX_STREAM;

已函数smd_stream_write_avail为例

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);
}

如果使用packed,则生成的汇编代码,都是使用ldrb,对字节进行操作

crash> dis smd_stream_write_avail
0xc021e6fc <smd_stream_write_avail>:    mov     r12, sp
0xc021e700 <smd_stream_write_avail+4>:  push    {r4, r5, r6, r11, r12, lr, pc}
0xc021e704 <smd_stream_write_avail+8>:  sub     r11, r12, #4
0xc021e708 <smd_stream_write_avail+12>: ldrb    r12, [r0, #37]  ; 0x25
0xc021e70c <smd_stream_write_avail+16>: ldrb    r3, [r0, #36]   ; 0x24
0xc021e710 <smd_stream_write_avail+20>: ldrb    r1, [r0, #41]   ; 0x29
0xc021e714 <smd_stream_write_avail+24>: ldrb    r2, [r0, #40]   ; 0x28
0xc021e718 <smd_stream_write_avail+28>: orr     r12, r3, r12, lsl #8
0xc021e71c <smd_stream_write_avail+32>: ldrb    r4, [r0, #38]   ; 0x26
0xc021e720 <smd_stream_write_avail+36>: ldrb    r3, [r0, #42]   ; 0x2a
0xc021e724 <smd_stream_write_avail+40>: orr     r1, r2, r1, lsl #8
0xc021e728 <smd_stream_write_avail+44>: ldrb    r2, [r0, #39]   ; 0x27
0xc021e72c <smd_stream_write_avail+48>: ldrb    r6, [r0, #33]   ; 0x21
0xc021e730 <smd_stream_write_avail+52>: orr     r12, r12, r4, lsl #16
0xc021e734 <smd_stream_write_avail+56>: ldrb    r5, [r0, #43]   ; 0x2b
0xc021e738 <smd_stream_write_avail+60>: orr     r1, r1, r3, lsl #16
0xc021e73c <smd_stream_write_avail+64>: ldrb    r4, [r0, #34]   ; 0x22
0xc021e740 <smd_stream_write_avail+68>: orr     r12, r12, r2, lsl #24
0xc021e744 <smd_stream_write_avail+72>: ldrb    r3, [r0, #32]
0xc021e748 <smd_stream_write_avail+76>: ldrb    r2, [r0, #35]   ; 0x23
0xc021e74c <smd_stream_write_avail+80>: orr     r1, r1, r5, lsl #24
0xc021e750 <smd_stream_write_avail+84>: orr     r3, r3, r6, lsl #8
0xc021e754 <smd_stream_write_avail+88>: add     r0, r12, r1
0xc021e758 <smd_stream_write_avail+92>: orr     r3, r3, r4, lsl #16
0xc021e75c <smd_stream_write_avail+96>: orr     r3, r3, r2, lsl #24
0xc021e760 <smd_stream_write_avail+100>:        rsb     r0, r3, r0
0xc021e764 <smd_stream_write_avail+104>:        ldm     sp, {r4, r5, r6, r11, sp, pc}

如果去掉packeted属性,则生成的汇编代码为:

注意这个是使用objdump工具看得

arm-none-eabi-objdump -D vmlinux | less,而上面那个使用的是 crash工具

c0254518 <smd_stream_write_avail>:
c0254518:       e1a0c00d        mov     ip, sp
c025451c:       e92dd800        push    {fp, ip, lr, pc}
c0254520:       e24cb004        sub     fp, ip, #4      ; 0x4
c0254524:       e5901024        ldr     r1, [r0, #36]
c0254528:       e5902028        ldr     r2, [r0, #40]
c025452c:       e5903020        ldr     r3, [r0, #32]
c0254530:       e0810002        add     r0, r1, r2
c0254534:       e0630000        rsb     r0, r3, r0
c0254538:       e89da800        ldm     sp, {fp, sp, pc}

后果是什么

因为变量如读写指针,是按字节更新的,当另一个 CPU [BP]使用使,看到的可能是更新工程中的一部分【变量都是4个字节,但按字节1个个更新】

算法的设计是一次更新4个字节,就是一次更新完变量。

如函数:smd_stream_read_avail中,可以发现 可以读出的数据大于最大的实际的整个shared memory,这肯定是错误的。

unsigned int smd_stream_read_avail(T_SMD_STREAM_CHANNEL *ch)
{
    int len = 0;
    T_SMD_RX_STREAM *stream=&ch->rx_stream;

len = stream->write - stream->read;
    if(len < 0 || len > SMD_BUFFER_SIZE)
    {
        pr_err("ERRORED current write %x, read %x\n", stream->write, stream->read);
        pr_err("ERRORED Last write %x, read %x\n", stream->protection[1], stream->protection[0]);
        pr_err("ERRORED SMD READ/WRITE POINTER!!!!!!!!!\n");
        stream->read = stream->write;
    }

stream->protection[0]= stream->read;
    stream->protection[1]= stream->write;

return (stream->write - stream->read);
}

总结

即使使用原子操作,操作这些变量,也不能解决问题。原子操作的意思是SMP【AP】中多个CPU的访问,而不是说的另外一个CPU【BP】。

问题的解决,却是修改数据变量的类型,有点神奇啊,解决bug,思路要开阔啊,敢于审视那些应该不会出问题的地方。

shared memory driver(2)相关推荐

  1. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析

    在前面一篇文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析中,我们系统地介绍了Android系统匿名共享内存的实现原理,其中着重介绍了 ...

  2. Windows Mobile使用Shared Memory(共享内存)进行IPC(进程间通信)的开发

    背景 在Unix-like系统进行IPC(Inter-process communication)通信,Shared memory是效率最高的,我称之为IPC的王中王. 简介 本文讲述在Windows ...

  3. 处理错误:ORA-27101: shared memory realm does not exist 解决方案

    处理错误:ORA-27101: shared memory realm does not exist 解决方案 参考文章: (1)处理错误:ORA-27101: shared memory realm ...

  4. 关于Java HotSpot(TM) 64-Bit Server VM warning: Insufficient space for shared memory file: 11043的解决办...

    Java HotSpot(TM) 64-Bit Server VM warning: Insufficient space for shared memory file: /tmp/hsperfdat ...

  5. 处理错误:ORA-27101: shared memory realm does not exist

    2019独角兽企业重金招聘Python工程师标准>>> 我试图连接数据库时的ORA-01034 和 ORA-27101错误信息,它总是显示这样的信息,"ORA-01034 ...

  6. linux 内存 shared,Linux Shared Memory的查看与设置

    Linux Shared Memory的查看与设置 共享内存就是进程之间可以共享的一段内存,通过一个唯一的KEY值绑定 shmget()创建或获取 shmat()连接 shmdt()断连 共享内存的访 ...

  7. linux shared,从 0 开始学习 Linux 系列之「22.共享内存 Shared Memory」

    共享内存 版权声明:本文为 cdeveloper 原创文章,可以随意转载,但必须在明确位置注明出处! 共享内存 Shared Memory 这次我们来学习在 Linux 中最快的一种 IPC 方式:共 ...

  8. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划

    在Android系统中,提供了独特的匿名共享内存子系统Ashmem(Anonymous Shared Memory),它以驱动程序的形式实现在内核空间中.它有两个特点,一是能够辅助内存管理系统来有效地 ...

  9. ORA-27125: unable to create shared memory segment的解决方法(转)

    ORA-27125: unable to create shared memory segment的解决方法(转) 原文:http://www.eygle.com/rss/20111202.html  ...

最新文章

  1. lamp平台的搭建:mysql的编译安装【转】
  2. Excel如何快速清除单元格所有内容
  3. 射线法 java_射线法(1190 - Sleepwalking )
  4. 加密、解密、摘要、签名、证书一文搞懂
  5. 一文看懂微服务背后的技术演进与应用实践
  6. java string set_Java StringJoiner setEmptyValue()用法及代码示例
  7. windows中使用mysql配置my.ini时的坑
  8. 获取Linux命令源代码的方法
  9. UE4之windows.h冲突
  10. 通过PDMS系统文件快速批量添加颜色规则
  11. ubuntu的使用--系统目录篇(文末附Desktop目录位置)
  12. Java IO流(超详细!)
  13. draw.io箭头设置虚线
  14. vue中使用图片裁切器
  15. pynq 环境搭建_FPGA硬件加速的图像大小调整案例分析
  16. 利用python计算个人所得税
  17. ModuleNotFoundError: No module named ‘official‘
  18. 成都Java程序员培训毕业后什么水平
  19. 比尔盖茨沙漠里买地建未来城市?可能是个谣传!
  20. http协议入门之Content-Disposition

热门文章

  1. 传统图像处理之皮肤区域检测
  2. Script file ‘F:.....\pip-script.py‘ is not present 原因及解决办法
  3. win7 Telnet功能安装
  4. c#元胞自动机_用元胞自动机实现多数分类算法
  5. 网络结构 - Inception深度网络家族盘点
  6. 极空间Docker安装Centos 开启SSH
  7. C#培训2019-10-24 关于继承的两点问题
  8. 【SpringCloud】3分钟讲解SpringCloud1.0
  9. 用工单位使用劳动派遣时需注意这几点
  10. 计算机网络基础:常见的网络传输介质