嵌入式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))

參考資料

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