42_파일 개념 (File Concept)
메모리는 통상적으로 프로그램과 자료를 영구 보관하기에는 용량이 작고 비용이 많이 들어가므로 보조 저장 장치를 사용한다. 컴퓨터에 부착되는 보조 저장 장치들은 여러 면에서 서로 다른 특징을 가지고 있으며 접근방법, 전송방법, 전용, 공용 등 다양한 특징이 있다. 또한 현재 컴퓨터의 구성 요소 중에서 가장 속도가 느리다.
운영체제의 입/출력 서브시스템의 중요 목적은 시스템에 대하여 간단한 인터페이스를 제공하고 각 장치들이 성능 병목을 피하기 위해 최대한의 동시성(concurrency)을 확보를 위한 입/출력의 최적화를 이루는 것이다.
파일은 운영체제에 의해서 물리 장치들로 매핑되며 이들 저장 장치들은 일반적으로 비휘발적 성질을 갖기 때문에 전원이 나가거나 시스템이 재부팅되어도 저장된 내용들은 영구 보관 된다.
[파일 개념]
파일은 보조 저장 장치에 기록된 관련 정보의 집합으로 정의할 수 있다. 사용자 관점에서 볼 때 파일은 논리적 보조 저장 장치의 가장 작은 할당 요소이다. 파일 내의 정보는 작성자에 의해 정의되며 다양한 정보들이 파일 내에 저장되고 유형(텍스트, 도형, 이미지 등)에 따라 특별히 정의된 구조를 가진다.
- 소스파일 : 선언문 다음에 실행 문장들로 구성도니 서브루틴이나 함수들의 집합체
- 목적파일 : 시스템의 링커가 인식 가능한 블록으로 구성된 연속된 바이트들의 집합체
[파일의 속성]
사용자의 편의를 위해 파일에 이름을 부여하고 그 이름으로 파일을 참조 한다. 파일은 운영체제마다 다른 속성을 갖지만 대표적으로 다음과 같은 속성을 가지고 있다.
- 이름 : 기호형 파일 이름은 사람이 읽을 수 있는 형태로 유지된 유일한 정보
- 식별자(identifier) : 통상 하나의 숫자로 파일 시스템 내에서 파일을 확인한다. 식별자는 우리가 읽을 수 없는 파일의 이름
- 유형 : 여러 유형을 제공하는 시스템을 위해 필요
- 크기 : 파일의 현재 크기(바이트, 워드, 블록 등)와 최대 허용크기가 이 속성에 포함
- 보호 : 접근 제어 정보는 읽기, 쓰기, 실행 등을 할 수 있는가를 제어
모든 파일에 대한 정보는 보조 저장장치에 상주하는 디렉토리 구조에 의해서 유지 된다. 각 파일에 대하여 관련된 정보를 기록하기 위해서는 1KB 이상 필요할 수도 있다. 많은 파일을 가지고 있는 시스템에서는 디렉토리 그 자체만해도 수 메가바이트가 된다. 파일처럼 디렉토리도 비휘발성을 가져야 하므로 저장 장치상에 저장되어야 하고 필요할 때마다 메모리로 조금씩 가져오도록 해야 한다.
[파일 연산]
파일이란 추상적인 데이터 유형이다. 파일을 적절히 정의하기 위해 파일에 대해 실행할 수 있는 연산들을 고려해 볼 필요가 있다.
- 파일 생성 : 두 단계가 필요 하다. 파일을 저장할 수 있도록 파일 시스템 내에서 공간을 찾는다. 새로 생성된 파일에 대한 항목이 디렉토리에 만들어져야 한다.
- 파일 쓰기 : 파일 이름과 파일에 기록될 정보를 명시하는 시스템 호출을 실행 한다. 파일 이름이 주어지면 시스템은 파일의 위치를 알아내기 위해 디렉터리를 탐색한다. 시스템은 파일 내의 다음 쓰기가 일어날 위치를 가리키는 쓰기 포인터(write point)를 유지하고 있어야 한다. 쓰기 포인터는 쓰기가 일어날 때마다 갱신되어야 한다.
- 파일 읽기 : 파일의 이름과 파일이 읽혀져야 할 블록의 위치(메모리내)를 기술하는 시스템 호출을 사용한다. 파일안의 위치를 가리키기 위한 읽기 포인터(read point)를 유지할 필요가 있다. 프로세스는 일반적으로 읽기나 파일 쓰기 중 하나를 하고 있기 때문에 대부분의 시스템은 하나의 현재 파일 위치 포인터(current file position pointer)를 가진다.
- 파일 안의 위치 재설정(reposition) : 현재 파일의 위치를 주어진 값으로 설정 한다. 파일 내에서 위치를 재설정 해도 실제로 입/출력을 할 필요는 없으며 이 파일 연산은 파일 탐색(seek)으로도 알려져 있다.
- 파일 절단 : 사용자가 파일의 내용은 지우고 그 파일의 속성은 그대로 남기기를 원할 때 사용. 파일을 삭제하고 재생성 하는 것이 아니라 파일의 길이를 제외한 모든 속성은 그대로 유지되게 한다. 파일의 길이가 0으로 재설정 되며 파일이 가지고 있던 공간은 해제 된다.
대부분의 파일 연산들은 지명된 파일과 관련된 디렉토리를 찾는 작업을 한다. 이러한 반복적인 탐색을 피하기 위해서 열린 파일에 대한 정보를 갖는 오픈 파일 테이블(open file table)을 유지 한다. 임의의 파일 연산이 요구되면 이 테이블에 대한 색인으로 그 파일을 지정하므로 어떠한 탐색도 필요하지 않다.
실제로 파일이 더 이상 사용되지 않으면 프로세스에 의해 닫히고 운영체제는 오픈 파일 테이블에 있는 항목을 제거한다. Create와 delete는 열린 파일이 아니라 닫힌 파일에 대해 동작한 시스템 호출이다.
일부 시스템은 파일에 대한 첫 번째 참조가 이루어질 때 파일을 암묵적으로 연다. 이 파일은 자신을 연 작업이나 프로그램이 종료되면 자동적으로 닫힌다.
[오픈파일과 관련된 정보]
- 파일 포인터 : read()와 write() 시스템 호출의 일부분으로 파일 오프셋(offset)을 포함하지 않는 시스템은 현재 파일 위치 포인터로 가장 최근의 읽기/쓰기 위치를 추적해야 한다. 이 포인터는 파일 연산을 수행하는 각 프로세스에 대해 유일하게 하나씩 만들어지므로 디스크 상의 파일 속성들과는 분리되어 유지되어야 한다.
- 파일 오픈 계수 : 파일이 닫히면 운영 체제는 오픈 파일 테이블의 항목들을 재사용해야 한다. 아니면 테이블 공간이 모자라게 될 것이다. 이 계수는 파일의 총 열기와 닫기를 추적하며 이 계수 값이 0에 도달하면 시스템은 항목을 제거할 수 있다.
- 파일의 디스크 위치 : 대부분의 파일 연산들은 시스템에게 파일 내의 자료를 변경하도록 요구한다. 디스크 상의 파일의 위치를 찾기 위한 정보는 매 연산마다 디스크에서 읽는 것을 피하기 위해 메모리에 저장 된다.
- 접근 권한: 각 프로세스는 한 파일을 하나의 접근모드로 연다. 이 정보는 프로세스 별 테이블에 저장되며 운영체제는 이 정보를 후속 요구를 허용하거나 불허하는데 사용할 수 있다.
일부 운영체제는 열려진 파일을 잠금 할 수 있는 기능을 제공한다. 파일 잠금은 하나의 프로세스가 파일을 잠그고 다른 프로세스들이 그것에 대한 접근 하는 것을 막는데 사용될 수 있다.
잠금에는 여러 프로세스가 동시에 잠금을 획득할 수 있는 공유(shared lock) 잠금과 한 번에 한 프로세스만 접근할 수 있는 베타적인 잠금(exclusive lock)이 있다. 또한 운영체제는 강제적(mandatory)또는 권고적(advisory) 파일 잠금 방법을 제공할 수도 있다.
Windows 운영체제는 강제적 잠금을, Unix 운영체제는 권고적 잠금을 채택하고 있다.
[파일 구조 (File Structure)]
파일의 유형을 사용하여 파일의 내부 구조 형태를 짐작할 수 있다. 각각의 파일들은 그 파일을 다루는 프로그램에 의해 인식 가능한 내부 구조를 일정한 형태로 가지게 된다. 어던 파일들의 경우에는 운영체제가 인식할 수 있도록 미리 정해진 구조를 따라야 할 때도 있다.
운영체제가 여러 파일 구조를 지원하는 경우에 발생 가능한 단점으로는 운영체제의 크기가 증가한다는 점이다. 예를 들어 운영체제가 다섯 가지의 다른 파일 구조를 지원한다면 그러한 파일 구조를 지원하기 위한 코드가 부가적으로 필요하며 또한 모든 파일은 운영체제에서 지원하는 파일 유형 중 하나로만 정의되어야 한다.
어떤 운영체제는 파일 형태, 구조에 대하여 제한을 거의 두지 않는다. 이렇게 되면 시스템은 어떠한 목적으로나 자유롭게 파일들을 사용할 수 있게 되며 유연성은 극대화 된다. 대신 시스템 차원에서의 파일 유형 지원은 상대적으로 적다.
너무 적은 파일 구조 지원은 프로그래밍을 매우 불편하게 할 수도 있으며 너무 많은 파일 유형을 지원하는 경우는 운영체제의 덩치를 부풀리면서 프로그래머의 혼란을 가중시키는 경향이 있다.
[파일의 내부 구조 (Internal File Structure)]
디스크 시스템은 보통 섹터의 크기에 의해 결정되는 블록 크기를 가진다. 모든 디스크 입/출력은 한 블록 단위로 실행되며 모든 디스크 블록들은 동일한 크기를 가진다. 논리 레코드의 길이는 매우 다양하며 여러 논리 레코드를 하나의 물리 레코드에 팩킹(packing)하는 것이 일반 적이다.
논리 레코드의 크기, 물리 블록 크기 그리고 팩킹 기술은 각 물리 블록 내에 몇 개의 논리 블록이 들어갈지 결정한다. 팩킹은 사용자의 응용프로그램이나 운영체제에 의해 실행된다.
디스크 공간이 항상 블록단위로 할당 되기 때문에 각 파일의 마지막 블록의 일부는 낭비된다. 만일 한 블록이 512byte라면 파일크기가 1949byte일 경우 4블록(4028byte)이 할당되며 마지막 99byte는 낭비 될 것이다. 이렇게 낭비 되는 것을 내부 단편화(internal fragmentation)이라 한다.
모든 파일 시스템은 내부 단편화의 문제를 가지고 있으며 블록 크기가 클수록 내부 단편화가 커진다.
[참고자료]
Operating System Concepts / 홍릉과학출판사
'SW Engineering > OS Concept' 카테고리의 다른 글
44_디렉토리 구조 (Directory Structure) (0) | 2015.07.16 |
---|---|
43_파일 접근 방법 (Access Method) (0) | 2015.07.16 |
41_커널 메모리 할당 (0) | 2015.07.16 |
40_가상 메모리 매핑 파일 (memory Mapped File) (0) | 2015.07.16 |
39_가상 메모리 쓰레싱(Thrashing) (0) | 2015.07.16 |