[시스템프로그래밍] - 메모리(Memory 1) 1

2019. 11. 26. 16:41Computer Science/SystemProgramming

컴퓨터에서 메모리Memory란 Cpu(처리기)가 적재된 프로세스를 실행하기위해 놓이는 하나의 버킷 리스트 개념이다..

(대략적으로 출퇴근하는 회사에서 편하게 쓰려고 사물함을 두어 업무에 필요한 물건들을 거기다 두고 쓰는 개념과 비슷하다.)

흔히 배그컴등을 맞출때 쓰이는 하드웨어 이름으로는 RAM이라고 불린다.

어쨌든 메모리란, 처리기에서 프로세스 실행을 위해 적재해두는 공간으로 보는데, 프로세스를 다음과 같은 형태로 메모리에 적재한다.

 

 

프로세스를 실행함에 있어서 필요한 소스코드 변수 등등이 기술되어있음

그러나 메모리의 용량은 디스크만큼 크지않고 한정되어있기 때문에, 최대한 효율적이고 실용적으로 사용해야한다. 그러나 대부분의 프로그램들이 그렇듯이 실행하면서 용량이 커지는 경우가 있을 수 있기 때문에, 프로그램을 실행하기전까지 그 프로그램의 용량에 대해서는 '모른다'라고 정의 하는 것이 맞다. 그러면 이러한 문제를 어떻게 해결해야 겠는가?

바로 동적 메모리 할당이라는 기법을 사용하는데 그냥 필요할때마다 그만큼 가져와서 쓴다는 말이다. 상식적으로 모른다고 메모리를 전부다 끌고와서 쓰는것은 비효율적인것이고 때로는 프로그램크기가 메모리의 맥스사이즈를 초과하는 경우도 있을 수 있다. ( 이부분은 가상메모리에서 어떻게 처리하는지 다룸) 가장 이상적인 것은 정적으로 필요한 메모리를 정의하면 가장 좋지만, 현실은 그럴수 없기때문에 가장 직관적인 방법으로 해결한 것이다.

 

동적 메모리 할당방법

  • 간접: 응용프로그램이 할당하지만 반환은 직접적으로 하지않는다.(Ex. java 가비지컬렉션이 알아서 메모리를 회수함)
  • 직접: 응용프로그램이 할당하지만 반환도 명시적으로 직접 해줘야된다.

C에서는 직접형식 할당을 사용하고 있다.

Malloc 패키지 * malloc(int num) : num의 크기만큼 바이트를 메모리에 할당함.

 

Malloc 사용 예시

p에 int의 크기(4바이트) *n의 갯수만큼 의 바이트를 할당받고,for loop를 돌면서 각 iteration에 해당하는 i값에 을 할당한 p에 저장한다.  **realloc은 미리 할당된 메모리에 대해서 재할당을 하는것이다.

 

할당된 메모리 p에 대해서 realloc으로 (n+m)*4바이트만큼 재할당을 한다. (기존의 n만큼 할당되어있는데 m만큼늘리는 경우: 기존데이터는 유지하고 할당량만 extends하는 방식으로 늘린다.)

마찬가지로 iteration을 돌면서, 할당한다.

 

 

내부단편화와 외부 단편화

운영체제에서 프로세스를 실행하는데, 있어서 처리량(성능:throught)은 중요한 요소로 작용하는데, 이는 밀려있는 프로세스들을 최대한 빠르고 효율적으로 처리하는 것이다. 그러나 cpu가 프로세스들을 처리하는데 있어서 발생하는 어쩔수 없는 이슈가 있는데 이는, 외부단편화와 내부단편화라는 것이다.

외부단편화 예시 

  • 외부단편화(external fragment): 새 프로세스를 적재해야하는데,  남은 메모리 양의 합은 실행하려는 프로세스보다 커서 논리적으로는 할당이 가능하나. 기존 프로세스들의 배치에 의해 메모리안으로 들어갈수 없는 상황
  • 내부단편화(internal fragment): 기존에 실행중인 프로세스와 프로세스 사이에 24바이트(6칸)이 있다고 가정했을때, 3칸 짜리의 새 프로세스가 추가될 때, 6칸사이에 들어가게 되는데 그러면 3칸(12바이트)의 낭비가 발생하게 된다.

이러한 이슈가 발생할 수 밖에 없는 이유는 CPU는 미래에 실행될 프로세스들 대한 정보를 예측하는 것이 불가능 하기 때문이다.

 

그래서 오랜 연구 끝에 성능을 향상시킬만한 여러가지  방법들이 나왔는데, 그중 대표적인 것이 간접리스트 방식이다.

메모리에 적재된 프로세스의 끝에 1워드(4바이트)씩 추가로 두어 해당 프로세스의 용량을 저장하는 방식이다 그러면 4칸(16바이트)의 용량을 가지는 프로세스가 메모리에 적재되면 해당 프로세스의 정보를 담은 헤더를 포함해서 5바이트를 두는 것이다. 

이런 헤더들의 정보를 이용하면, 비어있는 메모리의 부분을 알수있는 데, 쓰지 않는 메모리의 첫 부분들에 링크드 리스트같이 논리적으로 연결이 가능하다.

이렇게 빈 메모리의 위치 정보를 알고 있는 상태이고, 새로운 프로세스가 적재되었을 때, 보다 빠르게 처리할 수 있다.

메모리의 크기가 64기가라고 가정하면 어디가 비었는지 일일이 체크해야되서 오버헤드가 드는데 이것은 정적으로 어디가 비었는데 확실히 알기 때문에 적재하는 시간을 상당히 줄일 수 있는 이점인 것이다.

헤더 워드는 메모리가 차있는지 안차있는지, 차있으면 1 안차있으면 0을 주고 블록크기 등에 대한 정보가 담겨있다.