55_디스크 스왑 공간 관리(Disk Swap Space Management)

 

스와핑은 프로세스 전체를 디스크나 메인 메모리로 옮기는 작업으로 사용 가능한 물리 메모리가 매우 작을 때 활성화 되며 사용 가능 메모리를 만들기 위해 프로세스들은 메모리에서 스왑 공간으로 이동 된다. 대부분의 현재 운영체제들은 이러한 방식이 아닌 스와핑과 가상 메모리 기법을 이용하여 페이지를 스왑한다.

 

스왑 공간 관리는 운영체제가 수행하는 저수준 작업으로 가상 메모리는 디스크를 주 메모리의 스왑 공간으로 사용한다. 디스크는 메모리보다 느리므로 스왑 공간의 설계는 매우 중요하다.

 

[스왑 공간 사용 (Swap Space Use)]

사용하는 메모리 관리 알고리즘에 따라 스왑 공간은 운영체제마다 다양한 방법들로 운영된다. 스왑 공간은 예상보다 크게 잡는 것이 안전하다. 시스템을 운영하다가 스왑 공간이 바닥나면 프로세스들을 도중에 중단시켜야 하고 최악의 경우에는 시스템 전체가 손상될 수 있다.

  • Solaris는 가상 메모리 크기에서 페이징이 가능한 물리 메모리를 뺀 만큼을 제안한다.
  • Linux는 물리 메모리 크기에 두 배를 제안하나 현재 대부분의 Linux 시스템들은 그보다 작은 스왑 공간을 사용한다.

 

Linux를 포함한 여러 운영체제는 여러 개의 스왑 공간을 가질 수 있다. 이들 스왑 공간들은 보통 여러 다른 디스크에 할당되어 페이징과 스와핑에 대한 I/O부하를 I/O 디바이스에 분산한다.

 

[스왑 공간 위치 (Swap Space Location)]

스왑 공간은 두 군데 있을 수 있다. 일반 파일 시스템이 차지하고 있는 공간 안에 만들 수도 있고 별도의 파티션을 만들어 사용할 수도 있다.

 

스왑 공간이 만일 하나의 커다란 파일이라면 통상 파일 시스템 루틴을 사용하여 스왑 공간을 생성/삭제하고 스왑 공간을 관리 할 수 있다. 이 방법은 구현하기 쉬우나 스왑 할 때마다 디렉토리 구조와 디스크 할당 자료 구조를 거쳐야 하기 때문에 추가 액세스로 인한 비효율이 발생한다.

 

스왑 공간을 일반 파일이나 디렉토리는 저장되지 않는 별도의 비가공(raw) 파티션에 위치하는 경우 공간 효율성은 상대적으로 낮지만 스왑 공간은 파일 시스템 보다 자주 접근 되기 때문에 속도 효율성에는 많은 이득이 있다. 또한 내부 단편화 문제에서도 스왑 공간안에 있는 자료는 일반 파일보다 짧은 시간 동안만 존재하기 때문에 큰 문제가 되지 않는다.

 

스왑 공간은 부트시에 초기화 되어 단편화 현상은 오래 남지 않는다. 디스크 파티션을 나눌 때 별도의 파티션을 만들어 스왑 공간을 만들어 사용한다. 스왑 공간을 늘리려면 파티션 작업을 새로 하거나 별도의 파티션에 새로운 스왑 공간을 추가해야 한다.

 

 

[Solaris와 Linux 스왑 공간 관리]

Solaris는 가상 메모리 페이지가 처음 생성되었을 때가 아닌 한 페이지가 물리 메모리에서 쫓겨날 때 스왑 공간을 할당한다. 이 방법은 현재의 시스템이 예전보다 큰 물리 메모리를 가지고 있기 때문에 더 좋은 성능을 보여준다.

 

Linux는 스왑 공간을 익명 메모리 혹은 다수의 프로세스들이 공유하는 메모리 영역에만 사용한다. 이런 면에서 Solaris와 유사하다. Linux는 한 개 이상의 스왑 영역을 허용하며 일반 파일 시스템 및 스왑 파티션에 위치할 수도 있다. 각 스왑 영역은 연속된 4KB의 페이지 슬롯(page slot)들로 구성되고 이 페이지 슬롯들에 스왑된 페이지들이 적재 된다. 각각의 스왑 영역은 스왑 맵(swap map)으로 연관 된다. 해당 카운터 값이 0이면 사용가능하고 0보다 큰 값은 스왑된 페이지들이 사용하고 있는 것을 나타낸다

 

[참고자료]

Operating System Concepts / 홍릉과학출판사

 

 

54_디스크 관리(Disk Management)

 

운영체제는 디스크 관리 기능 일부를 담당한다. 포맷을 통한 섹터의 관리, 컴퓨터 시작을 위한 부트 블록 관리, 디스크의 손상된 블록 등을 관리 한다.

 

[디스크 포맷(Disk Format)]

디스크는 자료를 저장하기 전에 섹터들로 나누어져 있어야 한다. 이 과정을 저수준 포맷팅(low level formatting) 또는 물리적 포맷팅 이라 한다.

 

저수준 포맷팅은 섹터를 구분하기 위해 디스크를 적절한 자료구조로 채우는 것이며 자료 구조는 보통 헤더, 자료 영역(보통 512 바이트), 트레일러로 구분 된다. 헤더와 트레일러는 수정 코드(ECC, Error Correcting Code)와 같은 정보를 가지고 있다.

 

 

디스크 제어기가 섹터에 자료를 쓸 때 자료 값으로부터 ECC를 구해서 같이 기록한다. 나중에 이 섹터가 읽혀질 때 자료로부터 ECC가 다시 계산되고 이것이 저장되었던 ECC값과 비교하여 서로 다르면 섹터에 문제가 발생한 것이다. ECC는 1~2개의 비트만 잘못 되었을 때 이를 교정할 수 있는 오류 수정 코드 이다. ECC처리는 대부분 섹터를 읽고 쓸 때 제어기에 의해 자동으로 이루어 진다.

 

포맷을 진행 할 때 디스크의 섹터 크기를 크게 하면 트랙 당 섹터수가 줄어들고 헤더와 트레일러가 차지하는 공간이 자료가 차지하는 공간에 비해 상대적으로 줄어들게 되어 디스크 공간 이용 효율성이 올라가게 된다.

 

디스크에 파일을 저장하기 위해서 운영체제는 디스크에 운영체제의 자료 구조를 기록할 필요가 있으며 두 단계로 이루어 진다.

  1. 디스크를 여러 실린더들로 이루어지는 파티션을 만든다. 운영체제는 각 파티션을 각각 별도의 디스크 드라이브처럼 취급한다.
  2. 논리적 포맷팅은 파일 시스템을 만드는 것이다. 이 단계는 운영체제가 파일 시스템 자료 구조를 디스크에 저장하는 일이다.

 

 

[부트 블록 (Boot Block)]

컴퓨터를 부팅 할 때 시스템을 시작 시키는 프로그램이 요구되며 부트스트랩 프로그램은 운영체제가 어디에 저장되어 있는지 알아내고 그것을 메모리에 올려놓고 시작 시킨다.

 

대부분 시스템들은 ROM에 부트스트랩 프로그램을 저장한다. 하지만 ROM의 경우 부트스트랩을 교체하기 위해 하드웨어 칩을 교체해야 하기 때문에 ROM에는 부트스트랩 프로그램 본체를 디스크로부터 적재하는 일만 하는 아주 작은 부트스트랩 적재기(bootstrap loader) 프로그램만 저장한다. 부트스트랩 프로그램 본체는 쉽게 변경이 가능하고 본 디스크의 고정된 위치인 "부트 블록"에 저장한다. 부트 파티션을 가지고 있는 디스크는 부트 디스크 또는 시스템 디스크라 한다.

 

ROM 내의 부트스트랩 적재기가 하는 일은 디스크 제어기에게 부트스트랩 프로그램을 메모리에 올리도록 지시하고 그 프로그램의 수행을 시작 한다. 부트스트랩 프로그램 본체는 디스크 내 임의의 장소에 저장되어 있는 운영체제 커널을 찾아내고 그것을 시작시키는 일까지 하게 된다.

 

 

Windows의 부트코드는 하드 디스크에 첫 번째 섹터에 저장된다.(master boot record 또는 MBR 영역이라고 함) 일단 시스템이 부트 파티션을 찾으면 첫 번째 섹터부터 읽고 여러 시스템과 서비스들을 적재하는 등의 부트 프로세스의 남은 일을 재개 한다.

 

 

[손상된 블록 (Bad Block)]

디스크는 움직이는 부품들로 구성되어 있기 때문에 언제든지 오류가 발생할 가능성이 있다. 손상된 블록들은 디스크와 제어기에 따라 다양한 방법으로 처리될 수 있다.

 

 

Microsoft의 format명령은 논리적 포맷을 하는데 손상된 블록이 있는지 검사하여 손상된 블록을 발견하면 그 블록을 더 이상 사용하지 못하도록 FAT 테이블에 표시해 놓는다.

서버에 사용되는 디스크(SCSI)등은 제어기가 손상된 디스크 블록 리스트를 유지 한다. 리스트는 공장에서 저수준 포맷하는 동안 초기화되고 저수준 포맷팅은 운영체제가 볼 수 없는 예비 섹터를 남겨놓아 손상된 섹터와 교체할 수 있다. 이 방법을 섹터 옴기기(forwarding)혹은 섹터 남기기(sparing)로 알려져 있다.

 

예비 섹터를 관리하는 다른 방법으로 일부 제어기는 섹터 밀어내기(sector slipping)에 의해 손상 섹터를 처리할 수 있도록 한다. 블록이 손상되면 자료가 유실되기 때문에 이를 완전히 자동으로 처리할 수 는 없다. 소프트 에러(soft error)들은 손상된 블록 자료를 복사하고 그 블록을 예비 블록으로 하거나 밀어내기를 하여 처리 한다.

 

하드 에러(hard error)는 복구가 되지 않으며 자료를 잃게 되어 손상된 블록의 내용을 다른 백업 디스크에서 가져와서 복구하는 등 사람의 개입을 필요로 한다.

 

 

[참고자료]

Operating System Concepts / 홍릉과학출판사

 

53_디스크 스케줄링(Disk Scheduling)

 

운영체제의 역할 중 하나는 효율적인 하드웨어 사용이다. 디스크 드라이브의 경우에는 빠른 접근 시간과 높은 전송량을 제공해야 함을 의미한다. 디스크 접근시간은 두 가지 요소로 이루어지는데 탐색시간(seek time, 디스크 암이 헤드를 해당 실린더로 움직이는데 걸린 시간)과 회전 지연(rotational latency, 디스크 헤드가 원하는 섹터 위치로 도달하기까지 회전에 소요되는 추가적인 시간)시간 이다. 디스크 대역폭(bandwidth)은 단위 시간 당 전송되는 총 바이트 수이다. 효율적인 스케줄링은 접근 시간과 대역폭을 모두 향상 시킬 수 있다.

 

프로세스가 입/출력을 필요로 할 때마다 운영체제에 시스템 호출(system call)을 한다. 이 호출에는 여러 가지 인수가 주어 진다.

  • 입력인가 출력인가
  • 디스크 주소
  • 메모리 주소
  • 전송될 섹터 수

 

디스크 드라이브가 유휴 상태라면 이 요청은 즉시 처리 되고 아니면 큐(queue)에 들어가 기다려야 한다. 다중 프로그래밍에서는 많은 프로세스들이 디스크를 공유하므로 이 큐에는 여러 디스크 입/출력 요청들이 함께 대기하고 있을 수 있다.

 

디스크는 대기하는 작업의 처리 순서를 제어하는 여러 알고리즘을 사용하는데 그 종류에 대해서 알아 보자.

 

[선입 선처리 스케줄링 (FCFS Scheduling)]

가장 간단한 형태인 선입 선처리(first-come-first-served)이다. 이 알고리즘은 본질적으로는 공평해 보이지만 빠른 서비스를 제공하지는 못한다. 예를 들어 다음과 같은 입/출력 요청이 디스크 큐에 있다고 가정한다.

98, 183, 37, 122, 65, 67

 

디스크 헤드가 현재 53 실린더에 있다면 헤드는 53->98->183->37 … 67로 이동하여 총 640 실린더 헤드를 이동하는데 비용이 많이 든다.

 

 

 

[최소 탐색 시간 우선 스케줄링 (SSTF Scheduling)]

헤드(head)가 다른 곳으로 이동을 시작하기 전에 근처에 있는 요구들을 먼저 처리해 주고 헤드를 이동하는 것이 합리적이다. 최소 탐색 시간 우선(Shortest Seek Time First)알고리즘은 이러한 논리에 근거한 것이다. 이 알고리즘은 현재 위치로부터 가장 가까운 요청을 우선 선정한다. 탐색 시간은 헤드가 경유하는 실린더 수에 따라 증가하므로 최소 탐색 시간 우선은 현재 위치로 가장 가까이 요청된 것을 선택 한다.

 

현재 헤드가 53 실린더에 있다면 가장 가까운 65 -> 67 -> 37 …-> 183 순서로 처리 된다.

 

최소 탐색 시간 우선(SSTF) 알고리즘은 최소 작업 우선(Shortest Job First) 스케줄링과 유사하지만 몇 개의 요청들은 매우 오래 기다리게 되는 기아(starvation) 상태가 발생하게 된다. 새로운 요청이 기존의 위치와 가까운 요청이 계속 들어온다면 멀리 있는 요청은 무한정 기다려야 하는 현상이 발생한다. 이 같은 현상은 큐의 길이가 길어질수록 심해 진다.

 

최소 탐색 시간 우선 알고리즘은 선입 선처리 보다는 상당히 개선되었지만 최적의 방법은 아니다.

 

[SCAN 스케줄링(SCAN Scheduling)]

SCAN 알고리즘에서는 디스크 암(disk arm)이 디스크의 한 끝에서 시작하여 다른 끝으로 이동하며 가는 길에 있는 모든 요청을 처리 한다. 다른 한쪽 끝에 도달하면 역 방향으로 이동하면서 오는 길에 있는 요청을 처리 한다. 엘리베이터처럼 왕복하며 처리하므로 엘리베이터(elevator algorithm)이라고도 부른다.

 

 

[C-SCAN 스케줄링 (C-SCAN Scheduling)]

C-SCAN 스케줄링은 각 요청에 걸리는 시간을 좀 더 균등하게 하기 위한 SCAN의 변형이다. SCAN과 같이 C-SCAN은 한쪽 방향으로 헤드를 이동해 가면서 요청을 처리하지만 한쪽 끝에 다다르면 반대 방향으로 헤드를 이동하며 처리하는 것이 아니라 처음 시작했던 자리로 다시 되돌아가서 서비스를 시작한다. C-SCAN 스케줄링 알고리즘은 실린더들을 마지막 실린더가 처음 실린더와 맞닿은 원형 리스트로 간주 한다.

 

 

[LOOK 스케줄링 (LOOK Scheduling)]

SCAN나 C-SCAN 스케줄링은 헤드를 디스크의 끝에서 끝으로 이동한다는 점에 유의해야 한다. 그러나 실제로 이런 방식으로 구현하지는 않는다. 보통 헤드는 각 방향으로 가다가 그 방향에서 아무도 기다리는 요청이 없으면 헤드의 이동 방향을 즉시 반대로 바꾸면 된다. SCAN과 C-SCAN 스케줄링의 이런 변형을 한 방향으로 계속 움직이기 전에 요구가 있는지 확인(look for)하기 때문에 각각 LOOK, C-LOOK 스케줄링 이라 한다.

 

 

[참고자료]

Operating System Concepts / 홍릉과학출판사

 

52_네트워크 파일 시스템 (Netwrok File System)

 

NFS는 LAN을 거쳐 원격 파일을 접근하기 위한 소프트웨어 시스템의 구현과 명세 모두를 말한다. 통신은 TCP 또는 UDP 두 가지 중 하나를 사용한다.

 

NFS의 목적은 이들 파일 시스템들 사이에서 일정 수준의 공유를 투명하게 허용하는 것이다. 공유는 클라이언트 서버의 관계를 기반으로 하며 시스템은 동시에 클라이언트와 서버가 될 수 있다.

 

[원격 디렉토리 접근]

  1. 원격 디렉토리가 특정 시스템(M1)으로부터 투명하게 접근 가능하도록 하기 위해서 M1의 클라이언트는 먼저 마운트 명령을 실행 한다.
  2. 마운트 명령은 원격 디렉토리가 지역 파일 시스템의 디렉토리 상에 장착 되게 한다.
  3. 마운트 명령이 완료되면 장착된 디렉토리는 지역 파일 시스템의 서브트리처럼 보이며 지역 디렉토리의 기존 서브트리를 대체한다.
  4. 지역 디렉토리는 새로 장착된 디렉토리의 루트의 이름이 된다.
  5. 마운트 명령을 위한 매개변수로 원격 디렉토리를 지정하는 일은 투명하지 않은 방식으로 실행 된다. 즉 원격 디렉토리의 위치가 반드시 제공 되어야 한다.
  6. 일단 장착되고 나면 시스템 M1의 사용자 들은 원격 티렉토리의 파일을 완전히 투명하게게 접근할 수가 있다.

 

일부 NFS 구현에서는 연속(cascading) 마운트를 허용한다. 즉 한 파일 시스템이 원격 장착된 파일 시스템에 다시 장착 될 수 있다. 한 기계는 단지 자신이 호출한 마운트에 의해서만 영향을 받는다. 원격 파일 시스템을 장착해도 클라이언트는 원격 파일 시스템에 우연히 이미 장착되어 있던 다른 파일 시스템은 접근할 수 없다. 그러므로 마운트 기법은 이행성(transitivity) 특성을 갖지 않는다.

 

[NFS 설계 목표]

NFS의 설계 목표 중 하나는 서로 다른 기계, 운영체제, 네트워크 구조로 구성된 다른 환경에서 작동하는 것이다. NFS 명세는 이들 매체에 독립적이기 때문에 다른 구현들을 이용 가능하게 한다. 이러한 독립성은 두 개의 구현된 독립적 인터페이스간에 사용되는 외부 자료 표현(XDR, Extenal Data Representation)프로토콜 위에 구축된 RPC 프리미티브를 통해서 이루어 진다. 따라서 NFS와 정확하게 인터페이스되는 이기종 시스템과 파일 시스템으로 구성된 시스템에서는 다른 유형의 파일 시스템들도 지역 또는 원격으로 장착될 수 있다.

 

NSF 명세는 마운트 기법에 의해 제공되는 서비스와 실제 원격 파일 접근(remote file access)서비스를 구분한다. 이들 서비스들을 위해 두 가지의 다른 프로토콜이 명세 되어 있다.

  • 마운트 프로토콜(Mount Protocol) : 마운트 프로토콜은 서비스와 클라이언트 사이의 초기 논리적 연결을 생성하기 위해서 사용된다. 각 시스템은 커널 외부에 프로토콜의 기능들을 실행하는 하나의 서버 프로세스를 가진다.
  • NFS 프로토콜 (NFS Protocol) : NFS 프로토콜은 원격 파일 연산을 위한 원격 프로시저 호출의 집합을 제공 한다. 이 프로시저는 다음과 같은 연산들을 지워 한다
    • 디렉토리 내의 파일 검색
    • 디렉토리 항목 집합의 읽기
    • 파일 속성의 접근
    • 파일 읽기와 쓰기

이러한 프로시저는 원격으로 장착된 디렉토리에 대한 파일 핸들이 구축되어야만 호출할 수 있다.

 

[VFS (Virtual File System)]

NFS는 가상 파일 시스템(VFS)을 통하여 운영체제로 통합된다. 이미 열려진 원격 파일에 대한 연산들이 어떻게 처리되는지 확인해 보자.

 

  1. 클라이언트는 정규 시스템 호출을 통해서 연산을 시작한다.
  2. 운영체제 계층은 이 호출을 적절한 vnode에 대한 VFS 연산으로 매핑 한다.
  3. VFS 계층은 이 파일을 원격 파일로 인식하고 적절한 NFS 프로시저를 실행한다.
  4. 하나의 RPC 호출이 원격 서버 내의 NFS 서비스 계층에 대해 행해진다.
  5. 이 호출은 원격 시스템 상의 VFS 계층으로 다시 들어가고 원겨격 시스템은 그 호출이 지역적임을 반견하며 적절한 파일 시스템 연산을 실행 한다.
  6. 이 경로를 되돌아가 결과를 반환한다.

 

이러한 구조의 장점은 클라이언트와 서버가 동등하므로 시스템이 클라이언트나 서버 모두가 될 수 있다. 각 서버에서 실제적인 서비스는 경량 프로세스(lightweight process), 즉 스레드(thread) 기법을 일시적으로 대체하는 여러 커널 프로세스들에 의해서 실행 된다.

 

 

[참고자료]

Operating System Concepts / 홍릉과학 출판사

 

 

 

 

51_로그 구조 파일 시스템 (Log Structure File System)

 

디스크 상의 디렉토리 구조, 자유 블록 포인터, 자유 FCB 포인터와 같은 파일 시스템 자료 구조는 시스템 고장 발생 시 일관성이 없어 질 수 있다. 운영체제가 로그 기반 기술을 사용하기 전에는 보통 이들에 대한 변경들은 이들 구조에 직접 적용 되었다.

 

파일 생성과 같은 대표적인 연산은 디스크 상의 파일 시스템 내부의 많은 구조적 변화를 포함한다. 이러한 변경은 고장에 의해 방해 받을 수 있고 이들 구조가 일관성이 없어지는 결과를 초래한다.

 

시스템 구조가 깨어질 수 있게 허용하고 복구 시 수리하도록 하는 접근 방법에는 여러 문제가 존재 한다. 그 중 한가지는 비일관성을 회복할 수 없을 수도 있다는 것이다. 일관성 검사가 구조를 복구할 수 없어 파일을 잃거나 디렉토리 전체를 잃게 될 수도 있다.

 

이 문제의 해결 방안은 파일 시스템 메타데이터 갱신에 로그 기반 복구 기술을 적용하는 것이다. 기본적으로 모든 메타데이터 변경은 로그에 순차적으로 기록된다. 특정 태스크를 실행하는 연산의 집합 각각을 하나의 트랜잭션이라고 한다.

 

변경이 로그에 기록되면 커밋된 것으로 간주되고 시스템 호출은 사용자 프로세스로 복귀하여 실행을 계속하도록 허용 한다. 그동안 이 로그 항목은 실제 파일 시스템 구조에 대해 재실행 된다.

 

변경이 반영되는 동안 어느 동작이 끝났는지 그리고 어느 것이 아직 덜 끝났는지를 나타내기 위해 포인터가 갱신된다. 커밋된 전체 트랜잭션이 완료되면 이 로그는 원형 버퍼로 구성된 로그 파일로부터 제거 된다.

 

 

원형 버퍼(circular buffer)는 버퍼 공간의 맨 뒤에 기록하고 맨 앞에서 시작하는 연속적인 공간으로 구성 된다. 이러한 원형 버퍼는 연속적으로 기록되므로 이전의 자료 위에 겹쳐서 기록될 것이다. 따라서 원형 버퍼를 사용할 경우에는 아직 저장되지 않은 유효한 자료 위에 겹쳐서 기록되지 않게 관리된다.

 

시스템이 고장(crash)나면 로그 파일에 0개 이상의 트랜잭션이 있을 것이다. 이러한 트랜잭션들은 운영체제에 의해 커밋되었다 할지라도 파일 시스템에서 결코 실행이 완료 되지 않은 것이기 때문에 이들은 반드시 실행을 완료 해야 한다. 이 트랜잭션들은 작업이 완료될 때까지 실행될 수 있고 파일 시스템 구조는 일관성을 유지하게 된다.

 

유일한 문제는 트랜잭션이 중단되었을 때 발생하는데 트랜잭션이 커밋되기 이전에 시스템에 장애가 발생 할 경우 트랜잭션에 의해 변경된 파일 모두 복구해야 시스템의 일관성이 유지된다.

 

디스크 메타데이터 갱신에 대한 로그를 사용하는 부수적인 이득은 이들을 직접 디스크 자료 구조에 적용하는 것보다 갱신이 더 빠르다는 것이다. 이러한 성능 향상은 임의 입/출력에 비해 순차 입/출력이 빠르다는데서 찾을 수 있다.

 

비용이 많이 드는 동기식 임의 메타데이터 쓰기가 비용이 훨씬 적게 드는 로그 구조 파일 시스템의 로깅 지역에 대한 동기식 순차 쓰기로 변환된다. 이러한 변환은 다시 해당 구조에 대한 임의 쓰기를 통하여 비동기로 재실행 된다.

 

[참고자료]

Operating System Concepts / 홍릉과학출판사

 

50_디스크 자유 공간 관리(Free-Space Management)

 

디스크의 공간은 제한되어 있기 때문에 삭제된 파일들일 차지하던 공간을 새로운 파일들을 위하여 다시 재사용하여야 한다. 시스템은 이러한 자유 공간을 리스트로 유지하고 관리한다.

 

디스크는 자유 공간 리스트에 디스크의 모든 자유 블록들을 등록 한다. 새로운 파일을 만들려면 자유 공간 리스트를 탐색하여 새로운 파일을 위한 공간을 할당 받아야 한다. 할당 된 공간은 자유 리스트로부터 삭제 된다.

 

자유 공간 관리를 위해서 꼭 리스트 형태로만 구현될 필요는 없다. 관리를 위해 사용되는 다양한 방법을 알아 보자.

 

[비트 벡터(Bit Vector)]

자유 공간 리스트는 흔히 비트 맵(bit map) 또는 비트 벡터(bit vector)로써 구현 된다. 여기서 각 블록은 1비트로 표현된다. 만약에 블록이 자유로우면 그 비트는 1이 되고 만약 블록이 할당되어 있다면 그 비트는 0이 된다.

 

예를 들어 디스크의 블록들 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 17, 18, 25, 26, 27이 비어 있고 나머지 블록은 할당되어 있다고 가정 할 때 그 자유 공간 비트맵은 다음과 같다.

 

001111001111110001100000011100000…

 

이 방법의 큰 이점은 첫 번째 자유 블록 또는 n개의 연속된 자유 블록들을 찾는 일이 간편하고 효율적이다. Apple Macintosh 운영체제는 디스크 공간 할당을 위해 비트 벡터 기법을 사용한다. Macintosh 운영체제는 비트 맵의 각 워드를 순차적으로 검사하여 0이 아닌 워드를 찾고 그 워드에서 첫 번째 1비트를 찾는다. 블록번호는 다음과 같이 계산 한다.

 

(워드의 비트 수) * (값이 0인 워드 수) + 첫 번째 1비트의 오프셋

 

비트 벡터는 그 전체가 주 메모리 내에 존재하지 않으면 비효율적이 된다.

 

[연결 리스트 (Linked List)]

모든 자유 디스크 블록들을 함께 연결시키는 것인데 첫 번째 자유 블록은 다음 자유 블록을 가리키는 포인터를 가진다. 두 번째 자유 블록은 다음 자유 블록의 포인터를 가지고 계속 그런 방법으로 구현 된다.

 

 

시스템은 첫 번째 자유 블록에 대한 포인터를 디스크의 특정 위치에 두고 메모리에 캐싱하여 사용 한다.

 

자유 리스트를 순회 하려면 매번 디스크를 접근해야 하므로 효율적이지 못하나 자유 리스트는 순회는 자주 발생하지 않는다. 통상 운영체제는 단순히 파일에 할당할 하나의 자유 블록이 필요하며 자유 리스트의 첫 블록을 사용할 수 있다.

 

 

 

[그룹핑(Grouping)]

자유 리스트 방식의 변형으로 첫 번째 자유 블록 내에 n 개의 블록 주소를 저장하는 방법이다. 이 중 처음 n -1 개는 실제로 비어 있는 블록의 주소이다. 그러나 마지막 1개는 자신과 마찬가지로 n-1 개의 빈 블록 주소를 가지고 있는 자유 블록을 가리킨다.

 

이 방법은 연결 리스트 방법과는 달리 다수 개의 자유 블록 주소들을 쉽게 찾을 수 있다는 점이 장점이다.

 

[계수 (Counting)]

프로그램들이 매우 자주(여러 연속된) 블록들을 할당하고(여러 연속된) 블록들을 반환 한다는 사실에 착안한 것으로 특히 연속 할당 알고리즘이나 클러스터링을 통해 공간을 할당 할 경우 유용하다.

 

모든 블록을 일일이 추적할 필요가 없이 연속된 자유 블록의 첫 번째 블록의 주소와 연속된 블록의 계수(count)만 유지하면 보다 효율적이다. 따라서 자유 공간 리스트의 각 항은 하나의 디스크 주소와 블록의 개수로 구성 된다.

 

[참고자료]

Operating System Concepts / 홍릉과학출판사

 

49_파일 할당 방법 (Allocation Method)

 

디스크의 직접 접근 특성이 파일의 구현에 융통성을 허용한다. 거의 모든 경우에 하나의 디스크에 여러 파일이 저장되며 이 파일들을 어떻게 디스크 공간에 배치해야 효율적으로 사용할 수 있을지 고민하게 된다. 디스크 공간을 할당 방법과 특성을 살펴 보자.

 

[연속 할당 (Contiguous Allocation)]

연속 할당은 각 파일이 디스크 내에서 연속적인 공간을 차지하도록 요구 한다. 디스크 주소들은 디스크 상에서 선형 순서를 정의 한다. 이러한 순서를 따를 경우 단지 한 작업(job)이 디스크에 접근 한다고 가정하고 블록 b 다음에 블록 b+1을 접근 한다면 통상 헤드의 이동을 요하지 않는다. 헤드의 이동이 필요한 경우는 다음 섹터의 이동할 경우 이다.

 

한 파일의 연속 할당은 디스크 주소와(블록 단위의) 길이로 정의 된다. 파일의 길이가 n블록이고 블록 b에서 시작한다면 이 파일은 블록 b, b+1, b+2 … b+n-1을 차지한다. 각 파일을 위한 디렉토리 항목은 이 파일의 디스크 내 시작 블록 주소와 이 파일의 크기만 표시하면 된다.

 

 

연속적으로 할당된 파일의 접근은 쉽다. 가장 최근 참조된 주소를 기억하고 있다가 필요할 때 다음 블록을 읽어 들이면 된다. 그러나 연속 할당 기법에서 가장 큰 문제는 새로운 파일을 위한 가용 공간을 찾는 일이다. 자유 공간(free space)을 관리하기 위해 선택된 시스템이 이 작업을 담당한다.

 

연속 할당 문제는 일반적인 동적 공간 할당 문제(dynamic storage allocation problem)의 특정 응용으로 볼 수 있다. 이 문제는 자유 공간 (free hole)의 리스트에서 크기 n의 공간을 할당하는 방법에 관한 것이다. 최초 적합(first fit)과 최적 적합(best fit)이 가용 공간 중에서 할당할 공간을 선택하는 가장 일반적인 전략이다. 연속 할당 방법은 모두 외부 단편화(external fragmentation)문제가 발생 한다.

 

연속 할당의 또 다른 문제점은 파일을 위해서 얼마나 많은 공간을 주어야 할지를 결정하는 것이다. 파일이 생성될 때 필요한 공간의 크기를 알아야만 할당 가능하다. 기존의 파일을 복사하는 경우를 제외하곤 파일의 크기를 예측하는 것은 어렵다.

공간을 너무 작게 예약하여 사용하는 경우 파일이 커졌을 때 앞뒤로 다른 데이터로 인해 확장 할 수가 없다. 한 파일에 대한 공간을 미리 알 수 있다고 해도 선할당은 비효율 적이다. 내부 단편화가로 낭비 될 수 있기 때문이다.

 

이러한 단점을 보완하기 위해 많은 운영체제는 어느 정도의 연속된 공간만 초기에 할당하고 그 양이 충분히 크지 않을 때는 추후 n개의 연속된 공간을 단위(extent)로 할당한다. 파일 블록들의 위치는 위치와 블록 수, 다음 단위의 첫 블록에 대한 포인터로 기록된다.

 

 

[연결 할당 (Linked Allocation)]

연결 할당은 연속 할당의 모든 문제를 해결 한다. 연결 할당에서 각 파일은 디스크 블록의 연결 리스트이다. 파일의 디스크 블록들이 디스크 내에 흩어져 있다. 그리고 디렉토리는 파일의 첫 번째와 마지막 블록에 대한 포인터를 가지고 있다.

 

새 파일을 생성하려면 단순히 디렉토리 내의 새로운 항목(entry)을 만든다. 연결 할당의 경우 각 디렉토리 항목은 파일의 첫 디스크 블록에 대한 포인터를 갖고 있다. 이 포인터는 처음에는 빈 파일을 표시하기 위해 nil(연결의 끝에 해당하는 포인터 값) 값으로 초기화된다. 파일 쓰기가 일어나면 자유 공간 관리 시스템은 자유 블록을 할당받아 쓰기를 실행 한 후 파일의 끝에 연결 한다.

 

 

연결 할당의 경우 외부 단편화가 없고 모든 블록들은 크기가 같기 때문에 자유 공간 리스트의 어떠한 자유 블록들을 이용하여도 무방하다. 파일의 크기가 미리 고정될 필요도 없다. 파일은 계속해서 커질 수 있으며 주기적으로 밀집화 할 필요도 없다.

 

하지만 단점도 존재한다. 가장 중요한 단점은 순차적 접근 파일에만 효과적이다. 포인터를 접근할 때마다 디스크 읽기와 몇 번의 탐색이 필요하므로 직접 접근에는 비효율 적이다. 그리고 포인터를 관리하기 위한 추가 공간이 필요하다. 이 문제를 일반적인 해결방법은 블록들을 클러스터(cluster)로 구성하여 클러스터 단위로 할당하는 것이다.

 

또 다른 문제는 신뢰성의 문제인데 포인터를 이용하여 관리하다 보니 포인터를 잃어버리거나 잘못된 포인터 주소를 가지게 되면 결국 모든 자료를 잃게 된다. 이 경우 이중 연결 리스트를 사용하거나 각 블록마다 파일 이름과 상대 블록 번호 등을 저장하는 방법을 같이 쓸 수도 있겠으나 이 기법들은 더 많은 오버헤드를 유발한다.

 

연결 할당의 변형으로 파일 할당 테이블(file Allocation Table, FAT)을 사용하는 것이다. FAT 테이블은 각 디스크 블록마다 한 개의 항목을 가지고 있고 이 항목은 디스크 블록 번호를 색인으로 찾는다.

 

FAT 할당 기법은 FAT가 캐시되지 않으면 상당한 수의 디스크 찾기를 유발 할 수 있다. FAT를 읽기 위해 디스크 헤드를 반드시 파티션의 시작 부분으로 움직여 찾고자 하는 블록의 주소를 알아내야 하고 이어 그 블록이 있는 곳으로 다시 이동해야 한다. 최악의 경우 각 블록을 찾을 때마다 두 번의 이동이 일어나야 한다. 장점은 디스크헤드가 FAT의 정보를 읽어 임의의 블록의 위치를 알아 낼 수 있기 때문에 임의(random) 접근 시간이 개선된다.

 

 

[색인 할당 (Indexed Allocation)]

연결 할당은 연속 할당의 외부 단편화 문제와 파일 크기 문제를 해결하였지만 FAT가 없으면 직접 접근 방식을 지원 할 수가 없다. 색인 할당은 모든 포인터들을 하나의 장소 즉, 색인 블록으로 관리함으로써 이 문제를 해결 한다.

 

각 파일들은 디스크 블록 주소를 모아 놓은 배열인 색인(index) 블록을 가진다. 색인 블록의 i번째 항목은 파일의 i번째 블록을 가리킨다. 디렉토리는 색인 블록의 주소를 가지고 있다. i번째 블록을 읽기 위해서는 색인 블록 항목에 있는 i번째 항목에서 포인터를 얻어서 그 블록을 읽는다. 이 기법은 페이징과 유사하다.

 

 

색인 할당은 추가 공간 요구가 있을 경우 디스크 상의 임의의 자유 공간을 사용할 수 있기 때문에 외부 단편화 없이 직접 접근을 제공 한다. 그러나 색인 할당은 공간의 낭비가 문제이다. 색인 블록의 포인터 오버헤드는 일반적으로 연결 할당의 포인터 오버헤드 보다 크다. 대부분의 파일들은 작으므로 파일들이 대부분 하나 또는 두 개의 블록만으로 구성되어 있는 것이 일반적이다. 이 경우 단지 한 두개의 포인터만 사용되지만 색인을 위해 한 블록이 할당되어야 한다.

 

여기에서는 색인 블록이 얼마나 커야 하는지가 문제 된다. 각 파일들은 하나의 색인 블록을 가지므로 색인 블록의 크기는 가능한 작은 것이 좋다. 만약 색인 블록이 너무 작다면 큰 파일들에 대해서 충분한 공간을 가질 수가 없을 것이다.

 

이러한 문제점을 보완하는 기법은 다음과 같다.

  • 연결 기법(Linked scheme) : 하나의 색인 블록은 통상 한 디스크 블록이다. 파일의 크기가 크면 여러 개의 색인 블록들을 연결 시킨다.
  • 다단계 색인(Multilevel index) : 첫 번째 수준의 색인 블록은 여러 개의 두 번째 수준 색인 블록들에 대한 포인터들을 가진다. 두 번째 수준의 색인 블록은 실제 자료 블록들을 가리킨다. 이러한 방법은 파일의 크기에 따라 세 번째 또는 네 번째 수준으로까지 계속 된다. 한 블록의 크기가 4096 바이트라면 1024개의 4바이트 포인터를 한 색인 블록에서 저장할 수 있다, 2단계 색인 기법을 쓰면 1048576개의 자료 블록을 가질 수 있으며 이는 파일 크기 4GB까지 저장 가능하다.
  • 결합 기법(Combined scheme) : 디렉토리 내의 색인 블록이 15개의 포인터를 갖는다. 이 포인터들의 처음 12개는 직접 블록(direct block)을 가리킨다. 그 다음 3개의 포인터는 간접 블록(indirect block)의 주소로서 첫 번째 포인터는 단일 간접 블록(single-level indirect block)을 통하여 간접적으로 파일의 블록을 찾을 수 있으며 두 번째 포인터는 이중 간접 블록 (double-level indirect block), 마지막 포인터는 삼중 간접 블록(triple indirect block)을 통하여 간접적으로 파일의 블록을 찾는 형식이다. 이는 다단계 색인 기법을 확장한 것이다.

 

색인 할당 기법은 연결 할당과 동일한 성능 문제를 갖는다. 특히 색인 블록은 메모리에 캐시될 수 있지만 자료 블록은 전체 볼륨 파티션 전체에 널리 퍼져 있을 수 있다.

 

 

[참고자료]

Operating System Concepts / 홍릉과학출판사

 

 

48_디렉토리 구현 (Directory Implementation)

 

디렉토리를 구현하는 공간을 어떻게 할당하고 관리하는가? 파일 시스템의 효율, 성능과 이들 알고리즘 장단점을 알아 보자.

 

[선형 리스트 (Linear List)]

디렉토리를 구현하는 가장 간단한 방법은 파일 이름과 자료 블록에 대한 포인터들의 선형 리스트를 디렉토리에 사용하는 것이다.

 

선형 리스트는 프로그래밍이 쉽지만 실행 시간이 길다. 새로운 파일을 생성하기 위해 먼저 디렉토리를 탐색하여 같은 이름의 존재 여부 확인 후 끝 부분에 새로운 항목을 첨가한다. 파일을 삭제 하려면 디렉토리에서 이름을 찾아 그 파일에 할당된 공간을 방출 한다. 파일 삭제 시간을 줄이기 위해 연결리스트를 사용할 수도 있다.

 

 

디렉토리 항목을 다시 사용하기 위해서는 몇 가지 방법이 있다.

  • 비어있는 항목에 특별한 이름을 부여하거나 각 항목에서 사용되지 않는 비트를 이용하여 비었음이라고 표시
  • 비어 있는 항목을 자유 디렉토리 항목의 리스트에 기록
  • 자유화된 항목에 제일 마지막 항목을 복사해 넣고 디렉토리의 길이를 하나 줄이는 방법

 

선형 리스트로 구성된 가장 큰 단점은 파일을 찾기 위해 선형 탐색을 해야 한다는 것이다. 이는 빈번한 사용으로 인하여 사용자가 체감으로 느낄 정도로 오버헤드가 많다. 최근 많은 운영체제들은 가장 최근에 사용된 디렉토리 정보를 저장하기 위해 소프트웨어 캐시를 구현하여 사용하여 매번 디스크로부터 읽어오는 오버헤드를 감소 시킨다.

 

정렬된 리스트는 이진 탐색을 가능하게 하며 평균 탐색 시간을 줄인다. 그렇지만 리스트가 정렬 상태를 유지하려면 파일을 생성하거나 삭제하는 일이 복잡해 질 수 있다. 정렬을 위해 많은 데이터가 이동할 수도 있기 때문이다. 하지만 정렬된 리스트는 별도의 정렬 작업 없이 정렬된 리스트를 생산할 수 있다.

 

 

[해시 테이블 (Hash Table)]

디렉토리 구조로 해싱 테이블을 사용하기도 한다. 선형 리스트에 디렉토리 항목들이 저장되기는 하지만 해싱(hashing)도 함께 사용한다. 파일 이름을 제시하면 해시로부터 값을 얻어서 그것을 포인터로 활용하여 리스트에 직접 접근할 수 있다. 따라서 디렉토리 탐색 시간을 상당히 개선할 수 있다.

 

 

충돌(collision)에 대한 부분만 보완되면 삽입 삭제도 쉽게 할 수 있다. 해싱 테이블의 가장 큰 단점은 해시 테이블이 고정된 크기를 갖는다는 것이다. 이는 해시 테이블의 크기에 따라 해시 기능도 제한을 받는다.

 

예를 들어 64개의 항목을 갖는 선형 탐사(probing) 해시 테이블을 만든다고 하였을 때 나중에 65번째 파일을 생성하려면 디렉토리 해시 테이블을 키워야 한다. 그 경우 파일 이름을 0~127까지 매핑하는 새로운 해시 함수를 필요로 한다. 이때 기존 디렉토리를 새로운 해시 값에 맞게 다시 매핑 해야 하는 문제가 발생한다.

 

해시테이블의 제한을 개선하기 위하여 체인 오버플로우 해시 함수 테이블을 사용할 수 있다. 각 해시 항목은 하나의 값이 아니라 연결 리스트가 되고 새로운 항목을 연결 리스트에 추가함으로써 충돌을 해결한다. 이제 이름을 찾으려면 충돌하는 테이블 항들의 연결 리스트를 살펴보아야 하기 때문에 상대적으로 늦어지겠지만 이러한 연산은 전체 디렉토리를 선형으로 찾는 것보다 훨씬 빠르다.

 

[참고자료]

Operating System Concepts / 홍릉과학출판사

 

 

 

47_파일 시스템 구현 (File System Implementation)

 

운영체제는 파일에 접근을 요구하는 프로세스를 위해 open(), close() 시스템 호출을 구현하며 디스크와 메모리 상에 존재하는 여러 구조가 파일 시스템을 구현하는데 사용된다.

디스크상의 구조는 다음과 같다.

  • 부트 제어 블록(boot control block) : 볼륨 당 하나씩 존재하며 시스템이 그 파티션으로부터 운영체제를 부트 시키는 데 필요한 정보를 가지고 있다. 디스크가 운영체제를 가지고 있지 않다면 부트 제어 블록은 비어 있다. 부트 제어 블록은 일반적으로 한 파티션의 첫 번째 블록이다. UFS에서는 부트 블록, NTFS에서는 파티션 부트 섹터라 불린다.
  • 볼륨 제어 블록 (volume control block) : 볼륨 당 존재하여 볼륨(파티션)의 블록의 수, 블록의 크기, 자유 블록의 수와 포인터, 자유 FCB와 포인터 같은 파티션 정보를 포함 한다. UFS에서는 수퍼블록, NTFS에서는 마스터 파일 테이블에 정보가 저장된다.
  • 디렉토리 구조는 파일을 조직화 하는데 사용된다. UFS에서는 디렉토리 구조에 파일 이름 및 해당 inode 번호가 저장된다. NTFS에서는 마스터 파일 테이블에 이러한 정보가 저장된다.
  • FCB는 파일 허가, 소유, 크기, 자료 블록의 위치 등을 포함하여 자세한 파일 정보를 가지고 있다. UFS에서 이는 inode라 불린다. NTFS에서 이 정보는 실제적으로 마스터 파일 테이블 안에 저장되며 파일마다 한 행을 가지고 관계 데이터베이스 구조를 사용한다.

 

메모리 내의 정보는 파일 시스템 관리와 캐싱을 통한 성능 향상을 위해 사용된다.

  • 메모리 내 파티션 테이블은 각 장착된 파티션 정보를 포함한다.
  • 메모리 내 디렉토리 구조는 최근 접근된 디렉토리 정보를 가진다.(파티션이 장착된 디렉토리의 경우는 파티션 테이블에 대한 포인터를 포함할 수 있다.)
  • 범 시스템 오픈 파일 테이블(system wide open file table)은 다른 정보와 더불어 열려진 각 파일의 FCB의 복사본을 가진다.
  • 프로세스 별 오픈 파일 테이블(per-process open file table)은 다른 정보 뿐만 아니라 범 시스템 오픈 파일 테이블 내의 해당 항목에 대한 포인터를 포함한다.

 

새로운 파일을 생성하기 위해서는 논리 파일 시스템을 호출 한다. 논리 파일 시스템은 디렉토리 구조의 포맷을 알고 있으며 일단 새로운 파일이 생성되면 입/출력을 위해 사용된다.

 

파일을 사용하려면 파일이 반드시 열려야 하며 open() 호출은 파일 시스템에 파일 이름을 넘겨준다. open() 시스템 호출은 먼저 그 파일이 다른 프로세스에 사용중인지 범 시스템 오픈 파일 테이블을 찾으며 이 알고리즘은 오버헤드를 줄이는데 도움이 된다. 또한 디렉토리 연산의 속도를 향상 시키기 위해 통상 디렉토리 구조의 일부는 메모리에 캐싱한다.

 

파일이 발견되면 FCB가 메모리 내의 범 시스템 오픈 파일 테이블에 복사된다. 이 테이블은 FCB와 프로세스의 수도 저장한다. 범 시스템 오픈 파일 테이블 안에는 테이블의 항목에 대한 포인터와 몇 개의 다른 필드를 갖는 프로세스별 항목이 만들어 진다. 이 필드들은 파일 안의 현재 위치(다음 read() 또는 write() 연산이 시작되는 위치)를 가리키는 포인터와 파일이 열린 접근 모드 등을 포함 한다.

 

Open() 호출은 프로세스 별 파일 시스템 테이블 내의 해당 항목에 대한 포인터를 찾아 돌려준다. 그 후 모든 파일 연산은 이 포인터를 통해 실행 된다. 일단 해당 FCB를 디스크에서 찾으면 시스템은 파일 이름을 더 이상 사용하지 않기 때문에 파일 이름은 오픈 파일 테이블의 한 부분이 아니다. 그러나 같은 파일에 대한 차후 open() 연산을 빠르게 하기 위해 캐시될 수 있다. 유닉스에서는 파일 기술자라 부르고 Windows에서는 파일 핸들이라 부른다.

 

파일을 닫지 않는 이상 모든 파일 연산은 오픈 파일 테이블에서 이루어진다. 프로세스가 파일을 닫을 때 프로세스 별 테이블 항목이 삭제되며 범 시스템 항목의 오픈 계수는 감소 된다. 사용자가 열었던 모든 파일을 닫으면 갱신된 메타데이터 정보가 디스크 기반 디렉토리 구조에 복사되며 범 시스템 오픈 파일 테이블에서 그 항목이 삭제 된다.

 

이런 구조들은 캐싱 기법을 사용함으로써 실제 자료 블록을 제외한 오픈 파일에 대한 모든 정보는 메모리 내에 존재 한다. 디스크 입/출력 작업을 줄일 수 있다.

 

 

사용자는 지역 디스크의 여러 파일 시스템이나 네트워크를 통하여 이용 가능한 파일 시스템에 접근할 수 있다. 구현 세부 사항으로부터 기본 시스템 호출 기능을 격리시키기 위해 자료 구조와 프로시저가 사용 된다. 일반적으로 파일 시스템 인터페이스, VFS 인터페이스, 지역 파일 시스템 으로 세 가지 주요한 계층으로 구성되어 있다.

 

파일 시스템 인터페이스는 open(), read(), write(), close() 호출과 파일 기술자에 기반을 둔 인터페이스이다.

가상 파일 시스템(VFS, Virtual File System)은 VFS 인터페이스를 명확하게 정의함으로써 파일 시스템의 일반적 연산을 구현과 분리 시킨다. VFS 인터페이스에 대한 다른 구현들이 같은 기계 상에 공존할 수 있으므로 다른 형태의 파일 시스템을 지역적으로 장착함으로써 투명한 접근을 가능하게 한다. 또한 전체 네트워크에 걸쳐 파일을 유일하게 표시할 수 있는 기법을 제공한다. vnode라는 전체 네트워크에서 파일을 유일하게 만들어주는 수치 지정자(designator)를 포함하고고 있다. VFS는 특정 파일 시스템 고유의 연산을 활성화시킴으로써 파일 시스템 유형에 따른 지역 요청들을 처리하며 원격 요청에 대해서는 NFS 프로토콜 프로시저를 호출 한다. 파일 핸들은 연관된 vnode들로부터 구성되며 이들 프로시저에 매개변수로 전달 된다.

 

 

 

[참고자료]

Operating System Concepts / 홍릉과학출판사

 

 

 

46_파일 시스템 구조 (File System Structure)

 

디스크는 여러 개의 파일을 저장하는데 다음 두 가지 중요한 특성을 가지고 있다.

  1. 디스크는 추가 장소를 사용하지 않고 재기록이 가능하다. 디스크로부터 한 블록을 읽고 변경하여 같은 장소에 재기록이 가능하다.
  2. 디스크에 있는 임의의 블록의 정보를 직접 접근 할 수 있다. 따라서 임의의 파일을 순차적 또는 무작위 방법으로 쉽게 접근 할 수 있다. 그리고 한 파일로부터 다른 파일로 전환이 요구 될 때 읽기-쓰기 헤드를 이동시키고 디스크가 회전하는 동안 기다리면 된다.

 

디스크는 한 번에 한 바이트를 전송하는 대신 입/출력 효율을 향상시키기 위해 메모리와 디스크간의 입/출력 전송은 블록 단위로 실행 된다. 각 블록은 하나 이상의 섹터이다. 디스크 드라이브에 따라 섹터는 32바이트 ~ 4096 바이트 까지 사용하지만 일반적으로 512 바이트를 사용한다.

 

디스크를 보다 효율적이고 편리하게 사용하기 위해서 운영체제는 디스크 내에 반드시 하나 이상의 파일 시스템을 구성한다. 파일 시스템은 크게 상이한 두 가지의 설계 문제를 제기한다.

  1. 파일 시스템이 사용자에게 어떻게 보여야 할지를 정의하는 것이다. 속성, 디렉토리 구조, 파일에 허용되는 연산 등을 포함한다.
  2. 논리 파일 시스템을 물리적인 보조 저장 장치로 매핑하는 알고리즘과 자료 구조를 만드는 것

 

파일 시스템 자체는 통상 여러 수준으로 구성 된다. 각 수준은 저수준의 기능을 이용하여 고수준을 위한 새 기능을 구현 한다.

 

 

 

  1. 장치 드라이버(device driver) : 최저 수준인 입/출력 제어(I/O Control) 루틴들과 인터럽트 핸들러로 이루어져 있으며 메모리와 디스크 시스템간의 정보 전송을 담당.
  2. 기본 파일 시스템(basic file system) : 적절한 장치 드라이브에게 디스크 상의 물리 블록을 읽고 쓰도록 일반적인 명령을 내린다. 각 디스크 블록은 숫자로 표시된 디스크 주소에 의하여 식별 된다.
  3. 파일 구성 모듈(file organization module) : 파일의 논리 블록과 물리 블록들 양쪽을 알고 있어야 하며 사용되는 파일 구성 모듈은 파일 할당 유형과 파일의 위치를 앎으로써 파일에 대한 논리 블록 주소를 물리 블록 주소로 변환할 수 있다. 파일 구성 모듈은 어느 디스크 공간이 비어 있는지를 파악하는 자유 공간 관리자도 포함하고 있어 파일 구성 모듈이 요구 할 때 이들 블록을 제공 한다.
  4. 논리 파일 시스템(logical file system) : 메타데이터 정보를 관리한다. 메타데이터는 파일의 내용 자체인 자료를 제외한 모든 파일 시스템 구조를 말한다. 파일 구조는 파일 제어 블록(FCB)을 통해 유지 된다. FCB는 소유, 허가, 파일 내용의 위치를 포함하여 파일에 관한 정보를 가지고 있다.

 

오늘날에는 많은 파일 시스템이 구현되어 있다. CD-ROM의 경우에는 High Sierra 포맷을 사용하고 UNIX는 기본으로 UFS(Unix File System), Windows 계열에는 FAT, FAT32, NTFS 포맷을 지원한다.

 

 

[참고자료]

Operating System Concepts / 홍릉과학출판사

 

+ Recent posts