열렬히.뛰기

1. 파일이란?

운영체제 > part 6 : 파일 시스템 > 공룡책 13장 : 파일 시스템 인터페이스 > 1. 파일이란?

파일이란?

운영체제는 컴퓨터 시스템을 편하게 사용하기 위해

  • 저장된 정보에 대한 일관적인 논리적 관점을 제공하고
  • 저장장치의 물리적 특성을 추상화하여
  • 논리적 저장단위인 파일을 정의한다.

💡 파일은 보조저장장치에 기록된 관련 정보의 집합

  • 파일은 논리적 보조 저장장치의 가장 작은 할당 요소
  • 자료는 파일 안에 존재해야 보조저장장치에 기록될 수 있음
    • 자료의 종류 : 숫자, 문자, 숫자+문자, 이진수
    • 작성자와 사용자에 의해 그 의미가 정의된 비트, 라인, 레코드의 연속
  • 파일의 사용 용도는 다양하다. (유닉스 & 리눅스 ⇒ 시스템 정보에 대한 액세스도 파일로 함)
    • 소스 파일 : 함수들의 연속
    • 실행 파일 : 로더가 메모리로 가지고 와 실행시킬 수 있는 연속된 코드

파일 속성

파일은 무엇으로 이뤄져 있는가?

운영체제마다 다르지만, 크게 다음과 같은 것들로 이뤄진다.

  1. 이름 : 사람이 읽을 수 있는 유일한 정보
  2. 식별자 : 통상 하나의 숫자로, 파일 시스템 내에서 파일을 확인. 사람이 읽을 수 없음.
  3. 유형 : 여러 유형을 제공하는 시스템을 위해 필요
  4. 위치 : 파일이 존재하는 장치와 그 장치 내의 위치에 대한 포인터
  5. 크기 : 파일의 현재 크기와 최대 허용 가능한 크기가 포함
  6. 보호 : 누가 읽기, 쓰기, 실행을 할 수 있는지를 나타냄
  7. 타임스태프와 사용자 식별 : 이 정보는 생성, 최근 변경, 최근 사용 등을 유지하고, 이를 보호, 보안 및 사용자 감시를 위해 사용.

몇몇 새 파일 시스템들은 파일의 문자 인코딩 정보와 파일 체크섬 같은 보안 정보들을 포함해 확장된 파일 속성도 지원.

모든 파일에 대한 정보는 파일 자신과 같은 위치에 상주하는 디렉터리 구조에 의해 유지됨.

  • 디렉터리 항목은 파일의 이름과 고유의 식별자로 구성
  • 식별자는 다시 다른 파일 속성을 찾는데 사용됨.
  • 디렉터리 항목의 크기는 파일마다 다양함
  • 디렉터리는 파일과 같이 장치에 저장 & 필요할 때 조금씩 메모리로 반입됨.

파일 연산

파일 = 추상적인 데이터 유형.

파일의 정의를 위해 파일에 대해 실행할 수 있는 연산을 알아보자.

기본 연산

파일 조작에 필요한 최소 연산 7가지

  1. 파일 생성 : 파일을 생성하려면 2단계의 과정이 필요하다.
    • 파일을 저장할 수 있는 파일 시스템 내 공간이 필요
    • 파일에 대한 항목이 디렉터리에 만들어 져야 함.
  2. 파일 열기
    • 생성과 삭제 전 반드시 파일을 open() 해야 함
    • open() 성공 시 파일 핸들을 반환
  3. 파일 쓰기
    • 열린 파일 핸들과 파일에 기록될 정보가 명시된 시스템 콜을 실행해야 쓰기가 됨
    • 시스템은 다음에 쓸 위치를 가리킬 쓰기 포인터를 유지해야 함
    • 쓰기 포인터는 쓰기가 일어날 때마다 갱신되어야 함.
  4. 파일 읽기
    • 파일을 읽기 위해서는 파일 핸들 & 파일이 읽혀야 할 블록의 위치를 기술하는 시스템 콜
    • 시스템은 다음 읽을 위치를 파악하기 위해 읽기 포인터를 유지할 필요가 있다.
      • 읽기가 발생하면, 읽기 포인터는 갱신 된다.
    • 프로세스는 일반적으로 파일 읽기나 파일 쓰기 중 하나를 하고 있기 때문에, 대부분의 시스템은 현재 파일 위치 포인터를 가진다.
    • 읽기와 쓰기 연산 모두 이 포인터를 사용함으로써 공간을 절약하고 시스템의 복잡성을 감소시킨다.
  5. 파일 안에서의 위치 재설정
    • 일린 파일의 현재 파일의 위치를 주어진 값으로 설정한다.
    • 파일 내에서 위치의 재설정을 위해 실제로 입출력할 필요는 없음.
    • 이 파일 연산은 파일 탐색으로도 알려준다
  6. 파일 삭제
    • 파일을 삭제하기 위해 지정된 파일을 디렉토리에서 찾는다.
    • 모든 파일 공간을 해제, 디렉터리 항목을 지우거나 사용 가능으로 표기.
  7. 파일 절단
    • 파일의 길이를 0으로 재설정 & 파일이 가지고 있던 공간을 해제
    • 사용자가 파일의 내용은 지우고 다만 그 파일은 속성은 그대로 남기기를 원할 때 사용.

이외의 자주 쓰이는 연산은 다음과 같다.

  • 새로운 정보를 기본 파일 끝에 첨가.
  • 이름을 바꾸는 연산

이러한 연산들은 다른 파일 조작 연산을 실행하기 위해 결합할 수도 있다.

  • ex. 새 파일 생성 & 기존 파일을 읽어 새 파일에 기록해 파일의 복사본 생성

또한 사용자가 파일의 다양한 속성을 획득하고 설정할 수 있는 연산을 가진다.

  • ex. 파일 길이와 같은 파일 상태로 결정할 수 있는 연산
  • ex. 파일의 소유자와 같은 파일의 속성을 설정할 수 있는 연산

파일 테이블

대부분의 파일 연산 = 지명된 파일과 관련된 디렉터리 검사 작업이 필요.

반복적인 탐색을 피하기 위해서 운영체제는 open() 이후 파일 테이블을 유지

  • 파일 테이블의 인덱스 ⇒ 파일을 가리킴. 따라서 탐색이 필요 없음.
  • 사용되지 않으면 프로세스에 의해 닫힘.
    • 운영체제는 열린 파일 테이블에 있는 항목을 제거
    • 락을 해제하게 됨.
  • create()와 delete()가 열린 파일보다는 닫힌 파일을 대상으로 동작하는 대표적인 시스템 콜

대부분의 시스템은 암묵적으로 파일이 사용되기 전에 먼저 open()을 해줘야 한다.

open() 연산은 파일 이름을 취하여 그 파일 이름으로 디렉터리를 찾고 디렉터리 항목을 열린 파일의 테이블로 복사함.

open() 시스템 콜은 젭근 모드 정보를 받을 수 있음. (O_RDONLY, O_WDONLY 등등)

  • 요구된 모드가 허용된다면 해당 프로세스를 위해 파일을 열어 줌
  • 반환값 : 열린 파일 테이블 항목에 대한 포인터
    • 이를 통해 추가적인 탐색 과정을 피하고, 시스템 콜 인터페이스를 단순화한다.

열린 파일

여러 프로세스가 동시에 여러 파일을 열 수 있는 환경에서의 open()과 close()는 더 복잡하다.

  • ex. 여러 프로세스가 동시에 같은 파일을 연다면?

보통 운영체제는 두 단계의 내부 테이블을 사용

  1. 프로세스별 테이블 : 각 프로세스가 연 모든 파일을 기록
    • 즉 프로세스가 어떻게 파일을 쓰는지 나타내는 기록장
    • 각 파일에 대한 현재 파일 포인터가 있음.
    • 다음에 수행될 읽기/쓰기 함수가 영향을 미칠 파일의 위치도 나타냄
    • 접근 권한 & 회계 정보도 포함 가능.
  2. 범 시스템 테이블
    • 프로세스별 테이블의 각 항목은 범 시스템 테이블을 가리킴
    • 프로세스에 독립된 정보를 가짐
    • ex. 파일을 연 프로세스 수 = 열린 계수
      • close()는 이를 감소시킴
      • 만약 계수가 0이면, 열린 파일 테이블에서 제거

열린 파일에 대한 추가적인 정보는 다음과 같다.

  • 파일 포인터 : 읽기와 쓰기 시스템 콜의 일부분으로써 offset을 가지지 않은 시스템은 현재 파일 위치 포인터로써 가장 최근의 읽기/쓰기 위치를 추적해야 함.
    • 이 포인터는 파일 연산을 수행하는 각 프로세스에 대해 유일하게 1개씩 만들어짐
    • 따라서 디스크 상의 파일 속성들과는 분리되어 유지되어야 함.
  • 파일 열린 계수
    • 파일이 닫히면 운영체제는 열린 파일 테이블 항목들을 재사용해야 함.
    • 아니면 테이블의 공간이 모자를 수 있음
    • 여러 프로세스가 파일을 열 수 있기 때문에, 시스템은 열린 테이블 항목을 제거하기 전에 마지막 파일이 닫히기 까지 기다려야 함
    • 계수 값이 0에 도달했을 때, 시스템은 항목을 제거할 수 있음.
  • 파일의 위치 : 파일의 위치를 찾기 위한 정보는 메모리에 저장됨.
    • 연산마다 디렉터리 구조에서 읽는 것을 피하기 위해서
  • 접근 권한 : 각 프로세스는 한 파일을 하나의 접근 모드로 염
    • 이 정보는 프로세스별 테이블에 저장
    • 운영체제는 이 정보를 후속 요구를 허용하거나 불허하는데 사용할 수 있음.

파일 락

몇몇 운영체제는 열린 파일을 락킹할 수 있는 기능을 제공.

💡 파일 락 : 하나의 프로세스가 다른 프로세스가 파일에 접근하는 것을 막기 위해 이를 잠그는 것.

파일에 관해 프로세스의 읽기-쓰기 락과 비슷한 기능을 가졌다고 생각하면 된다.

대표적인 락의 예시는 다음과 같으며, 운영체제는 이 중 일부(또는 전체)를 지원한다.

  • 공유 락 : 여러 프로세스가 동시에 락을 획득 (프로세스의 읽기 락과 비슷)
  • 베타적 락 : 한 번에 한 프로세스만 락을 획득 (프로세스의 전체 락과 비슷)
  • 강제적 락 : 락의 무결성을 안전하게 보장해줌.
  • 권고적 락 : 락의 획득 & 해제를 개발자가 결정 (유닉스가 채택)

파일 락의 사용은 프로세스 동기화처럼 조심스럽게 이뤄져야 함.

  • 충돌이나 교착상태가 발생할 수 있음.

파일 유형

파일 유형을 통해 운영체제는 파일에 대한 합리적인 연산을 지원할 수 있음.

파일 연산의 유형

모두가 알고 있는 것처럼 보통 이름을 마침표로 구분해 그 뒷부분을 확장자로 쓴다.

  • App은 자신에게 필요한 파일 유형을 나타내기 위해 확장자를 사용함.
  • 다만, 확장자는 필수가 아니며, 따라서 사용자가 확장자 없이 파일을 찾으면 운영체제는 주어진 이름 + 기대하는 확장자를 접목해 제일 그럴 듯 한 것을 찾는다.

macOS

  • 각 파일은 .app과 같은 파일 유형을 가짐
  • 각 파일은 자신을 생성한 프로그램의 이름을 파일의 속성으로 가짐
    • 이러한 속성은 create() 호출 중 운영체제에 의해 설정됨
    • 따라서 사용 시 시스템에 의해 감시되고 유지됨.
  • ex. new.pptx라는 파일이 있을 때
    • creator 속성에서 파워포인트를 가지고 있음
    • 더블 클릭 시 new.pptx 파일을 가진 파워포인트가 시스템에서 실행.

UNIX

  • 파일의 시작 부분에 저장된 매직 넘버를 사용해 파일의 데이터 유형을 나타냄
  • 다만 모든 파일이 매직 넘버를 가지고 있지는 않기 때문에, 시스템의 모든 기능이 매직 넘버에 의존할 순 없음
  • 파일 이름 확장자 힌트를 허락하지만, 운영체제가 이걸 무조건 쓰는 것은 아니다
    • 사용자가 파일에 포함된 콘텐츠 유형을 결정하는 데 도움을 주려는 것.

파일 구조

파일의 유형 = 내부 구조 형태를 짐작 가능.

각각의 파일들은 파일을 다루는 프로그램에 의해 인식 가능한 내부 구조를 일정한 형태로 가지게 됨.

  • 어떠한 파일은 운영체제가 알아볼 수 있도록 미리 정해진 구조를 따라야 함
  • 이를 응용해 운영체제는 특정한 구조에 맞춘 파일을 다루는 연산 기능을 제공하기도 함

운영체제가 여러 파일 구조를 지원하는 경우 단점도 있다.

  • 운영체제의 크기가 커지고, 관리가 힘들어진다
  • 모든 파일이 해당 운영체제의 파일 구조를 따라야만 한다.

그래서 일부 운영체제는 파일 형태나 구조에 제한을 두지 않음.

  • ex. 유닉스 = 파일은 8비트 바이트의 집합
  • 시스템은 어떠한 목적으로든 파일을 사용할 수 있음
  • 시스템 차원에서 파일 유형 지원은 상대적으로 적음
  • 따라서 개발자들이 각자의 App에서 사용되는 파일에 대한 해석과 운영을 해야만 함.
  • 그렇다고 해도, 프로그램을 로딩하고 실행할 수 있는 실행파일의 구조는 반드시 지원해야 함

파일 내부 구조

내부적으로 한 파일 내에 어떠한 위치를 찾는 것은 복잡할 수 있음.

이를 극복하기 위해 운영체제는 다양한 방법을 사용

유닉스에서 모든 파일 = 바이트의 연속된 열

  • 각 바이트의 위치를 오프셋에 의해 설정할 수 있음. (논리 레코드 : 1바이트)
  • 파일 시스템은 자동으로 바이트들을 하나의 물리 블록에 필요에 따라 팩하거나 언팩함

논리 레코드의 크기, 물리 블록 크기, 팩킹 기술은 각 물리 블록 내 몇 개의 논리 블록이 들어갈 지 결정

  • 패킹은 사용자의 App이나 운영체제에 의해 결정됨
  • 어느 경우든 파일은 일련의 블록으로 간주

디스크 공간의 내부 단편화

  • 공간이 항상 블록 단위로 할당
  • 따라서 마지막 블록의 일부가 남을 수 있음
  • 블록 크기가 커질 수록 내부 단편화가 심해짐.