嵌入式linux开发 (三十一) 内存管理2.0(2) freertos内存管理

代码分析

  • 内存分段初始化部分
startup_stm32f407xx.s
	Reset_Handler
		初始化栈 	// 系统.stack段
		// .code 段没做动作
		// .bss  段没做动作
		从flash 上 加载data 段入sram
		清bss段
		SystemInit
		__libc_init_array // .heap 和 C 库
		main // 功能函数

$ nm build/startup_stm32f407xx.o  |grep " U "
         U _ebss	// 在 STM32F407ZETx_FLASH.ld中	
         U _edata	// 在 STM32F407ZETx_FLASH.ld中	
         U _estack	// 在 STM32F407ZETx_FLASH.ld中	
         U __libc_init_array
         	// 在 /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/armv7e-m/fpu/libc_nano.a(lib_a-init.o)中
         	// /usr/lib/arm-none-eabi/lib/armv7e-m/fpu/libc_nano.a
         U main		// 	在 USER/main.c 中
         U _sbss	// 在 STM32F407ZETx_FLASH.ld中	
         U _sdata	// 在 STM32F407ZETx_FLASH.ld中	
         U _sidata	// 在 STM32F407ZETx_FLASH.ld中	
         U SystemInit	// 在 STM32F407ZETx_FLASH.ld中	

  • rtos 内存管理部分
main
	xTaskCreate(start_task)
	vTaskStartScheduler

start_task
	taskENTER_CRITICAL
	task1_task
	task2_task
	taskEXIT_CRITICAL

task1_task
	while(1)
task2_task
	while(1)


-------------

1. 首先创建了一个任务A
2. 然后开始调度
3. A开始执行
4. A创建了两个任务B C ,并删除了任务A
5. B 开始执行
6. B结束执行,C 开始执行
7. C结束执行,B 开始执行
8. B结束执行,C 开始执行
9. ...


分析到 6 应该能分析完所有系统做的内存相关的动作.这里面包括了所有状态下的调度.
3中的 A 开始执行 // A 执行,有个关键状态:调度开始
5中的 B 开始执行 // B 执行,有个关键状态:A被删除
6中的 C 开始执行 // C 执行,无关键状态

从其他角度分析

os管理内存的话
1. 为 os 提供 api 和 内存空间
	1. os的正常运行需要内存
		1.1 os的 各个段 // free rtos OS是不是只有一个调度器? 属于 .code
			.code
				// 调度器 ,对于stm32 ,应该是在flash 里面
			.data
				// 具体要分析调度器的代码
			.ro-data
			.bss
			.stack
			.heap
		1.2 调度器
		1.3 消息队列
			// 先不关心
		1.4 定时器
			// 先不关心
		
2. 为 user space 提供 api和内存空间
	1. os 需要维护应用程序的状态(TCB和STACK)
		2.1 为了提供应用程序需要的各个段做了什么
			// .code  在哪里,应该是在flash里面,但是需要每个应用程序知道,是用PC管理的
			// .ro-data //.code 知道 .ro-data 在哪里,应该和 内核的.data在一起
			// .data //.code 知道 .data 在哪里,应该和 内核的.data在一起
			// .bss  // 在生成二进制文件的时候.bss 是不是已经定了
				// 如果定了的话,那么应用程序的.bss 应该和 内核的.bss在一起
				// 如果不定,.code 里面有对.bss特定地址索引,os处理的时候需要怎么处理
			// .stack // 对于每个.code ,分配不同的栈,这个通过PC来控制
			// .heap // 这个可以对于每个.code ,分配不同的.heap,也可以和内核公用
				// 如果共用的话,就很简单, 用户的.heap 和 内核的.heap 是一个 .heap ,但是不能限制用户用多少.heap
				// 如果不共用的话,内核要在load应用程序的时候自动分配heap空间,并初始化 , 并提供malloc 函数,买个应用程序返回的是其特有的heap
用户使用内存的话
1. 使用 os 提供的malloc 函数 操作 os 提供给应用程序的空间.
	1.1 应用程序的各个段在哪里
	1.2 应用程序什么时候用了哪个段
		运行的时候
			.code 从 flash 加载,通过TCB中的PC控制
			.ro-data 直接在.code中,通过.code索引
			.data 在 ram ,通过 .code 索引
			.bss 在 ram ,通过.code 索引
			.stack 在 ram ,通过TCB中的SP索引
			.heap 在 ram ,通过malloc索引
		不运行的时候
			.code 对应的PC放在了 TCB 中,其他进程不能访问该进程TCB,也就访问不了该进程的.code
			.ro-data 在 .code中
			.data .bss 在ram中,其他进程没有 索引(索引在.code中)
			.stack 对应的SP被放在了TCB中,其他进程不能访问该进程TCB,也就访问不了该进程的.stack
			.heap 在 ram 中,已经被malloc过,未被free,其他进程不能malloc到该进程的.heap
			
------------------------------
按照stm32 freertos来说
系统的.code(调度器) .ro-data .data .bss .heap 和 应用程序的.code(功能函数) .ro-data .data .bss .heap 是在一块的
系统的.stack 和 应用程序的.stack 是分离的..code .ro-data 在flash上
.data .bss .heap .stack 在内存里
另外内存里还有每个进程的TCB

所以整体来说,大小的话
初始化的时候 .data .bss 是初始化好的,占用的内存可以通过map来查看
另外只要知道 .heap(可以通过配置来查看) .stack(可以通过配置来查看) TCB(可以通过配置来查看) 占用多少内存就可以了

整体来说,布局的话
flash
	.code .ro-data // 应用程序的和系统的混在一起了
ram
	.data .bss .heap  TCB(应用程序) // 注意: TCB在.heap里面 // 应用程序的和系统的混在一起了
	.stack(内核) .stack(应用程序1) .stack(应用程序2) ...  // 应用程序的和内核的分开了
	// freertos 的 应用程序stack 是在 .heap中申请的 , 内核stack 是 一开始初始化的
---------------------------和裸机内存的布局有什么不同
1.大体相同(都是 .code .ro-data .data .bss .heap .stack)
2.只不过.heap被内核用了一部分(用于TCB的管理)
3.stack被分成了很多份(内核一份(内核的stack在.stack),每个应用程序一份(用户的stack在.heap))

参考资料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章