1. Address Binding?
하나의 프로그램이 실행되기 위해서는 프로그램 코드가 어셈블리어로 컴파일되고, 어셈블리어가 기계어로 변환되어 프로세스가 만들어져 메인 메모리에 적재되면 해당 프로세스의 명령어들은 Physical address를 가지게 된다. CPU가 메인 메모리에 적재된 프로세스 명령어를 실행하기 위해서는 Logical address를 알아야 하기 때문에 Physical address에 매핑된 Logical address를 알아내서 프로세스를 처리한다. 이때 Logical address와 Physical address를 매핑하는 과정이 바로 Address Binding이다.
Symbolic address VSLogical address VS Physical address
Symbolic address
변수나 함수와 같이 코드에서 사용하는 변수명을 주소로 사용하는 방법
C언어에서 int a = 1이라는 코드에서 a는 0x100번지의 4byte만큼의 메모리 주소의 별명이 a라는 뜻이며, a라는 별명을 통해 0x100번지에 1이라는 값을 넣는것이다.
즉 프로그래머가 사용하는 프로그래밍 언어에서 사용하는 방법이다.
Logical address
- 코드에 존재하는 데이터를 가리키는 등 프로세스 내부에서 사용되는 주소이다
- CPU가 명령어를 실행할 때 Logical address를 참조해서 실행한다.
- 각 프로세스마다 0번지부터 시작한다.
Physical address
- 실제 메모리에 올라가는 주소
이제 주소에 대해 알았으니 아래의 그림을 통해 Address Binding을 하는 시점에 대해 자세히 살펴보자
1. Compile time binding
컴파일 시점에 물리적 주소를 결정하는 방법이다.
이름에서 알 수 있듯이 컴파일 시점에 메모리 주소가 결정되어 있어야 하기 때문에 다른 주소가 비어있어도 무조건 프로그램 내부에서 사용하는 주소와 물리적 주소가 동일하게 올라간다.
단점
1. 물리적 메모리의 위치를 변경하려면 컴파일을 다시 해야함.
2. 비어있는 메모리를 사용하지 않고 정해진 메모리 주소를 사용하기 때문에 비효율적
그래서 요즘 운영체제는 사용하지 않는다
2. Load time binding
컴파일된 파일이 실행되면서 메모리의 주소가 결정되는 방법이다.
실행 시점에 비어있는 주소가 있으면 메모리를 할당할 수 있다.(= Relocatable code)
실행 시점에 메모리를 유동적으로 바인딩 할 수 있지만 실행 도중에 메모리가 변경되지는 않는다.
3. Run time binding
Load time binding과 동일한 방법으로 프로그램이 실행되면서 메모리의 주소가 결정되는 방법이다. 한가지 차이점은 프로그램 실행 중에 메모리의 주소가 변경될 수 있다.
CPU가 메모리의 주소를 참조할 때마다 binding을 확인하기 때문에 하드웨어의 도움을 받는다(Memory Management Unit)
MMU가 Address binding을 하는 방법
위의 그림을 보면 프로세스는 실제 메모리에서 0x14000번지부터 할당을 받아 사용하고 있다(Base register). MMU가 Address binding을 할 때는 Base register + Logical address를 계산해서 실제 메모리에 물리적인 주소로 적재한다.
그래서 CPU가 논리적 주소 0x346번지의 명령어를 달라고 요청하면 MMU는 물리적 시작 주소를 변환해서 시작주소로 부터 CPU가 요청한 346만큼 떨어진 메모리에 저장되어 있는 명령어를 가져다준다.
Dynamic Loading
먼저 Loading이란 실행할 리소스를 메모리에 옮기는 것을 의미한다. 그럼 Dynamic Loading이란 동적으로, 프로세스 생성시 전체를 메모리에 다 올리는것이 아닌, 실행할 리소스를 필요로 할 때 메모리로 옮기는것을 의미한다. 프로그램 자체에서 구현이 가능 라이브러리 지원이 가능하기 때문에 개발자가 어렵게 코딩하지 않아도 사용할 수 있다.
프로세스가 실행되려면 메모리에 올라와야 하기 때문에 처음 프로세스 생성시 바로 전부 올리는 것이 아닌, 프로세스중에 CPU가 진짜 일을 처리할 때 메모리에 올라가기 때문에 메모리를 절약하며 사용할 수 있다.
Static Linking & Dynamic Linking
static Linking
실행파일 안에 모든 내용을 다 때려박는 것을 말한다. 그래서 별도의 라이브러리가 필요 없고 실행시 속도가 빠르다. 하지만 코드 자체가 실행파일 안에 들어있기 때문에 메모리에 같이 올라가야 해서 메모리 낭비가 심하다.
c++로 생각해보면 printf 함수를 포함한 프로세스가 static linking으로 들어가있으면 printf 를 구현한 코드가 다 메모리에 올라가 있다는 말이고 여러개의 프로세스를 실행시키면 printf코드가 메모리에 n번 올라가기 때문에 끔찍해져 버린다.
Dynamic Linking
Static Linking과 반대개념으로, 라이브러리가 프로세스 실행시에 연결되는 방법이다. 여기서 printf 같은 라이브러리를 어떻게 찾냐면 라이브러리가 있는 주소를 찾기 위해 stub이라는 포인터를 통해 찾는다. Static Linking에서 든 예시를 다시 보면 여기서는Dynamic Linking에서는 프로세스에서 printf를 실행하게 되면 stub를 통해 printf가 있는 주소를 가져와서 print를 실행하기 때문에 n번 실행할더라도 내 프로세스 메모리 상에는 printf에 대한 코드가 없기 때문에 메모리가 n번씩 호출될 상황이 발생하지 않는다.
C계열로 코딩하면 dll파일이 나오던데 이제 dll이 뭔지 알았다ㅋㅋㅋㅋ dll은 Dynamic Linking Library이며 주로 많이 사용하는 printf, scanf같은 함수, 타입 등을 구현해놓고 재사용하는것이다. 그래서 stub은 이 dll에 있는 함수를 포인팅 해서 사용하기 때문에 최종적으로 dll은 프로세스마다 올라가는게 아닌 dll파일 하나만 한번 올라간다. 다른 똑같은 dll파일을 사용하는 프로세스 또한 동일한 dll파일을 사용한다. dll을 사용하는 프로세스 갯수를 count해서 총 0이되면 dll을 메모리에서 삭제하는 방식이 있지만 이번 포스팅과는 살짝 다르기 때문에 여기서 뿅
Overlays
메모리에 프로세스의 부분 중 실제 필요한 부분을 올리는 것을 의미한다. 이렇게 보면 Dynamic Loading과 똑같다. 하지만 다른점은 라이브러리, OS의 지원이 없다는 것이다. 프로세스의 크기가 메모리보다 클 경우 전부 다 못올리기 때문에 개발자가 원하는 부분, 실행 해야 할 부분을 직접 설정해서 코딩해줘야 하기 때문에 복잡하다.
Swapping
메모리에 올라가있는 프로세스를 일시적으로 하드디스크로 쫓아내는 것을 말한다. 스와핑에는 두가지가 있는데
1. Swap out : 메모리를 하드디스크로 쫓아내는 것.
2. Swap in : 하드디스크로 쫓겨났던 프로세스를 다시 메모리로 올리는 것.
이렇게 두가지가 있으며, Swap out, in을 하려면 앞에서 살펴봤던 Runtime binding이 적합하다. 하지만 Compile time과 load time binding을 사용한다면 원래 메모리위치로 다시 돌아간다.
CS 지식을 공부하고 기록하는 개인 공부 블로그입니다.
내용 중 틀린 부분 피드백 혹은 궁금한 점이 있으면 댓글로 남겨주시면 참고 및 답변 달아드리겠습니다🧐
'Computer Science > 운영체제' 카테고리의 다른 글
[OS/운영체제] Paging (0) | 2024.02.09 |
---|---|
[OS/운영체제] 메모리 할당 (1) | 2024.02.07 |
[OS/운영체제] Deadlock / 교착상태 (0) | 2024.01.27 |
[OS/운영체제] Atomic execution과 Semaphores / Mutex (1) | 2024.01.16 |
[OS/운영체제] 동기화 문제와 임계영역 문제 (0) | 2024.01.09 |