chapter 14. 가상 메모리

  1. 연속 메모리 할당

    : 프로세스에 연속적인 메모리 공간을 할당하는 방식을 말한다.

    메모리에 적재된 프로세스들 중에는 현재 실행되지 않은 프로세스가 있을 수 있음. 입출력 작업의 요구로 대기 상태가 된 프로세스, 오랫동안 사용되지 않은 프로세스가 이런 프로세스에 속함. 이런 프로세스들을 임시로 보조기억장치 일부 영역으로 쫓아내고, 쫓아내고 생긴 메모리상의 빈 공간에 또 다른 프로세스를 적재해 실행하는 방식을 **스와핑(swapping)**이라 함.

    스와핑(swapping) : 메모리에서 사용되지 않는 일부 프로세스를 보조기억장치로 내보내고 실행할 프로세스를 메모리로 들여보내는 메모리 관리 기법.

    스왑 영역(swap space) : 프로세스들이 쫓겨나는 보조기억장치의 일부 영역

    스왑 아웃(swap - out) : 현재 실행되지 않는 프로세스가 메모리에서 스왑 영역으로 옮겨지는 것

    스왑 인(swap - in) : 반대로 스왑 영역에 있던 프로세스가 다시 메모리에 옮겨 오는 것

    스왑 아웃되었던 프로세스가 다시 스왑 인될 땐 스왑 아웃되기 전의 물리 주소와는 다른 주소에 적재될 수 ㅇ.

    스와핑을 사용하면 프로세스들이 요구하는 메모리 주소 공간의 크기가 실제 메모리 크기보다 큰 경우에도 프로세스들을 동시 실행할 수 ㅇ.

    비어 있는 메모리 공간에 프로세스를 연속적으로 할당하는 방식 대표적인 3가지

    : 최초 적합, 최적 적합, 최악 적합

    연속 메모리 할당은 메모리를 효율적으로 사용하는 방법이 아님. 외부 단편화 문제를 내포하고 있기 때문.

    외부 단편화(external fragmentation) : 프로세스들이 연속적으로 할당되는 환경에서 프로세스들이 실행되고 종료되기 반복하며 메모리 사이 사이에 빈 공간들이 생기는데, 프로세스를 할당하기 어려운 만큼 작은 메모리 공간들로 인해 메모리가 낭비되는 현상을 말함.

    외부 단편화를 해결할 수 있는 대표적인 방안으로 메모리를 압축하는 방법이 있다.

    압축(compaction) : 여기저기 흩어져 있는 빈 공간들을 하나로 모으는 방식으로, 메모리 내에 저장된 프로세스를 적당히 재비치시켜 여기저기 흩어진 작은 빈 공간들을 하나의 큰 빈 공간으로 만드는 방법이며, 메모리 조각 모음이라고도 부른다.

    압축 방식의 단점 : 적운 빈 공간들을 하나로 모으는 동안 시스템은 하던 일을 중지해야 하고, 메모리에 있는 내용을 옮기는 작업은 많은 오버헤드를 야기하며, 어떤 프로세스를 어떻게 움직여야 오버헤드를 최소화하며 압축할 수 있는지에 대한 명확한 벙법을 결정하기 어려움.

    외부 단편화를 없앨 수 있는 또 다른 해결 방법 페이징 기법

  2. 페이징을 통한 가상 메모리 관리

    프로세스를 메모리에 연속 할당하는 방식의 문제 중 또 하나는 물리 메모리보다 큰 프로세스를 실행할 수 없다는 점.

    연속 메모리 할당 방식에서 외부 단편화가 생기는 근본적인 원인은 각기 다른 크기의 프로세스가 메모리에 연속적으로 할당되었기 때문.

    가상 메모리(virtual memory) : 실행하고자 하는 프로그램을 일부만 메모리에 적재해 실제 물리 메모리 크기보다 더 큰 프로세스를 실행할 수 있게 하는 기술로, 가상 메모리 기법에는 페이징과 세그멘테이션이 있다.

    페이징(paging) : 메모리의 물리 주소 공간을 프레임(frame) 단위로 자르고, 프로세스의 논리 주소 공간을 페이지(page) 단위로 자른 뒤 각 페이지를 프레임에 할당하는 가상 메모리 관리 기법.

    페이징에서도 스와핑 사용할 수 ㅇ. 페이징을 사용하는 시스템에서는 프로세스 전체가 스왑 아웃/스왑 인이 되는 것이 아니라 페이지 단위로 스왑 아웃/스왑 인이 된다.

    페이지 아웃(page - out) : 메모리에 적재될 필요 없는 페이지들을 보조기억장치로 스왑 아웃

    페이지 인(page - in) : 실행에 필요한 페이지들은 메모리로 스왑 인되는 것.

    → 한 프로세스를 실행하기 위해 프로세스 전체가 메모리에 적재될 필요없다는 말과 같음. 프로세스를 이루는 페이지 중 실행에 필요한 일부 페이지만 메모리에 적재하고, 당장 필요하지 않은 페이지들은 보조기억장치에 남겨둘 수 있다. 이와 같은 방식을 통해 물리 메모리보다 큰 프로세스를 실행할 수 있음.

    프로세스가 메모리에 불연속적으로 배치되어 있다면 cpu입장에서 순차적으로 실행할 수 없음. 프로세스를 이루는 페이지가 어느 프레임에 적재되어 있는지 cpu가 모두 알고 있기란 어려움(’다음에 실행할 명령어 위치’찾기).

    이를 해결하기 위해 페이징 시스템은 프로세스가 비록 (실제 메모리 내의 주소인)물리 주소에 불연속적으로 배치되더라도 (cpu가 바라보는 주소인) 논리 주소에는 연속적으로 배치되도록 페이지 테이블 이용해 CPU는 논리 주소를 순차적으로 실행하면 됨.

    페이지 테이블(page table) : 페이지 번호와 프레임 번호를 짝지어 주는 일종의 이정표. cpu가 페이지 번호만 보고 해당 페이지가 적재된 프레임을 찾을 수 있게함. → 현재 어떤 페이지가 어떤 프레임에 할당되었는지를 알려줌.

    페이징은 외부 단편화 문제를 해결할 수 있지만, 내부 단편화(internal fragmentation) 문제를 야기할 수 ㅇ. 페이징은 프로세스의 논리 주소 공간을 페이지라는 일정한 크기 단위로 자른다. 그런데 모든 프로세스가 페이지 크기에 맞게 딱 잘리는 것은 아닌데 페이지 크기가 프로세스의 크기와 맞지 않아 남게 되어 메모리 낭비되는 것을 내부 단편화라 한다. 내부 단편화는 하나의 페이지 크기보다 작은 크기로 발생한다. 테이블이 차지하는 공간이 낭비되지 않게 내부 단편화를 적당히 방지하면서 너무 크지 않은 페이지 테이블이 만들어지도록 페이지의 크기를 조정하는 것이 중요하다.

    프로세스마다 각자의 프로세스 테이블을 가지고 있고, 각 프로세스의 페이지 테이블들은 메모리에 적재되어 있음.

    테이블 베이스 레지스터(PTBR; Page Table Base Register) : 각 프로세스의 페이지 테이블이 적재된 주소를 가리키고 있음.

    이러한 각 프로세스들의 페이지 테이블 정보들은 각 프로세스의 PCB에 기록됨. 그리고 프로세스의 문맥 교환이 일어날 때 다른 레지스터와 마찬가지로 함께 변경됨.

    페이지 테이블을 메모리에 두면 메모리 접근 시간이 두 배로 늘어난다는 문제가 있음. 이를 해결하기 위해 cpu 곁에 TLB를 둠.

    TLB(Translation Lookaside Buffer) : 페이지 테이블의 캐시 메모리 역할을 수행하기 위해 페이지 테이블의 일부를 저장함. 참조 지역성에 근거해 최근에 사용된 페이지 위주로 가져와 저장.

    TLB 히트(TLB hit) : cpu가 발생한 논리 주소에 대한 페이지 번호가 TLB에 있을 경우, 페이지가 적재된 프레임을 알고 있어 메모리 접근 한 번만 하면 됨.

    TLB 미스(TLB miss) : 페이지 번호가 TLB에 없을 경우 페이지가 적재된 프레임을 알기 위해 메모리 내의 페이지 테이블에 접근하는 것.

    하나의 페이지 혹은 프레임은 여러 주소를 포괄하고 있어 특정 주소에 접근하려면 필요한 두 가지 정보

    그렇기에 페이지 시스템에서는 모든 논리 주소가 기본적으로 페이지 번호와 변위로 이루어져 있음. <페이지 번호, 변위>

    페이지 번호(page number) : 말 그대로 접근하고자 하는 페이지 번호, 페이지 테이블에서 해당 페이지 번호를 찾으면 페이지가 어떤 프레임에 할당되었는지를 알 수 ㅇ.

    변위(offset) : 접근하려는 주소가 프레임의 시작 번지로부터 얼만큼 떨어져 있는지를 알기 위한 정보.

    논리 주소 <페이지 번호, 변위>는 페이지 테이블을 통해 물리 주소 <프레임 번호, 변위>로 변환됨. 논리 주소의 변위와 물리 주소의 변위 값은 같다.

    페이지 테이블 엔트리(PTE; Page Table Entry) : 페이지 테이블의 각각의 행들을 말함.

    페이지 테이블 엔트리에 담기는 정보로 페이지 번호, 프레임 번호 이외에도 다른 중요한 정보들이 있는데 대표적인 것이 유효 비트, 보호 비트, 참조 비트. 수정 비트이다.

  3. 페이지 교체와 프레임 할당

    운영체제는 프로세스들이 한정된 메모리를 효율적으로 이용할 수 있도록 기존에 메모리에 적재된 불필요한 페이지를 선별하여 보조기억장치로 내보낼 수 있어야 하고, 프로세스들에 적절한 수의 프레임을 할당해 페이지를 할당할 수 있게 해야한다.

    요구 페이징(demand paing) : 프로세스를 페이지가 필요할 때에만 메모리에 적재하는 기법.

    요구 페이지의 기본적인 양상

    1. cpu가 특정 페이지에 접근하는 명령어를 실행.
    2. 해당 페이지가 현재 메모리에 있을 경우(유효 비트가 1일 경우) cpu는 페이지가 적재된 프레임에 접근.
    3. 해당 페이지가 현재 메모리에 없을 경우(유효 비트가 0일 경우) 페이지 폴트가 발생.
    4. 페이지 폴트 처리 루틴은 해당 페이지를 메모리로 적재하고 유효 비트를 1로 설정.
    5. 다시 1번을 수행.

    순수 요구 페이징(pure demand paging)기법 : 아무런 페이지도 메모리에 적재하지 않은 채 무작정 실행부터 할 수도 있는데 이 경우엔 프로세스의 첫 명령어를 실행하는 순간부터 페이지 폴트가 계속 발생하게 되고, 실행에 필요한 페이지가 어느 정도 적재된 이후부턴 페이지 폴트 발생 빈도가 떨어짐.

    요구 페이징 시스템이 안정적으로 작동하기 위해 필연적으로 해결해야 하는 2가지 : 페이지 교체, 프레임 할당

    페이지 교체 알고리즘 : 메모리가 가득 차 당장 실행에 필요한 페이지를 적재하기 위해 메모리에 적재된 페이지를 보조기억장치로 내보내야 한다. 메모리에 적재된 많은 페이지 중 어떤 페이지를 내보내는 것이 최선인지 결정하는 방법을 말한다. → 쫓아낼 페이지를 결정하는 방법.

    좋은 페이지 교체 알고리즘은 일반적으로 페이지 폴트를 가장 적게 일으키는 알고리즘을 좋은 알고리즘으로 평가한다. 페이지 폴트가 일어나면 보조기억장치로부터 필요한 페이지를 가져와야 하기 때문에 메모리에 적재된 페이지를 가져오는 것보다 느려지기 때문에.

    ‘한 페이지 교체 알고리즘을 선택했더니 페이지 폴트가 자주 발생했다’ → ‘보조기억장치로 내쫓을 페이지를 잘못 골랐다’는 뜻으로, 내보내면 안되는 페이지를 보조기억장치로 내보냈다는 의미와 같기 때문. 이는 당연히 컴퓨터의 성능을 저해하는 나쁜 알고리즘일 것이다.

    페이지 교체 알고리즘을 제대로 이해하려면 페이지 폴트 횟수를 알 수 있어야 한다. 그리고 페이지 폴트 횟수는 페이지 참조열을 통해 알 수 있다.

    페이지 참조열(page reference string) : cpu가 참조하는 페이지들 중 연속된 페이지를 생략한 페이지 열.

    연속된 페이지를 생략하는 이유는 중복된 페이지를 참조하는 행위는 페이지 폴트를 발생시키지 않기 때문. 페이지 교체 알고리즘을 평가할 때 관심있게 고려할 것은 오직 페이지 폴트의 발생 횟수이기 때문에 어차피 페이지 폴트가 일어나지 않을 연속된 페이지에 대한 참조는 고려하지 않는 것임.

    FIFO 페이지 교체 알고리즘(First-In First-Out Page Replacement Algorithm) : 메모리에 가장 먼저 올라온 페이지부터 내쫒는 방식으로 적재된 페이지 순서대로 교체하는 알고리즘을 말함. 아이디어와 구현은 간단하지만 실행 초기에 적재된 페이지 속에 프로그램 실행 초기에 잠깐 실행되다가 이후에 사용되지 않을 페이지도 있겠지만, 프로그램 실행 내내 사용될 내용을 포함하고 있을 수도 ㅇ. 그러니 이런 페이지는 먼저 적재되었다고 내쫓아서는 안됨.

    최적 페이지 교체 알고리즘(optimal page replacement algorithm) : cpu에 의해 참조되는 횟수를 고려하는 가장 오랫동안 사용하지 않을 페이지를 예상해 앞으로의 사용 빈도가 가장 낮은 페이지를 교체하는 알고리즘, 가장 낮은 페이지 폴트율을 보장하는 알고리즘. 현실적으론 사용 불가능 이론상 성능을 평가하기 위한 목적으로 사용됨.

    LRU 페이지 교체 알고리즘(LRU; Least Recently Used Replacement Algorithm) : 가장 오랫동안 사용되지 않은 페이지를 교체하는 알고리즘

    스래싱(thrashing) : 프로세스가 실제 실행되는 시간보다 페이징에 더 많은 시간을 소요해 성능이 저해되는 문제. → 지나치게 빈번한 페이지 교체로 인해 cpu 이용률이 낮아지는 문제.

    멀티 프로그래밍의 정도(degree of multiprogramming) : 메모리에서 동시에 실행되는 프로세스의 수. 멀티프로그래밍의 정도가 높다면 현재 메모리에는 많은 프로세스가 실행 중이고, 낮다면 현재 메모리에는 적은 프로세스가 동시에 실행 중이라고 이해하면 됨.

    스레싱이 발생하는 근본적인 원인은 각 프로세스가 필요로 하는 최소한의 프레임 수가 보장되지 않았기 때문.

    운영체제는 각 프로세스들이 무리 없이 실행하기 위한 최소한의 프레임 수를 파악하고 프로세스들에 적절한 수만큼 프레임을 할당할 수 있어야 한다.

    프레임 할당 방식

    → 균등 할당과 비례 할당 방식은 프로세스의 실행 과정을 고려하지 않고 단순히 프로세스의 크기와 물리 메모리의 크기만을 고려한 방식이라는 점에서 정적 할당 방식이라고도 함.

    프로세스를 실행하는 과정에서 배분할 프레임을 결정하는 방식에는 크게 작업 집합 모델을 사용하는 방식과 페이지 폴트 빈도를 사용하는 방식이 있다. → 이 두 개 방식은 프로세스의 실행을 보고 할당할 프레임 수를 결정한다는 점에서 동적 할당 방식이라고도 함.

chapter 15. 파일 시스템

  1. 파일과 디렉터리

파일과 디렉터리는 보조기억장치에 있는 데이터 덩어리, 운영체제 내부의 파일 시스템에서 관리하는 존재

파일(file) : 보조기억장치에 저장된 관련 정보의 집합 = 의미있고 관련된 정보를 모은 논리적 단위

파일을 이루는 정보는 이름과 파일을 실행하기 위한 정보, 파일 관련 부가 정보가 있다.

부가 정보를 속성(attribute) 또는 **메타데이터(metadata)**라고 부름.

파일 속성 중 유형은 운영체제가 인식하는 파일 종류를 나타냄. 같은 파일일지라도 텍스트 파일, 음악 파일, 실행 파일 등 유형이 다르면 실행 양상도 달라짐. 그래서 파일을 실행할 때 운영체제에 유형을 알려주어야 함.

파일 유형을 알리기 위해 가장 흔히 사용되는 방식은 파일 이름 뒤에 붙는 **확장자(extension)**를 이용하는 것.

확장자는 파일 종류가 무엇인지 운영체제에 힌트를 주는 것과 같다. ex) myfile.o o라는 확장자를 통해 운영체제에 목적 코드를 담고 있는 목적 파일임을 알려주는 셈이고, myfile.exe exe라는 확장자를 통해 운영체제에 실행 파일임을 알려주는 셈이다.

파일 유형 대표적인 확장자
실행 파일 exe, com, bin,없는 경우
목적 파일 obj, o
소스코드 파일 c, cpp, cc, java, asm, py
워드프로세서 파일 xml, rtf, doc, docx
라이브러리 파일 lib, a, so, dll
멀티미디어 파일 mpeg, mov, mp3, mp4, avi
백업/보관 파일 rar, zip, tar

파일을 다루는 모든 작업은 모두 운영체제에서 이뤄진다. 어떤 응용프로그램도 임의로 파일을 조작할 수 없으며 운영체제에 부탁해 파일을 다뤄야 한다. 이를 위해 운영체제는 다음과 같은 파일 연산을 위한 시스템 호출을 제공한다. (파일 생성, 파일 삭제, 파일 열기, 파일 닫기, 파일 읽기, 파일 쓰기)

디렉터리(directory) : 파일들을 일목요연하게 관리하기 위해 이용, 윈도우 운영체제에선 **폴더(folder)**라 부름.

옛날 디렉터리는 하나의 디렉터리만 존재했었음. 모든 파일이 하나의 디렉터리 아래에 있는 구조로 1단계 디렉터리(single-level directory)라 함. 1단계 디렉터리로는 많은 파일을 관리하기 어려워 여러 계층을 가진 트리 구조 디렉터리(tree-structured directory)가 생겨나게 됨.