https://github.com/BOOOO0/linux-operating-system
GitHub - BOOOO0/linux-operating-system: 리눅스 명령어, 이론과 운영체제 실습
리눅스 명령어, 이론과 운영체제 실습. Contribute to BOOOO0/linux-operating-system development by creating an account on GitHub.
github.com
깃허브에 더 많은 내용이 있습니다.
가상 메모리 (Virtual Memory)
한 프로세스를 실행시키려할 때 메모리에 프로그램 전체를 적재시키지 않아도, 혹은 실제 물리 메모리보다 프로그램의 크기가 더 커도 실행할 수 있게 해주는 기술이다.
주 메모리 자체를 굉장히 큰 가상의 저장공간이라고 생각하면 논리 메모리와 물리 메모리를 분리시킬 수 있다.
필요한 부분은 필요할 때 물리적 주소에 적재시키고 적재되지 않은 나머지 페이지들은 Backing Store에 저장한다.
가상 주소 공간 (Virtual Address Space)
프로세스가 어떻게 저장되었는지에 대한 논리적인 모습이다.
보통 0번지부터 시작하여 연속적인 공간을 차지한다.
가상메모리를 사용하면 페이지 공유를 통해 파일과 메모리의 공유가 쉬워진다.
어떻게 실행 프로그램을 디스크에서 메모리로 적재할 수 있을지 방법에 대해 생각해보면
첫째로 물리적 주소에 프로그램 전체를 로딩하는 방법이 있다. 그러나 그것은 효율적이지 못하기 때문에 페이징 기법을 사용해서 메모리에 적재시키는 방향을 추구하게 되었다.
그렇다면 페이지를 로드하는 시점은 언제인가?
그것에 대한 해답이 바로 가상메모리를 사용해 필요할 때만 로드하는 요구 페이징(Demand Paging)이다.
요구 페이징 (Demand Paging)
프로세스가 실행중일때 페이지들이 메모리에 로드되어 있을수도 있고 저장장치에 있을수도 있다.
두가지 상태를 구분하기 위해서는 유/무효 비트(valid-invalid bit)기법이 사용될 수 있다.
- 유효 : 해당 페이지가 메모리에 있다.
- 무효 : 해당 페이지가 유효하지 않거나(가상 주소 공간상에 정의되지 않았거나) 현재 저장장치에 있다.
위에서 만약 새로운 페이지를 로드하려고 한다면 backing store에서 물리 메모리로 스왑 인 시켜야한다.
페이지 부재 (Page Fault) 의 처리
- 프로세스에 대한 내부 테이블(internal table)을 검사해서 그 메모리 참조가 유효/무효인지를 알아낸다.
- 만약 가상 메모리 상 정의되지 않은 페이지에 대한 참조라면 그대로 프로세스는 중단된다. 정의되어 있지만 아직 로드되지 않았다면 저장장치에서 가져와야 한다.
- 아직 할당되지 않은 빈 공간, 자유 프레임(free frame)을 찾는다.
- 디스크에 새로 할당된 프레임으로 페이지 부재가 일어났던 해당 페이지를 읽어들이도록 요청한다.
- 읽기가 끝나면 내부 테이블을 수정해서 페이지가 메모리에 있음을 알린다.
- 중단되었던 명령을 다시 수행한다.
- M을 참조하기 위해 페이지 테이블에 접근했으나 페이지 부재
- 운영체제에 trap을 걸음
- backing store에 해당 페이지가 저장되어 있는지 확인
- 자유 프레임에 로드
- 페이지 테이블 갱신
- 명령 재개
순수 요구 페이징 (Pure Demand Paging)
어떤 페이지가 필요해지기 전에는 절대 메모리에 페이지를 로드하지 않는 것이다.
극단적인 경우 메모리에 로드된 페이지가 없어도 실행은 가능하다.
그럴 경우 실행된 후에 운영체제에서 명령 포인터 값을 설정했을 때 이 명령이 로드되지 않은 페에지에 있으므로 페이지 부재가 발생하고 필요한 페이지를 로드시킨다. 그리고 다른 페이지가 필요할때 마다 페이지 부재가 발생하고 또 그 후에 페이지를 로드시키는 방식이다.
참조의 지역성 (Locality of Reference)
프로그램들은 한 명령어에서도 여러 개의 페이지 부재를 일으킬 수 있다. (명령문을 읽기 위해서 한 페이지, 그리고 데이터마다 한 페이지 씩).
이렇게 되면 시스템 성능의 저하를 초래한다.
하지만 다행히도 실행 중인 프로세스들을 분석해 보면 이러한 경우는 거의 발생하지 않는다는 것을 알 수 있다. 모든 프로그램은 참조의 지역성 이라는 성질이 있어서 프로그램의 어느 한 특정 작은 부분만 한동안 집중적으로 참조하는데 이러한 성질 때문에 요구페이징은 만족할 만한 성능을 보인다.
페이지 하나의 크기가 128이라고 가정한 다음에 두 코드를 비교해보면
좌측의 코드는 반복문이 1회 반복하는 동안 128개 페이지의 j번째를 계속해서 참조해야 하기 때문에 페이지 부재가 연속으로 계속해서 일어난다.
우측의 코드는 반복문이 1회 반복하는 동안 한 페이지만 참조하기 때문에 페이지 부재는 처음 한번만 발생하는 차이가 있다.
하드웨어 지원
- 페이지 테이블 : 보호비트(Legal or Ilegal) 또는 유효/무효 비트(페이지 부재 여부)를 통해서 페이지 관리를 돕는다.
- 보조 기억 장치(=스왑공간) : 주 메모리에 없는 모든 페이지들을 가지고 있다. 주로 고성능 디스크이다.
명령 재시작 (Instruction Restart)
요구 페이징을 위한 필수적인 요구 사항은 페이지 부재 오류 처리 후에 명령어 처리를 다시 시작할 수 있어야 한다는 것이다.
위는 페이지 부재로 인한 명령 재시작 예시 중 worst case이다.
1에서 페이지 부재가 일어나도 그리고 2에서, 3에서 페이지 부재가 일어나도 전부다 1부터 명령을 재시작 해야한다.
자유 프레임 리스트 (Free Frame List)
운영체제는 자유 프레임들을 연결 리스트로 관리한다.
페이지 부재가 일어났을 때 운영체제는 자유 프레임 리스트를 유지하면서 요청을 이행할 수 있어야 한다.
요구 페이징의 성능 (Performance of Demand Paging)
실질 접근 시간 (Effective Access Time)
메모리 접근 시간을 'ma', 페이지 부재 확률을 'p'라고 하면
EAT = (1-p) * ma + p * (page fault time) 이다.
페이지 부재를 처리하는데 드는 시간엔 3가지의 주요 작업이 영향을 주는데
- 페이지 부재 인터럽트 처리
- 페이지 읽기
- 프로세스 재시작
이다.
그 중에서도 페이지를 읽는 시간이 가장 오래걸리기 때문에 영향을 많이 준다.
평균적인 페이징 시간을 8ms라고 하고
메모리 접근 시간을 200ns라고 한다면
EAT = (1-p) * 200 + p * 80000000
= 200 + 7999800*p
1000번에 1번 페이지 부재가 발생한다면
EAT = 200 + 799.8 = 8199.8ns
= 8.2microseconds
위와 같은 방식으로 실질 접근 시간을 계산할 수 있다.
쓰기 시 복사 (Copy on Write)
프로세스가 공유 페이지를 write할 때만 복사한다.
좌측은 페이지 수정 전, 우측은 페이지 수정 후이다.
좌측에서 P1을 fork() 한다면 물리적 메모리를 새로 만들지 않고 새 프로세스는 똑같은 물리 메모리 영역을 참조한다.
우측에서 만약 한 변수에 값을 새로 할당해줘서 값이 바뀐다거나 하는 write를 하는 상황이 생긴다면 그 부분의 페이지를 그때 복사해서 다른 물리 메모리 영역을 참조하는 것이다.
'Operating System' 카테고리의 다른 글
Operating System : Concepts - 가상 메모리 (Virtual Memory) (3) (0) | 2022.10.11 |
---|---|
Operating System : Concepts - 가상 메모리 (Virtual Memory) (2) (0) | 2022.10.06 |
Operating System : Concepts - 주 메모리(Main Memory) (4) (0) | 2022.07.19 |
Operating System : Concepts - 주 메모리(Main Memory) (3) (0) | 2022.07.19 |
Operating System : Concepts - 주 메모리(Main Memory) (2) (0) | 2022.07.18 |