메모리와 관련한 구조 개선을 다룸

- 가장 흔한 두 가지 컴퓨터 구조
- 함수 = 프로시져(procedure) = 서브루틴(subroutine)
스택
- 함수가 자기 자신을 호출하거나 다른 함수를 호출해야할 경우가 많고 그 함수를 실행하고 나서 다시 함수를 부른 곳의 위치로 돌아와야함 ⇒ 이때 필요한 것이 스택
- 스택에 저장되는 것(함수가 호출될 때마다 스택에 저장되는 데이터의 모음을 스택 프레임 이라고 함)
- 반환 주소
- 지역 변수
인터럽트


- 폴링 : 작업 도중에 계속해서 한번씩 확인하는 방법
- 단점은 문 앞에 누가 왔는지 검사하는데 너무 많은 시간을 소모함
- 위와 같은 상황에서 프로그램의 구조를 잘 재배치해서 작업을 더 잘 처리하는 것은 불가능하고 실행중인 프로그램을 interrupt 시켜서 외부 요소에 대응할 수 있게 만드는 하드웨어 기능이 필요함
- 운영체제는 다른 일반 프로그램들은 접근할 수 없는 물리적(하드웨어) 인터럽트에 접근할 수 있는 경우가 있음
- 운영체제는 일종의 가상 인터럽트나 소프트웨어 인터럽트 시스템을 제공하기도 함
- 최근 개발된 시스템들은 보통 이를 이벤트 라고 부름
운영체제
- 여러 프로그램을 동시에 실행하려면 각 프로그램사이에 서로 전환시켜 줄 수 있는(스케줄링) 일종의 관리자 프로그램이 필요한데 이를 운영체제 or 운영체제 커널이라고 함
- 사용자 프로그램 상태(state) 또는 문맥(context) : 레지스터의 상태와 프로그램이 사용 중인 메모리(스택도 포함)의 상태
- 여러 사용자 프로그램을 메모리에 하나씩 올릴 때 문제가 되는 부분 : 1000번지에서 실행되도록 만들어진 프로그램을 2000번지에서 읽어 들이면 제대로 실행되지 않음 → MMU(Memory Management Unit)

메모리 관리 장치

- MMU는 가상 메모리 주소를 두부분으로 나누어, LSB(주소 하위) 부분은 물리적 주소 범위와 같고 상위(MSB) 부분은 페이지 테이블 이라는 RAM 영역을 통해 주소를 변환함
- 페이지 테이블에는 각 페이지가 물리 메모리상에서 차지하는 실제 위치정보가 들어있음 → 페이지 테이블 또한 context의 일부가 됨
- 프로그램이 물리적 메모리에 연관되지 않은 주소에 접근하면 페이지 폴트 예외가 발생함
- MMU로 인해 폰노이만 구조와 하버드 구조의 차이가 없어짐
가상 메모리
- MMU가 프로그램의 가상 주소를 물리 메모리 주소로 변환해주고, 페이지 폴트 메커니즘으로 인해 프로그램은 필요한 만큼 많은 메모리가 있다고 생각할수 있게 됨(실제 물리 메모리주소보다)
demand paging
- 요청 받은 메모리가 사용가능한 메모리의 크기보다 크면, OS는 현재 필요하지 않은 메모리 페이지를 디스크로 옮김 - swap out
- swap in - 스왑 아웃한 페이지에 프로그램이 접근하면 필요한 메모리 공간을 확보하고 요청받은 페이지를 다시 메모리로 불러들임
- swapping이 일어나면 시스템 성능이 크게 저하됨. 그러나 아예 프로그램 실행 못하는 것보다는 낫기에 이렇게 실행을 함
시스템 공간과 사용자 공간
- 사용자 프로그램이 MMU의 설정을 바꾼다거나 운영체제가 인터럽트 하려는데 그것을 변경할 수 있고 하면 예상과 다르게 작동하게 됨
- CPU에 컴퓨터가 시스템 모드에 있는지 사용자 모드에 있는지 결정하는 비트가 어떤 레지스터 안에 들어있음. I/O를 처리하는 명령어 등 일부 명령어는 특권 명령어라 오직 시스템 모드에서만 실행가능
- trap 혹은 system call 이라는 특별한 명령어를 통해 사용자 모드에서 실행 중인 프로그램이 시스템 모드 프로그램에게 요청을 보낼 수 있음
메모리 계층과 성능
- CPU가 더더욱 빨라지지만 메모리는 그렇게 까지 빨라지지 못해 CPU보다 속도가 뒤쳐짐. 빠른 CPU가 느린 메모리를 기다리느라 아무 일도 하지 않는 경우를 줄이기 위해 방법을 씀

- 캐시 : 메모리에서 연속된 열에 있는 데이터를 한꺼번에 가져와서 캐시에 저장함(대부붕느 ㅇ녀속된 위치에 있는 데이터가 필요하기 때문)
- 캐시 적중(cache hit) : CPU가 원하는 내용을 캐시에서 찾은 경우
- 캐시 실패(cache miss) : CPU가 원하는 내용을 캐시에서 찾은 경우
메모리상의 데이터 배치
- 프로그램 실행 시 메모리에 명령어만 담는 게 아니라 데이터도 담아야 함.
- 스택
- 정적 데이터(프로그램 작성 시 얼마나 많은 메모리가 필요한지 이미 알고 있음)
- 동적 데이터 - 프로그램 실행 전에는 크기를 알 수 없는 데이터 ⇒ 힙
프로그램 실행
- 프로그램을 여러 조각으로 나누면 이 모든 조각을 하나로 엮거나 연결(link)할 방법이 필요함 → 링커라는 특별한 프로그램을 사용해 여러 조각을 하나로 연결해 실행함
- 링커 : ‘팝니다’ 섹션에는 ‘나는 cube라는 함수를 제공합니다’ 라는 광고가 있고, ‘삽니다’ 섹션에는 ‘나는 date라는 변수를 찾습니다’라는 광고가 있는데 이런 모든 광고를 resolve해서 실제로 실행할 수 있는 프로그램을 만들어내는 프로그램
- 정적 링크 : 라이브러리를 단지 필요한 함수가 들어 있는 파일로 간주해서 프로그램의 나머지 부분과 직접연결해 실행 파일을 만듦 → 정적 링크를 사용하면 같은 라이브러리 코드가 여러 실행 파일에 반복적으로 들어가서 메모리 낭비를 하게됨
- 동적 링크 : 공유 라이브러리를 사용해 MMU 가 여러 프로그램이 같은 라이브러리를 공유할 수 있게 해줌
- 진입점 : 프로그램의 첫번째 명령어가 위치한 주소
- 런타임 라이브러리 : 프로그램을 이루는 모든 부분이 하나로 합쳐져서 실행파일을 이룰 때 추가됨. 런타임 라이브러리에 있는 명령어가 먼저 실행되고 나중에 진입점의 명령어가 실행됨
- 스택과 힙 영역을 설정
- 정적 데이터에 위치한 데이터의 초깃값도 설정함 : 이런 값들은 실행 파일에 들어 있고 시스템에서 메모리를 할당 받은 직후 실행 파일에서 메모리로 복사돼야 함