我觉得还有一个可能怀疑的就是malloc与free本身.
设计上本身并不排除malloc,free执行一半调度到另一任务的malloc,free.
examples:
A delete B free了一半 调度到 B delete B
A delete B free了一半 调度到 C create D
。。。(这概率!)这总是让人不安,谁没用过malloc(应该包括new delete吧?)。
(malloc不局限于嵌入式平台)于是有了下文先。
暂时还没完全搞清楚,有点晕。有点简单问题复杂化的感脚。
(引用的帖子与博客不代表个人观点。。。) malloc free 的实现看上去好像不太靠普(其实没仔细看,不直观,看个大概..关键手册不详细,或没找到。)
ida F5生成(其中一个QSys.axf),仅供参考。
int __fastcall malloc(int a1)
{
int v1; // r1@1
int i; // r2@2
unsigned int v3; // r3@3
__int64 v4; // r6@5
int v5; // r3@5
int result; // r0@7
int v7; // r0@9
if ( result )
{
v1 = 0;
result -= 4;
for ( i = _microlib_freelist; i && i <= (unsigned int)result; i = *(_DWORD *)(i + 4) )
v1 = i;
if ( v1 )
{
if ( result - v1 == *(_DWORD *)v1 )
{
*(_DWORD *)v1 += *(_DWORD *)result;
result = v1;
}
else
{
*(_DWORD *)(v1 + 4) = result;
}
}
else
{
_microlib_freelist = result;
}
if ( i )
{
if ( i - result == *(_DWORD *)result )
{
*(_DWORD *)result += *(_DWORD *)i;
i = *(_DWORD *)(i + 4);
}
}
*(_DWORD *)(result + 4) = i;
}
return result;
} 参考1MDK4.54 hlp下的某个.chm,好吧我落伍了...)
calloc(),
free(),
malloc(),
realloc()
The heap functions are thread-safe if the _mutex_* functions are implemented.
A single heap is shared between all threads, and mutexes are used to avoid data corruption when there is concurrent access. Each heap implementation is responsible for doing its own locking. If you supply your own allocator, it must also do its own locking. This enables it to do fine-grained locking if required, rather than protecting the entire heap with a single mutex (coarse-grained locking).
改进taskCreate,不再使用malloc和free进行自动内存分配。
删除void delay(unsigned int pid,unsigned int ticks);
新增函数void suspend(void),用于挂起任务本身。
新增函数void resume(unsigned int pid),用于恢复已经被挂起的任务或者被sleep阻塞的任务。
我觉得还有一个可能怀疑的就是malloc与free本身.
设计上本身并不排除malloc,free执行一半调度到另一任务的malloc,free.
examples:
A delete B free了一半 调度到 B delete B
A delete B free了一半 调度到 C create D
。。。(这概率!)这总是让人不安,谁没用过malloc(应该包括new delete吧?)。
(malloc不局限于嵌入式平台)于是有了下文先。
暂时还没完全搞清楚,有点晕
(引用的帖子与博客不代表个人观点。。。)
malloc free 的实现看上去好像不太靠普(其实没仔细看,不直观,看个大概..关键手册不详细,或没找到。)
ida F5生成(其中一个QSys.axf),仅供参考。
int __fastcall malloc(int a1)
{
int v1; // r1@1
int i; // r2@2
unsigned int v3; // r3@3
__int64 v4; // r6@5
int v5; // r3@5
int result; // r0@7
int v7; // r0@9
v1 = (a1 + 11) & 0xFFFFFFF8;
while ( 1 )
{
for ( i = (int)&_microlib_freelist; ; i = v7 + 4 )
{
v7 = *(_DWORD *)i;
if ( !*(_DWORD *)i )
{
result = 0;
goto LABEL_11;
}
v3 = *(_DWORD *)v7;
if ( *(_DWORD *)v7 >= (unsigned int)v1 )
break;
}
if ( v3 <= v1 )
{
v5 = *(_DWORD *)(v7 + 4);
}
else
{
LODWORD(v4) = v3 - v1;
v5 = v7 + v1;
HIDWORD(v4) = *(_DWORD *)(v7 + 4);
*(_QWORD *)(v7 + v1) = v4;
}
*(_DWORD *)i = v5;
*(_DWORD *)v7 = v1;
result = v7 + 4;
LABEL_11:
if ( result )
return result;
if ( _microlib_freelist_initialised )
return 0;
_microlib_freelist = (int)&unk_200000EC;
unk_200000EC = 0x27FC & 0xFFFFFFF8;
unk_200000F0 = 0;
_microlib_freelist_initialised = 1;
}
}
int __fastcall free(int result)
{
int v1; // r2@2
int i; // r1@2
if ( result )
{
v1 = 0;
result -= 4;
for ( i = _microlib_freelist; i && i <= (unsigned int)result; i = *(_DWORD *)(i + 4) )
v1 = i;
if ( v1 )
{
if ( result - v1 == *(_DWORD *)v1 )
{
*(_DWORD *)v1 += *(_DWORD *)result;
result = v1;
}
else
{
*(_DWORD *)(v1 + 4) = result;
}
}
else
{
_microlib_freelist = result;
}
if ( i )
{
if ( i - result == *(_DWORD *)result )
{
*(_DWORD *)result += *(_DWORD *)i;
i = *(_DWORD *)(i + 4);
}
}
*(_DWORD *)(result + 4) = i;
}
return result;
}
参考1
calloc(),
free(),
malloc(),
realloc()
The heap functions are thread-safe if the _mutex_* functions are implemented.
A single heap is shared between all threads, and mutexes are used to avoid data corruption when there is concurrent access. Each heap implementation is responsible for doing its own locking. If you supply your own allocator, it must also do its own locking. This enables it to do fine-grained locking if required, rather than protecting the entire heap with a single mutex (coarse-grained locking).
参考2:(FROM amobbs)
在ARM上移植ucos (RVDS环境),关于MALLOC的问题bottom↓
看3652|回7|收藏
1楼 chinatf 只看他
2009-3-31 16:51:19
使用RVDS集成开发环境,ARM平台。
设置好系统堆栈,使得malloc()函数能够正常使用。
问题:
====
我运行uCosII系统,在多个同时运行的任务中调用malloc()函数。
由于多个任务可能同时在调用malloc()函数,而malloc()是RVDS提供的库函数,
并没有考虑多任务调度的情况,所以多个任务可能同时在调用malloc()函数有可能
会造成冲突。
解决方法:
====
在任务中调用malloc()的地方使用互斥量,使得malloc()在某个时候只能被一个任务
调用。
欢迎大家各抒己见!
2楼 dr2001 只看他
2009-3-31 17:37:58
malloc用的是C Run Time Library的堆[Heap],和堆栈没关系。不给CRTL初始化堆,再多的堆栈也没什么用。
malloc可重入与否请参考使用的CRTL的说明,有的也许可重入。不过这类库还是程序加锁比较安全。
具体使用什么锁看需求吧。MCU环境,单核心,能够引发调度的除了程序主动释放时间片,就是中断,理论上这类操作屏蔽中断的方法效率更高。用mutex,sem,queue都是可以实现的,根据程序结构定了。
3楼 akin 只看他
2009-3-31 20:30:17
我一直担心单片机上用malloc和free会产生碎片,
以前在RVDS下测试过能用,但有时候又不能,
所以到目前都是几乎不用这对函数。
4楼 akin 只看他
2009-3-31 20:32:08
太多的不确定性总让人用得不放心,睡不着觉。
5楼 armrtems 只看他
2009-3-31 21:56:19
RVDS 4.0么? 怎么调试?
malloc有一个配置选项,可配置为oe模式(保证实时性)和普通模式.
针对多线程,runlibc有几个函数需要实现,armlink文档里面有说明。实现几个函数,线程切换时切换一个结构体,否则可能会有问题。
runlibc的c库比较稳定,一般不会出问题。
事实上网络上流传的移植包不是完美的,大都没有考虑这个问题,楼主还是比较细心的。
6楼 chinatf 只看他
2009-4-1 09:46:46
to armrtems
我现在用RVDS2.2,我看看这个版本有没有malloc的配置选项。
7楼 dr2001 只看他
2009-4-1 10:03:17
To 2# akin
如果正确初始化堆,用起来是没有问题的,如果你用了printf之类的库,这些东西比较吃堆空间,堆小了不一定剩下那么多给你用。具体的需要看看CRTL的手册,专门有章节说内存管理的。
Malloc和Free导致的碎片问题确实讨厌,不过这个要看具体的分配策略了,CRTL发展了这么多年,嵌入式环境下应该有基于页的算法了吧。浪费是浪费些,毕竟还有的用。
To 4# armrtems
RV4 调试只能用ARM ICE;如果要调试,只能用这个的编译器,得到axf,加载到别的支持axf的调试环境来用。RVDS本身还是不要想了,米人除外。-_-!
8楼 chinatf 只看他
2009-4-1 16:18:26
to 4# armrtems
你说的malloc的配置选项是RVDS 4.0的新功能吗?
up↑
阿莫电子论坛(原ourAVR/ourDEV)
© 2004-2014 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com
首页|标准版|触屏版|电脑版
参考3:
对于可重入、线程安全、异步信号安全几个概念的理解
http://blog.chinaunix.net/uid-293474-id-2134181.html
之前只觉得malloc,free导致的内存碎片的问题,没考虑这么多。那你觉得是将所有的malloc,free关中断保护好,还是直接拒绝使用malloc,free好呢?
我觉得你可以发一篇ida反编译的教程,让我们学习一下。
用的不好,我这是插件生成的。
{
.o .axf是elf格式的,mdk默认工程配置是保留调试信息的。
打开ida,.axf托进去,弹出的对话框凭感觉点掉。。。
点要看的函数(有调试信息,一般该有的符号(函数)都有),会看到汇编代码。
按下F5,反编译(前提是要下载带arm F5 插件的和谐版)
(.hex就不太好弄了,我又不玩破解...)
}
感谢支持啊,话说这个头像和你QQ头像差距好大啊
改进taskCreate,不再使用malloc和free进行自动内存分配。
删除void delay(unsigned int pid,unsigned int ticks);
新增函数void suspend(void),用于挂起任务本身。
新增函数void resume(unsigned int pid),用于恢复已经被挂起的任务或者被sleep阻塞的任务。