센로그

6. Game Engine Support System (2) 본문

게임/게임 엔진 기초

6. Game Engine Support System (2)

seeyoun 2022. 12. 8. 04:59

◆ Kernel

OS가 가지고있는 프로그램

컴퓨터 밑단에서, core한 애들을 다뤄주는 애들이 존재한다.

컴퓨터 파워를 키면,  가장먼저 실행되는 프로그램이 bootstrap 프로그램(ROM)

그 다음에 올라오는게 oskernel 프로그램

 

 

커널의 크리티컬한 코드들은 메모리의 분리된 공간에 로드됨.

여기 올라와있는 커널 코드들은 크리티컬 코드가 아닌 곳에서 접근해오거나,

Application 단에서 접근해 오는 걸 막는 것임.

이 공간을 kernel space라고 부름.

이게 우리가 그 os의 권한을 얻어서 하기 힘들다 했던 그 접근 권한에 해당하는 거임.

내가 프로세스를 돌리거나, 하드웨어 디바이스, 핸들링.. 이런거를 얘가 관리함

 


▶ 구성

kernel space ↔ user space

 

user space에서 오류 나면, 걍 그 프로그램 죽임

kernel space에서 오류 나면, 블루스크린

 

게임(user space)가 커널 스페이스에 존재하는 얘네한테 접근해서 무언가를 처리하고자 하면,

정해진 규약에 따라 system call을 해야함

 

이것을 wrapper function의 형태로 호출하게 됨(실제로 실행하고 싶은 애를 감싼 것. 이 감싼 친구만 시스템 콜로 인정하겠어! 라는 느낌의 일종의 규약)

 

그럼 왜 굳이 이렇게 귀찮게 해놨을까?
커널은 시스템의 low-level이기때문에 다 컨트롤할 수 있는 중요한애임.
그러므로 아무 프로그램이나 나한테 명령하게 할 순 없음.  보안적인 문제.

 


◆ Memory Fragmentation

Dynamic Heap alloc을 사용하면 Memory Fragment가 일어난다는 문제.

필요없는 부분을 막 free하다보면 저렇게 떨어져서.. 저렇게 됨

50 사이즈 공간이 존재함에도 사용할 수 없게 되는 거.

 

 

시간이 흐를수록 allocationdeallocation이 반복돼서 일어나면 점점 메모리가 파편화됨

그러면 연속된 큰 자리가 없어서 못 넣는 상황 발생

 


◆ Virtual memory

PC에선 Memory Fragmentation 큰 문제 없음. 왜냐면, virtual memory 에 의해 거의 자동으로 핸들링 됨

논리 주소와 물리 주소를 맵핑해서 사용

Address는 메모리의 어떤 영역을 표현하기 위해 쓰는 숫자 같은 거.

여기서 logical addressphysical address에 접근하기 위해 사용하는 레퍼런스 같은거임.

Physical address는 실제로 램에 존재하는 메모리 주소라고 하면,

Logical addressphysical address랑 매핑해서 사용하는거

프로그램별로, A프로그램이 사용하는 논리주소와 B프로그램이 사용하는 논리주소가 따로있음

 

(물리주소가 실제로 어딘진 우리는 모름. 논리 주소는 알 수 있음)

 


Page

virtual memory 이해하기 위해 page를 알아야함. Pagefixed-length를 씀.

고정된 길이를 가지는 연속된 메모리 공간

(Pool 기반 관리할때 사이즈 같은 블록으로 쪼갰던거랑 유사함)

같은 크기로 나눴기 때문에 fragmentation이 일어날 필요가 없음.

 

페이지가 참조하는 페이지 테이블이 있음. 페이지가 얘를 참조해서 physical 메모리로 날아감

Virtual address space라는게 있음(logical address느낌으로 생각 )

앞에선 logical address 받아서 때려넣어서 physical address변환햇엇음

 

근데 page단위로 관리하면, page table을 참조해서 이게 physical memory 어디에 존재한다는 정보를

참조하고, 여기서 physical memory로 날아가게 됨.

virtual address 단에서는 연속된 것처럼 보이는. 형태로 0 1 2 3 4 이렇게.. 관리되고있는데

Physical memory로 가보면 전혀 연속 x

 

근데, pagefixed length라서 그만큼의 메모리를 차지하는 framefixed length가 됨.

따라서 fragmentation발생안함(최소화됨)

여기서 주목해야 할 부분! Os가 내부적으로 페이지관리, virtual address update, physical memory 상에 연관된느

부분들을 모두 자동으로 해주고잇음.

그래서 우리가 pc로 개발하면 저렇게 자동으로 해결되고있는 경우가 되게 많음

virtual addressphysical address사이의 맵핑에 대한 정보를 저장해놓은 것이 page table이다.

 

 

Frame.

Page가 같은 크기이므로, Frame도 같은 크기를 가진다.

Framecontinuous하지 않다.

 


 TLB

그러면 virtual addresphysical address어케 바뀌느냐?

 

MMU는 캐쉬를 써야함. 근데 여기서 뭘쓰냐

Page table에서 최근에 어디에 참조했다는 걸 MMU 내부에서 캐쉬의 형태로 저장해놓음

이 캐쉬의 역할을 하는 친구가 바로 TLB

여기서 캐쉬란 무엇일까? 캐쉬 메모리가 무슨 역할을하느냐

속도 향상을 위해 씀. 어케 속도 향상하냐?

데이터가 100개정도 있을때, 최근에 사용했던 친구는 다시 쓸 확률이 높다고 판단함.

그래서 조금 용량은 작지만 훨씬 빨리 작동할 수 있는 곳에다가 옮겨놓는거.

즉 자주 접근하는 애들은 정해져있으니까, 캐쉬메모리로 빨리 접근

 

TLBMMU안에서 마치 캐쉬처럼 작동하는 버퍼임.

페이지에 내가 한번 접근햇으면, 또 접근할 확률이 높다고 판단해서

그친구를 TLB에다 옮겨놓음

, 페이지 테이블 가기전에 TLB 먼저가서데이터있냐? 확인함

있으면 == TLB Hit. (바로 physical address로 감)

없으면 == TLB Miss. (page table로 가면 됨. 어디이써~~)

 

그 다음에 찾앗어! 그러면 TLB에다가 데이터를 써주고, 그 다음에 physical내려감.

 

근데 만약에, page table → physical로 날아가는데, 메모리에 안 올라와있는 애들이 있을 수 있음

그러면 이제 Disk를 뒤짐. RAM에다가 올리는 작업을 해야함. Ram disk 사이에 데이터 교환이 일어남

== 굉장히 느림. Cpu에서 메인 메모리에 접근한느것도 느리지만, 메인 메모리에서 disk접근하는것도 엄청느림

 

 

 

- page fault.

Virtual address가 유효하지 않거나, 시스템적인 오류때문에 page fault가 날 수 있다

이런 현상이 일어나면 segmentation fault signal을 보내서 해결하게 만듦

디스크에 있는데 메인 메모리에 없는경우 가져와야함

우리가 페이지 테이블이 꽉차있는데, 새로운 데이터를 가져온다? 그럼 업데이트를 해야함

이때 안 쓰는 페이지를 죽이는 과정을 paged out 이라고 부름.

(File이면 swapfile이라고 부르고 partition이면 partition이라고 부름~)

이런 일들이 일어나면 당연히 시간이 좀더 걸리겟죠?

 


Virtual memory

3가지 장점

1.이런 sw형태의 데이터 접근 패턴을 만들 수 있다. 피지컬 메모리쪽은 연속되지 않은데, virtual 메모리 상에서는 연속된 데이터를 사용할 수 있는것.
2.우리가 물리주소의 실제 크기보다 더 큰 프로그램을 실행시킬 수 있는 것처럼 해줌. 실제 데이터가 존재하는 게 아니라, 엄청 크게 해도 상관이 없는거. Logical memory 상에선 100gb짜리 프로그램을 돌리고있는데, 램에서는 20gb만 있어도 램과 디스크 왔다갔다하면서 swap해가면서 하면 되잖아?(대신 느리겟지). 이걸 가능하게 해주는게 virtual memory. 
3.Virtual address를 사용하면 프로그램a와 프로그램 b가 사용하는 공간이 완벽하게분리됨. Physical memory를 바로 사용하면, ab가 사용하는 공간이 연속적일수도 잇으니까 삐끗 잘못하면 다른거 접근해버림. 그치만! Logical memory에서 하게되면, 프로그램이 좀 잘못되거나 오작동하더라도, 같은프로그램에서 사용되는 메모리만 가져오도록 설계되어잇으니까 훨씬안전하다.(구분되어있음)

 

 


Defragmentation

주기적으로 빈 공간 땡겨주기

하지만 이렇게 모두 이상적인 상황만 존재하는건 아니에요

항상 사이즈를 나눠서 균일하게 사용할수있는 상황이 아님! 347Mb100Mb단위로 끊으면, 53Mblost

그러면~ Defragmentation 해야함

Defragementation은 구멍들을 메우는 것.

블록을 옮기는 거임. 빈공간 없게

Hole을 찾고, hole 바로 다음에있는 블록을 찾아서 끌어당기는 것.

느림

메모리를 옮기는 와중에 접근하려고하면 곤란~

 


 Relocation

빈 공간 땡겨주며 옮길 때 나를 참조하고 있던 애들에게 내 옮긴 정보를 다 알려줘야 함!

 

Relocation

내가 메모리를 옮기면, 메모리 입장에선 옮기는거 쉬움 . 그러나..

외부에서 포인터로 나를 참조하고 있는 애들이 있음.

옮길 때 나를 참조하고있는 애들한테 나 옮긴다~하고 다 알려줘야함 (Pointer Relocation)

근데 메모리에선 그 포인터로 가기 어려움.

따라서, 얘네가 어디를 참조하고있는지관리할수있는 상황에서 쓰거나,

스마트포인터 이용해야 함. 또는 핸들 이용~

 

-스마트 포인터를 클래스 형태로 사용.

모든 스마트포인터들을 글로벌 링크드리스트에 박아놓고, 뭐가 바뀌면 그 바뀐애를 가리키는 애들을찾기위해

링크드리스트를 순회해서 찾음

 

-핸들을 이용한 relocation

핸들이라는 거는 뭔가를 가리키는거.

핸들이 나를 가리키게하고,

나를 가리키는 애들은 내가 아닌 핸들을 참조하도록 설정.

똑같은건데, 핸들은 인덱스로 관리하는거고 링크드 스마트포인터리스트는 링크드리스트로 관리하는거임

핸들을 정리하는 과정에, 프로그램 스테이트는 멈추거나 할필요 없음. 핸들이랑 분리되어 작동하기 때문

 

'게임 > 게임 엔진 기초' 카테고리의 다른 글

7. Game Engine Support System (3)  (0) 2023.01.03
5. Game Engine Support System (1)  (1) 2022.12.08
4. Object-oriented programming (2)  (0) 2022.12.07
3. Object-oriented programming (1)  (0) 2022.12.07
2. Game Engine Architecture (2)  (1) 2022.12.07
Comments