임베디드 시스템에서 실행파일 동작
공부하다가 궁금하게 생겨서요..!!
소스코드를 작성하고
크로스 컴파일을 해서 소스코드의 실행파일을 만들었을 때
이 실행파일을 타겟(보드)에서 동작시키기 위해 타겟(보드)의 NAND Flash Memory에 다운로드를 했다고 가정하겠습니다
그러면 제가 알기로는
NAND Flash Memory에 넣어진 실행파일은 RAM으로 copy되어져서 RAM에서 실행한다고 알고있어요(NAND에서는 실행할 수 없으니까)
그런데 또 보다보니 NAND에 실행파일과 초기화된 전역변수는 NAND의 Text영역과 Data영역에 들어가고
이것이 복사되고
또 RAM에서 Stack, Heap, Bss 영역등에 지역변수나... 초기화되지않은 전역변수의 값이 들어갈 영역으로 나뉜다고 했습니다
여기까지도 맞는지 모르겠지만...
그럼 여기서 또 궁금한건
이러한 각 메모리 영역의 크기는 어떻게 무엇을 기준으로 나누어지는 것인지입니다
하드웨어 자체에서 메모리에서 얼마만큼은 Stack영역, 얼마만큼은 Data영역... 이렇게 정해져있는건가요?
아니면 제가 어떠한 설정파일을 넣어서 나눠주는 건가요...?
이러한 메모리 영역을 설정하는 부분이 실행파일의 내부에 같이 있나요?
그렇다면 실행파일은 ROM에 저정하는데 어떻게 그 설정부분을 설정해서 값들을 저장해주나요...?
혹시 제가 이상한길로 빠지고 있는것 같다면 실제로 실행파일이 어떻게 임베디드시스템에서 동작하는지(메모리도 같이) 간략하게 설명좀 부탁드릴게요...ㅠㅠ
Flash 에서도 실행가능합니다.
Flash 에서도 실행가능합니다. StartUpROM이 Flash에서 동작하고요. SUROM(StartUp ROM)의 역할은 SW를 ROM에서 실행할 지, RAM 으로 복사해서 실행할 지 결정해서 그렇게 해 줍니다.
Stack, Heap, BSS 등은 linker script 라고 부르는 설정 파일에 기록된 대로 linker 가 메모리를 나눠줍니다.
컴파일된 결과는 어떻게 메모리 영역이 결정된다고 해도 나중에 실행할 수 있게끔 relocatable 한 형태로 나타나게 되죠.
메모리 영역을 설정하는 부분이 StartUp ROM 에 있습니다. objdump 인가로 보면 최종 생성된 SW 이미지의 각 내용이 위의 linker script 에 기록된 메모리 영역대로 파티션 되어 들어가 있는 것을 확인할 수 있습니다.
열공하시면 됩니다. 열공하세요 ~~
c프로젝트가있을때.. 타겟에서 실행을 하기
c프로젝트가있을때.. 타겟에서 실행을 하기 위해서
크로스 컴파일과정을 거쳐서 타겟에서 동작할 수 있는 실행바이너리를 생성
실행바이너리를 타겟에 저장하고 실행하기위해서 NAND Flash Memory에 저장
**이때**
공부하기로는 NAND Flash Memroy에 저장을 할 때 code와 const값을 넣는 RO(Read Only)영역과 RW(Read Write)영역으로 나눠서 저장한다고 공부함
실행바이너리를 실행하지도 않았는데 어떻게 저영역들을 알아서 RO와 RW를 구분해서 넣어 저장하나요!?
(왜냐면 실행바이너리 안에 링커스크립트로 나눈 메모리영역에 관련된 바이너리가 있을 것이라고 생각. RAM에 들어가지 않아서 실행을 하지 않았을텐데...)
NAND Flash Memory는 Random Access가 되지 않아서 Random Access가 가능한 SDRAM으로 복사해서 실행을 해야함
NAND Flash Memory에 저장했을때 인터널 램의 부트로더가 NAND Flash Memory에 저장한 실행바이너리를 SDRAM으로 옮겨줌
**이때**
마찬가지로 SDRAM영역도 bss, heap, stack영역이 다 분리되어 있다고 공부했는데...
이건 또 언제나눠저서 값들이 저장되는지...
뭔가 꼬인것 같네요...ㅠㅠ
이해를 좀 도와주세요...설명좀 ㅠㅠ
컴파일러의 마술입니다. 컴파일러는 프로그램 코드를
컴파일러의 마술입니다. 컴파일러는 프로그램 코드를 해석해서 RO, RW 영역을 구분해 내고 그것을 각각 별도의 메모리 영역으로 잡습니다. 중요한 것은 모든 것은 실행 바이너리가 실행되기 전에 모두 결정됩니다. 실행 바이너리는 그냥 실행될 뿐입니다.
RAM에서 돌아가던지 ROM에서 돌아가던지가 중요한 것은 아닙니다. 필요한 메모리 주소 재배치 등은 자동으로 linker가 해줍니다.
ROM에서 실행할 경우 RO 부분은 그대로 ROM에 남아있고, RW 부분만 RAM에 복사됩니다.
RAM에서 실행할 경우 RO, RW 부분을 모두 RAM에 복사합니다. 그리고 stack 이 있어야 겠죠(C 언어라면)
아 그렇군요!! 답변감사드려요!!!
아 그렇군요!! 답변감사드려요!!! ㅠㅠㅎㅎ
컴파일러에서 이미 RO, RW를 구분해서 실행바이너리를 만들어 주는군요!
그럼 부트로더가 ROM에서 RAM영역으로 loading을 할 때 부트로드는 어디까지가 RO영역이고 어디까지가 RW영역인지 어떻게 알 수 있나요?!
그리고 혹시 링커가 메모리 주소를 재배치 해주기위해 사용하는게 링크스크립트같은데
이 링크스크립트는 어떤 파일에 작성하나요?ㅠ
.ld라는 파일... 같은 것을 찾을수가없어서 ㅠㅠ
부트로더는 그 RW, RO 영역 정보를 알고나서
부트로더는 그 RW, RO 영역 정보를 알고나서 생성되는 겁니다.
링크 스크립트는 linker 가 최종 실행 바이너리를 만들 때 사용합니다. 보통 ldscript 등으로 되어 있고 .ld 같은 확장자와 같은 규칙은 없습니다. -Xm 이던가 그런 지정자로 알려줄 수 있습니다.
linker 가 수행한 해당 결과는 생성된 실행 바이너리를 objdump 를 통해 보면 확인 가능합니다.
컴파일러와 링커를 언급하시면서... "RO, RW
컴파일러와 링커를 언급하시면서...
"RO, RW 영역을 구분해 내고 그것을 각각 별도의 메모리 영역으로 잡는" 역할을 컴파일러가 한다고 이야기 하시니 의아합니다.
단지 컴파일러와 링커를 통칭하여 컴파일러라고 언급 한다면 다르지만요...
컴파일러는, 이를테면 RO, RW 영역이 구분될 수 있도록 나누어 놓기만 하고 메모리 영역을 잡지 않는것으로 알고 있습니다.
메모리 영역을 잡는 '계획'은 링커스크립트 등에 의해 지정되며, 링커가 그 '계획'을 반영하여, 바이너리 파일을 만듭니다.
따라서 RAM에서 돌아가느냐 ROM에서 돌아가느냐 하는 부분은 매우 중요하고,
이것은 링커가 자동으로 해주지 않으며, 임베디드 시스템 환경에 맞게 수립된 '계획'이 필요 합니다.
맞습니다. 다만 제가 이야기한 " ..... 그것을
맞습니다. 다만 제가 이야기한 " ..... 그것을 각각 별도의 메모리 영역으로 잡습니다. ...." 라는 말은
메모리를 생성한다는 의미가 아니라 category 화 한다는 의미였습니다.
ELF 파일 포맷에 대해서 보시면 도움이 될듯 합니다.
ELF 포맷과 binary 파일을 readelf 툴로 확인하시면 질문하신내용 답변 될 듯 합니다.
댓글 달기