shared memory driver(2)
__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)相关推荐
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析
在前面一篇文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析中,我们系统地介绍了Android系统匿名共享内存的实现原理,其中着重介绍了 ...
- Windows Mobile使用Shared Memory(共享内存)进行IPC(进程间通信)的开发
背景 在Unix-like系统进行IPC(Inter-process communication)通信,Shared memory是效率最高的,我称之为IPC的王中王. 简介 本文讲述在Windows ...
- 处理错误:ORA-27101: shared memory realm does not exist 解决方案
处理错误:ORA-27101: shared memory realm does not exist 解决方案 参考文章: (1)处理错误:ORA-27101: shared memory realm ...
- 关于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 ...
- 处理错误:ORA-27101: shared memory realm does not exist
2019独角兽企业重金招聘Python工程师标准>>> 我试图连接数据库时的ORA-01034 和 ORA-27101错误信息,它总是显示这样的信息,"ORA-01034 ...
- linux 内存 shared,Linux Shared Memory的查看与设置
Linux Shared Memory的查看与设置 共享内存就是进程之间可以共享的一段内存,通过一个唯一的KEY值绑定 shmget()创建或获取 shmat()连接 shmdt()断连 共享内存的访 ...
- linux shared,从 0 开始学习 Linux 系列之「22.共享内存 Shared Memory」
共享内存 版权声明:本文为 cdeveloper 原创文章,可以随意转载,但必须在明确位置注明出处! 共享内存 Shared Memory 这次我们来学习在 Linux 中最快的一种 IPC 方式:共 ...
- Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划
在Android系统中,提供了独特的匿名共享内存子系统Ashmem(Anonymous Shared Memory),它以驱动程序的形式实现在内核空间中.它有两个特点,一是能够辅助内存管理系统来有效地 ...
- ORA-27125: unable to create shared memory segment的解决方法(转)
ORA-27125: unable to create shared memory segment的解决方法(转) 原文:http://www.eygle.com/rss/20111202.html ...
最新文章
- lamp平台的搭建:mysql的编译安装【转】
- Excel如何快速清除单元格所有内容
- 射线法 java_射线法(1190 - Sleepwalking )
- 加密、解密、摘要、签名、证书一文搞懂
- 一文看懂微服务背后的技术演进与应用实践
- java string set_Java StringJoiner setEmptyValue()用法及代码示例
- windows中使用mysql配置my.ini时的坑
- 获取Linux命令源代码的方法
- UE4之windows.h冲突
- 通过PDMS系统文件快速批量添加颜色规则
- ubuntu的使用--系统目录篇(文末附Desktop目录位置)
- Java IO流(超详细!)
- draw.io箭头设置虚线
- vue中使用图片裁切器
- pynq 环境搭建_FPGA硬件加速的图像大小调整案例分析
- 利用python计算个人所得税
- ModuleNotFoundError: No module named ‘official‘
- 成都Java程序员培训毕业后什么水平
- 比尔盖茨沙漠里买地建未来城市?可能是个谣传!
- http协议入门之Content-Disposition
热门文章
- 传统图像处理之皮肤区域检测
- Script file ‘F:.....\pip-script.py‘ is not present 原因及解决办法
- win7 Telnet功能安装
- c#元胞自动机_用元胞自动机实现多数分类算法
- 网络结构 - Inception深度网络家族盘点
- 极空间Docker安装Centos 开启SSH
- C#培训2019-10-24 关于继承的两点问题
- 【SpringCloud】3分钟讲解SpringCloud1.0
- 用工单位使用劳动派遣时需注意这几点
- 计算机网络基础:常见的网络传输介质