OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 25353|回复: 40

发一个内存管理:基于FreeRTOS内存管理Heap_4.c

  [复制链接]

22

主题

180

帖子

1

精华

高级会员

Rank: 4

积分
616
金钱
616
注册时间
2015-6-29
在线时间
101 小时
发表于 2015-12-24 11:46:29 | 显示全部楼层 |阅读模式
        之前看了一下原子哥的内存管理程序,随着内存池的增大,内存管理表也会增大,会浪费一点内存空间,觉得不爽。一直想自己写一个,又不想重复造轮子,最近比较闲,研究了一下FreeRTOS的内存管理Heap_4.c,发现它的实现方法还挺简单的,而且比较实用,不过为了要像原子哥的内存管理那样管理三个内存池,还需要稍稍修改一下,我已经修改好了,测试了一下没发现问题,上传上来给大家瞧瞧,有兴趣的可以帮忙测试一下,哈哈。
      
        既然是在FreeRTOS内存管理Heap_4.c的基础上稍稍修改的,那还是先介绍一下它的实现方法吧:


        以下为转载内容,原文链接:http://xilinx.eetrend.com/blog/8197

FreeRTOS8.0.1内存管理的最后一个堆模型Heap_4,貌似是在这一个版本才有的。所以找到的说明几乎没有。代码的开头注释也只是简单地说了 一下实现了pvPortMalloc()和vPortFree()两个函数,并且能够对回收的内存块进行合并,减少碎片的出现。(A sample implementation of pvPortMalloc() and vPortFree() that combines (coalescences) adjacent memory blocks as they are freed, and in so doing limits memory fragmentation.)不过经过这一次的剖析之后,发现Heap_4所用的内存管理算法为首次适配法(first fit algorithm)。

和Heap_2一样,Heap_4先申请了一个数组ucHeap[ configTOTAL_HEAP_SIZE ]作为自己管理的堆空间,同样也有空闲块头结构BlockLink_t来管理空闲块。但是和Heap_2不一样的是,Heap_4用了 BlockLink_t中xBlockSize的最高一位来标识某个内存块是否处于空闲状态。所以这就是为什么会有一个宏 heapBITS_PER_BYTE的出现,而且定义为( ( size_t ) 8 )。这样一来,每一个分配出去的内存块大小就有限制了。例如,我用的是STM32F103,size_t是定义为unsigned int类型的,32位,可支持到4G的内存空间。但是最高1位用来指示空间状态的话,那就只有31位去标识内存块地址,即只支持到2G的内存空间。所以用 Heap_4还是有一点点代价的,特别是用在16位或8位的单片机上。
还是先剖析一下堆空间的初始化过程prvHeapInit()。首先还是先将内存堆进行首地址对齐。接下来就是运用xStart和pxEnd来组织整个空 闲块链表。要注意的是,xStart是BlockLink_t的一个实体变量,存储在静态存储区,而pxEnd只是BlockLink_t的一个指针,存 储在静态存储区中,却指向了内存堆的最后一个BlockLink_t大小的位置上。也就是说,内存堆最后的空间是存储着一个BlockLink_t,用来 指示空闲块链表的终结,这是和Heap_2有所不同的地方。下图说明了初始化流程最终将空闲块链表组织成的样子。

接下来剖析Heap_4的第一个重点:pvPortMalloc()。和以前一样,分配内存之前还是先调用vTaskSuspendAll()挂起所有任 务,以确保分配内存的过程不被中断。下一步通过判断pxEnd是否为空来决定是否需要初始化内存堆和空闲块链表。因此,初始化之后pxEnd就不为空了, 以后再调用pvPortMalloc()也因此不再调用初始化函数。但是这一个判断的另一个分支(else分支却调用了一个 mtCOVERAGE_TEST_MARKER()的宏,这个宏的定义在FreeRTOS.h里,定义为空。因此目前还不知道这一个宏具体作用,看名字应 该是用来测试什么的。接下来是判断用户申请内存大小的最高位是否为0,为0即合法(之前说过,最高位用来标识空闲块的空闲状态,因此最高位为1则说明用户 申请的内存大小已超出空闲块的最大大小)。然后还是一个size_t类型的数据与0比较的判断(虽然这个判断总为真,但也不知道作者为啥要写这么一个判 断,要是有人知道这一个判断的意途,请告诉我),里面是增大用户申请的空间大小以便容纳空闲块块头BlockLink_t以及将最终申请的内存大小进行对 齐。
以上的预处理完成了,开始进入分配算法的核心了。只要最终申请的空间大小仍在空闲空间大小的范围内,则进入内存的分配。首先遍历链表,找到第1块能比申请 空间大小大的空闲块,修改空闲块的信息,记录用户可用的内存首地址。接下来,如果分配出去的空闲块比申请的空间大很多,则将该空闲块进行分割,把剩余的部 分重新添加到链表中。
分配内存的主要流程基本结束了,和之前分析的一样,pvPortMalloc()继续调用调试宏traceMALLOC()输出调试信息,恢复所有挂起的 任务,并按设置调用勾子函数vApplicationMallocFailedHook(),最终把用户可用的内存首地址返回。到这里整个 pvPortMalloc()就结束了。
但是,有一个地方刚刚没怎么详细讲,就是把分割出来的空闲块重新添加到链表中的过程。现在来详细分析一下,这也是Heap_4的一个重点。和Heap_2 不同,这一次的prvInsertBlockIntoFreeList()并不是写成一个宏,而是写成了一个函数。进入函数的开始,可以看 到,FreeRTOS实际上是将这个空闲块链表里的所有空闲块按地址顺序排列的。当然,如果不这么排列,怎么能将相邻的空闲块进行合并呢?将要回收的空闲 块为pxBlockToInsert,这个空闲块将被插到pxIterator的后面。通过一次链表的遍历,就把pxIterator找出来了。接下 来,FreeRTOS先试着将pxIterator和pxBlockToInsert进行合并,可以合并的标准为pxIterator的首地址加上 pxIterator的块大小之后等于pxBlockToInsert的首地址。相等就说明两个块是相邻的。如果不能合并,就什么事都不做。然 后,FreeRTOS再试着将pxBlockToInsert和pxIterator指向的下一个空闲块进行合并。可合并的标准和刚刚说的一样,只是这次 用pxBlockToInsert的首地址加上pxBlockToInsert的块大小与pxIterator指向的下一个块地址比较。能合并是最好的, 不能合并,则要修改pxBlockToInsert的Next指针,指向pxIterator的下一个空闲块。这是链表插入的基本操作,不用再细讲了。最 后,要是pxBlockToInsert没有和pxIterator合并,则还要修改pxIterator的Next指针,这样整条链表才完整无误。
最后一个重点是vPortFree()。不过这里的vPortFree()的流程和Heap_2的差不多,只是判断指针合法性的时候多了两个条件,一个是 检查回收的块大小最高位是否为1,为1才是合法的,毕竟是分配出去了嘛。第二个是Next指针是否为空,为空了说明那是pxEnd,那就不能回收了。在这 两个判断之前也有这两个条件的断言configASSERT(),定义在FreeRTOS.h里,同样也是定义为空,可能是留给用户另外用的吧。
Heap_4的其它三个函数,一个名字看上去是做什么初始化的,却什么都没有实现,所以没啥好讲的,另外两个只是用来返回内存堆的一些状态而已,所以也没啥好讲的。到这里,整个Heap_4就剖析完成了。


        PS:以下是使用方法
1、在.c里注释掉#include "../BSP/sys.h",加上自己的声明OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()的头文件(其实就是进入和退出临界区,跟原子哥的一样也可以)

2、在.h里配置一下是否使用内部内存池、外部内存池、内部CCM内存池,COUT_OF_MEM是内存池数量
#define EN_SRAM_IN                  (1)
#define EN_SRAM_EX                  (1)
#define EN_SRAM_CCM                 (1)
#define COUT_OF_MEM                 (3)                 //有多少块内存

3、配置各个内存池的大小
#define configTOTAL_HEAP_SIZE1        ( ( size_t ) ( 10 * 1024 ) )//内部内存池大小
#define configTOTAL_HEAP_SIZE2        ( ( size_t ) ( 900 * 1024 ) )//外部内存池大小
#define configTOTAL_HEAP_SIZE3        ( ( size_t ) ( 60 * 1024 ) )//CCM内存池大小

4、在.c里面我已经把外部内存池和CCM内存池的起始地址固定了,有需要的可以改变
    #if (EN_SRAM_IN == 1)
        __align(8) static uint8_t ucMemSRAMIn[ configTOTAL_HEAP_SIZE1 ];
    #endif
    #if (EN_SRAM_EX == 1)
        __align(8) static uint8_t ucMemSRAMEx[ configTOTAL_HEAP_SIZE2 ]  __attribute__((at(0X68000000)));
    #endif
    #if (EN_SRAM_CCM == 1)
        __align(8) static uint8_t ucMemSRAMCCM[ configTOTAL_HEAP_SIZE3 ] __attribute__((at(0X10000000)));
    #endif

5、使用示例
申请外部内存:p= fMalloc(2048*1024,SRAM_EX);
释放:fFree(p,SRAM_EX);

fMalloc.c

16.36 KB, 下载次数: 913

fMalloc.h

2.93 KB, 下载次数: 339

我是菜鸟
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

72

主题

2711

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3505
金钱
3505
注册时间
2014-8-4
在线时间
696 小时
发表于 2015-12-24 11:55:03 | 显示全部楼层
谢谢分享,抽空研究学习一下......
以我资质之鲁钝,当尽平心静气、循序渐进、稳扎稳打之力。
回复 支持 反对

使用道具 举报

13

主题

296

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2066
金钱
2066
注册时间
2012-5-26
在线时间
291 小时
发表于 2015-12-24 11:56:54 | 显示全部楼层
谢谢分享,mark一下~
活着才是王道!健康是一切的前提!
回复 支持 反对

使用道具 举报

27

主题

711

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
11922
金钱
11922
注册时间
2015-11-5
在线时间
2086 小时
发表于 2015-12-24 15:56:28 | 显示全部楼层
heap_4方案确实比heap_2好,heap_2是以最适合的内存块来分配的,没有空闲块合并功能,并且实际用起来很容易出现内存分配失败

heap_4方案具有相邻空闲块合并的功能,但缺少了heap_2的最优分配,因此还是留下了缺陷,但实际应用heap_4的稳定性比heap_2强很多

FreeRTOS的内存管理方案一直都被人诟病,期待楼主能将heap_2和heap_4的优点合并起来,个人认为这样就比较贴合实际需求了
拿来长岛冰茶换我半晚安睡
回复 支持 反对

使用道具 举报

15

主题

786

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
3223
金钱
3223
注册时间
2015-7-26
在线时间
811 小时
发表于 2015-12-24 16:05:28 | 显示全部楼层
先顶再看,谢谢分享
我的博客:http://blog.csdn.net/itdo_just
回复 支持 反对

使用道具 举报

22

主题

180

帖子

1

精华

高级会员

Rank: 4

积分
616
金钱
616
注册时间
2015-6-29
在线时间
101 小时
 楼主| 发表于 2015-12-24 16:31:22 | 显示全部楼层
回复【4楼】FreeRTOS:
---------------------------------
没有你研究的透彻,哈哈。
本来是想直接用原子哥的算了,后来有时间了,就看了一下heap_4,觉得可以满足我目前的需求,内存分配如果再深究下去也是不简单的,更高级一点的分配算法在其他RTOS上应该会有(如Linux),有时间再学习一下。
我是菜鸟
回复 支持 反对

使用道具 举报

27

主题

711

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
11922
金钱
11922
注册时间
2015-11-5
在线时间
2086 小时
发表于 2015-12-24 16:39:02 | 显示全部楼层
回复【6楼】负西弱:
---------------------------------
我没有你这么大的志向,只是希望有更多的人去发扬光大FreeRTOS,也希望楼主考虑下我的建议,感觉这个想法还是不错的!
拿来长岛冰茶换我半晚安睡
回复 支持 反对

使用道具 举报

22

主题

180

帖子

1

精华

高级会员

Rank: 4

积分
616
金钱
616
注册时间
2015-6-29
在线时间
101 小时
 楼主| 发表于 2015-12-24 16:49:37 | 显示全部楼层
回复【7楼】FreeRTOS:
---------------------------------
我也是刚刚开始用FreeRTOS,资料实在太少,可以多多交流~~
我是菜鸟
回复 支持 反对

使用道具 举报

27

主题

711

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
11922
金钱
11922
注册时间
2015-11-5
在线时间
2086 小时
发表于 2015-12-24 17:00:58 | 显示全部楼层
回复【8楼】负西弱:
---------------------------------
加个好友呗,我q:410846867
拿来长岛冰茶换我半晚安睡
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2015-12-24 19:09:20 | 显示全部楼层
不错,cool
回复 支持 反对

使用道具 举报

22

主题

180

帖子

1

精华

高级会员

Rank: 4

积分
616
金钱
616
注册时间
2015-6-29
在线时间
101 小时
 楼主| 发表于 2015-12-24 20:18:46 | 显示全部楼层
回复【10楼】正点原子:
---------------------------------
哈哈,谢谢原子哥
我是菜鸟
回复 支持 反对

使用道具 举报

8

主题

175

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
407
金钱
407
注册时间
2011-3-31
在线时间
51 小时
发表于 2015-12-25 22:45:50 | 显示全部楼层

先顶再看,谢谢分享
代开发智能楼宇对讲通讯、交直流无刷电机驱动、无功功率补偿器、电力仪表、电气火灾监控系统、(电梯远程监控、对讲通讯系统、TFT楼层显示)开发等。代理记账(限北京)联系方式:15300201607?shop65501025.taobao.com
回复 支持 反对

使用道具 举报

13

主题

53

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
331
金钱
331
注册时间
2015-12-13
在线时间
83 小时
发表于 2016-8-17 16:40:10 | 显示全部楼层
mark
回复 支持 反对

使用道具 举报

12

主题

126

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
281
金钱
281
注册时间
2013-1-5
在线时间
22 小时
发表于 2017-2-12 21:49:59 | 显示全部楼层
多谢分享,抽空学习下
天道酬勤
回复 支持 反对

使用道具 举报

0

主题

29

帖子

0

精华

高级会员

Rank: 4

积分
671
金钱
671
注册时间
2012-2-24
在线时间
226 小时
发表于 2017-8-17 11:41:43 | 显示全部楼层
谢谢分享。正在学习中
回复 支持 反对

使用道具 举报

1

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
123
金钱
123
注册时间
2017-8-21
在线时间
32 小时
发表于 2017-8-21 11:28:14 | 显示全部楼层
真的很不错
回复 支持 反对

使用道具 举报

11

主题

179

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1100
金钱
1100
注册时间
2016-7-19
在线时间
168 小时
发表于 2017-8-22 10:59:49 | 显示全部楼层
mark
回复 支持 反对

使用道具 举报

11

主题

99

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
5267
金钱
5267
注册时间
2015-11-5
在线时间
681 小时
发表于 2017-11-9 20:34:23 | 显示全部楼层
牛逼,给楼主点个赞,有空也可以看一下lwip里面的内存堆分配方式,可以看一下老衲五木写的那本很经典的书。
回复 支持 反对

使用道具 举报

1

主题

15

帖子

0

精华

新手上路

积分
42
金钱
42
注册时间
2016-9-26
在线时间
7 小时
发表于 2017-12-5 19:28:39 | 显示全部楼层
我只用内存1
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
65
金钱
65
注册时间
2017-12-11
在线时间
23 小时
发表于 2018-1-11 19:02:23 | 显示全部楼层
请问现在heap4实现realloc了吗 我下载了一个源码 好像没有
回复 支持 反对

使用道具 举报

9

主题

141

帖子

1

精华

高级会员

Rank: 4

积分
606
金钱
606
注册时间
2017-1-3
在线时间
65 小时
发表于 2018-3-2 10:32:15 | 显示全部楼层
在使用heap4的时候,一直在报一个错误,不知道是哪里的原因

Error:..\FreeRTOS\portable\MemMang\heap_4.c,320
Error:..\FreeRTOS\portable\MemMang\heap_4.c,321

实际上我使用  BT_Init_pntr = pvPortMalloc(20);
测试发现 指针也不为空,就是说分配完成了,经测试,发现报的错误是从Malloc里面的断言发出的
回复 支持 反对

使用道具 举报

2

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2018-4-29
在线时间
21 小时
发表于 2018-7-27 21:13:16 | 显示全部楼层
BJTT 发表于 2018-3-2 10:32
在使用heap4的时候,一直在报一个错误,不知道是哪里的原因

Error:..\FreeRTOS\portable\MemMang\heap_4 ...

我也遇到这个问题,不知道您后面是怎么解决的呢?
回复 支持 反对

使用道具 举报

2

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
79
金钱
79
注册时间
2018-4-29
在线时间
21 小时
发表于 2018-7-27 21:13:52 | 显示全部楼层
我也遇到了这个问题,我的内存是申请过的
[mw_shl_code=c,true]t = pvPortMalloc(256);
                                printf("point(t) = %p\r\n", t);
                                sprintf(t, "%s:%s", serverhost, serverport);                                                                                        // Cache Host
                                content = pvPortMalloc(256);
                                sprintf(content, GET, p, t);
                                printf("%s\r\n", content);
                                esp8266_send_data((u8*)content, (u8*)"200 OK", 400);
                                // printf("%s\r\n", USART3_RX_BUF);
                                t = strstr((char*)USART3_RX_BUF, "{");
                                switchUtf8ToGbk(t, content);
                                vPortFree(t);
                                t = NULL;[/mw_shl_code]

回复 支持 反对

使用道具 举报

8

主题

63

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
424
金钱
424
注册时间
2016-4-26
在线时间
84 小时
发表于 2018-7-28 08:54:01 | 显示全部楼层
有时间学习一下
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2019-9-18
在线时间
5 小时
发表于 2019-9-19 09:44:43 | 显示全部楼层
谢谢,下载学习一下
回复 支持 反对

使用道具 举报

0

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
176
金钱
176
注册时间
2019-4-27
在线时间
49 小时
发表于 2019-12-27 08:36:52 | 显示全部楼层
谢谢,下载学习
回复 支持 反对

使用道具 举报

0

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
176
金钱
176
注册时间
2019-4-27
在线时间
49 小时
发表于 2019-12-27 08:38:35 | 显示全部楼层
谢谢 好好学学
回复 支持 反对

使用道具 举报

2

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
195
金钱
195
注册时间
2019-12-3
在线时间
47 小时
发表于 2020-1-6 19:48:03 来自手机 | 显示全部楼层
文件无法访问是为什么呀
回复 支持 反对

使用道具 举报

2

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
195
金钱
195
注册时间
2019-12-3
在线时间
47 小时
发表于 2020-1-6 23:00:37 | 显示全部楼层
还是无法读取,难受
回复 支持 反对

使用道具 举报

2

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
195
金钱
195
注册时间
2019-12-3
在线时间
47 小时
发表于 2020-1-7 16:08:42 | 显示全部楼层
有兄弟知道怎么下载么,我下载不了
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

新手上路

积分
21
金钱
21
注册时间
2019-9-11
在线时间
5 小时
发表于 2020-11-20 17:56:26 | 显示全部楼层
无法下载?
回复 支持 反对

使用道具 举报

0

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2021-2-4
在线时间
14 小时
发表于 2021-10-23 13:17:28 | 显示全部楼层
无法下载
回复 支持 反对

使用道具 举报

0

主题

451

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3316
金钱
3316
注册时间
2016-3-19
在线时间
815 小时
发表于 2021-10-27 17:04:05 | 显示全部楼层
抽空学习一下  
回复 支持 反对

使用道具 举报

15

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
178
金钱
178
注册时间
2013-9-24
在线时间
20 小时
发表于 2021-11-22 10:34:11 | 显示全部楼层
抱歉,该附件无法读取
回复 支持 反对

使用道具 举报

8

主题

168

帖子

0

精华

高级会员

Rank: 4

积分
557
金钱
557
注册时间
2015-7-4
在线时间
104 小时
发表于 2022-8-25 11:10:13 | 显示全部楼层
FreeRTOS 发表于 2015-12-24 15:56
heap_4方案确实比heap_2好,heap_2是以最适合的内存块来分配的,没有空闲块合并功能,并且实际用起来很容易 ...

freeRTOS的heap_5听说就是实现多块内存管理的
回复 支持 反对

使用道具 举报

2

主题

48

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
372
金钱
372
注册时间
2018-9-14
在线时间
51 小时
发表于 2022-8-29 09:27:56 | 显示全部楼层
mark!
回复 支持 反对

使用道具 举报

0

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
58
金钱
58
注册时间
2021-3-7
在线时间
14 小时
发表于 2023-1-30 09:36:42 | 显示全部楼层
为什么无法获取
回复 支持 反对

使用道具 举报

0

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
131
金钱
131
注册时间
2014-5-5
在线时间
25 小时
发表于 2023-2-2 17:58:43 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

0

主题

37

帖子

0

精华

初级会员

Rank: 2

积分
131
金钱
131
注册时间
2014-5-5
在线时间
25 小时
发表于 2023-2-2 17:59:34 | 显示全部楼层
为什么无法获取
回复 支持 反对

使用道具 举报

0

主题

451

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3316
金钱
3316
注册时间
2016-3-19
在线时间
815 小时
发表于 2023-4-7 10:58:05 | 显示全部楼层
多年后  再次分析一下   感觉还是有收获滴
Nothing is impossible
回复 支持 反对

使用道具 举报

12

主题

156

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2551
金钱
2551
注册时间
2017-12-16
在线时间
187 小时
发表于 2023-7-21 15:49:46 | 显示全部楼层
先收藏,后边慢慢理解!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 17:03

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表