프로시저, 서브루틴, 함수
- 함수를 호출, 실행하고 다시 원래 자리로 돌아오기 위해서는 어디서 함수를 호출하였는지를 기억해야 하는데, 이는 바로 프로그램 카운터의 값이다.
- 반환 주소를 저장하고, 이를 간접 호출하여 분기해서 돌아오는 과정은 많은 작업이 필요하므로 대부분의 기계는 이를 구현한 명령어를 제공한다.
스택
- 반환 위치 저장할 메모리 주소가 하나뿐이라면 반환 위치가 덮어씌워지기 때문에 재귀 함수를 사용할 수 없다.
- 따라서, 함수를 호출할 때에는 반환 위치를 LIFO로 가져오기 위해 스택을 사용하며, 스택의 크기를 초과하는 것을 스택 오버플로, 빈 스택에서 데이터를 가져오려고 하는 경우를 스택 언더플로라 한다.
- 함수가 호출될 때마다 반환 주소 이외에도 각각의 독립된 로컬 변수를 사용하기 때문에, 로컬 변수 역시 스택에 저장하면 각각의 함수 호출을 독립적으로 구성할 수 있다. 이렇게 매 함수 호출 시 스택에 저장되는 데이터의 모음을 스택 프레임이라 한다.
인터럽트
- 폴링(Polling)은 자원을 많이 소비할 수 있으므로, 인터럽트 시스템이 필요하다.
- 인터럽트 요청이 발생하면, 처리중인 명령어까지는 마무리한 후 프로그램을 중단하고 인터럽트 핸들러라는 프로그램(함수)을 실행하고, 다시 원래 프로그램이 중단된 위치부터 실행을 계속한다.
- 이를 위해 인터럽트에 대응하고 실행 중이던 프로그램으로 돌아가기까지 걸리는 시간을 제한해야 하며, 스택에 인터럽트 발생 이전의 상태를 저장하였다가 복구해줘야 한다.
- 인터럽트 벡터: 컴퓨터는 각 인터럽트에 대응하는 인터럽트 핸들러 주소를 지정하는 포인터를 가지고 있는데, 이를 인터럽트 벡터라 한다.
상대 주소 지정
- 여러 프로그램을 동시에 사용할 때, 타이머를 통해 각 프로그램이 실행되는 시간을 제한하여 스위칭하는 스케줄링 방식을 시분할이라 한다.
- 이를 위해 각 프로그램에 다른 공간을 허용하는데, 이 때 한 프로그램이 다른 프로그램이 사용하는 메모리에 접근하면 여러 가지 문제가 발생할 수 있다.
- 이를 방지하기 위해 메모리 주소를 절대적으로 지정하는 것은 바람직하지 않으며, 상대 주소 지정을 통해 프로그램이 접근할 수 있는 메모리 주소를 재배치한다.
메모리 관리 장치
- 한 프로그램이 의도치 않게, 또는 의도적으로 허용되지 않은 메모리에 접근하는 것은 바람직하지 않으므로 이를 위해 메모리 관리 장치(Memory Management Unit)이 사용된다.
- 프로그램은 가상 주소를 사용하여 작성되고, MMU는 이를 물리적 주소로 변환하는 역할을 한다.
- MMU는 페이징 기법을 활용하여 실제 가능한 물리주소 범위보다 넓은 범위의 가상 주소를 사용할 수 있게 해준다.
가상 메모리
- MMU의 페이징 기법으로 확장된 메모리 가용 영역보다 더 큰 영역이 필요할 경우, OS는 현재 필요하지 않은 페이지를 느리지만 용량이 큰 디스크로 옮겨버리고(swap out), 추후 다시 접근이 필요할 때 다시 메모리에 불러들인다(swap in).
- 이는 성능을 크게 저하시키지만, 메모리가 부족해서 실행할 수 없는 프로그램을 실행할 수 있게 해준다.
메모리 계층과 성능
- CPU에 비해 메모리가 느리기 때문에, 메모리 계층이라는 개념을 적용, CPU에 캐시라는 하드웨어를 추가하여 CPU가 필요로 할 가능성이 높은 데이터를 미리 읽어옴으로써 성능 향상을 기대할 수 있다.
메모리상의 데이터 배치
- 실행 전에는 크기를 알 수 없는 데이터, 즉 동적 데이터를 다루기 위해 힙(heap)이라는 영역을 사용한다.
프로그램 실행
- 링커는 재사용 등을 위해 조각난 프로그램을 하나로 연결하여 실행 가능한 프로그램을 만들어주는 프로그램이다.
- 라이브러리를 프로그램에 직접 가져다 붙이는 방식을 정적 링크라 하고, 공유 라이브러리를 사용하여 여러 프로그램이 같은 라이브러리를 사용할 수 있도록 하는 방식을 동적 링크라 한다.
- 공유 라이브러리의 명령어는 해당 라이브러리를 사용하는 모든 프로그램에서 공통이므로, 라이브러리 함수를 작성할 때는 호출하는 프로그램의 스택과 힙을 사용하도록 함수를 설계한다.
- 프로그램이 합쳐져 실행파일이 되면, 런타임 라이브러리가 추가되어 프로그램 실행시 가장 먼저 실행되고 이후 진입점의 명령어가 수행되면서 프로그램이 실행된다.
- 런타임 라이브러리는 프로그램이 사용할 메모리 설정을 수행하면서 스택과 힙 영역을 설정하고 데이터의 초깃값도 설정하는 역할을 한다.