[OS] 파일 시스템 기초, Directories, Pathname Translation, 마운팅, 파일 쉐어링, file locking, 파일 프로텍션 시스템

2024. 6. 8. 22:08CS/Operating System

Basic Concepts

storage 요구사항

  • 매우 컸으면 좋겠다.
  • 프로세스가 디스크를 사용하고 그게 잘 종료되었으면 좋겠다.
  • 여러 프로세스가 동시에 접근할 수 있어야 한다.

파일

  • secondary storage에 기록된 관련된 정보들의 집합이다.
    • 윈도우에서는 확장자가 의미가 있다. exe는 실행 파일, txt는 텍스트 파일 이렇게 되는데 이건 사실 윈도우에서 의미가 있는 것이다. jpg라면 jpg확장자를 보고 jpg 뷰어를 보여주는 것이다.
    • 다른 운영체제는 확장자가 의미가 없다.
  • persistent 해야 한다. power가 꺼지거나 재부팅 해도 유지되어야 한다.
  • OS는 file을 통해 storage를 logical view로 보여주게 된다.

file system

  • storage에 있는 파일을 abstraction으로 구현한 시스템이다.
  • 디렉터리라는 logical 개념으로 파일을 관리한다.
  • 파일시스템이 파일을 다루면서 프로세스나 사람들이나 머신들이 공유할 수 있어야 한다. 내가 만든 파일을 다른 기기가 볼 수 있어야 하고 protection도 필요하다. 다른 사람은 쓸 수 없고 read만 가능하다는 방식처럼 말이다.

storage는 블락 단위로 구성되어 있다. 3번 블락부터 몇 개의 섹터로 read, write 할 수 있고 블락 번호로 식별할 수 있다.

이제 파일이 뭔지, 파일 시스템이 뭔지 자세히 알아보자.


파일 시스템 기초

파일은 다음의 요소들을 가져야 한다.

  • 파일 이름
  • 파일 속성(메타데이터)
    • 파일 사이즈
    • 소유자
    • 생성 시간, 최근 수정된 시간 등등
  • 파일 contents (data)
    • 결국 파일은 0101로 되어있는데 그 데이터가 storage 어딘가에 저장되어있어야 한다.

우리는 파일의 이름을 가지고 엑세스한다.

 

파일 시스템은 매핑의 문제를 가지고 있다. 파일은 <filename, metadata, data>의 구조를 가지는데 그걸 디스크에 어떤 블락에 어떻게 매치할 것인가 이다.

a.out, dog.jpg를 어떻게 디스크에 저장할 수 있을까? 만약 디스크의 블락 크기 하나가 512byte라면 파일을 512byte로 잘라서 저장한다. 파일의 metadata, file name 이런 식으로 블락 단위로 저장한다.

이렇게 저장되어 있고 a.out을 찾는다면 디스크에서 a.out을 찾아서 파일 이름과 metadata를 확인해서 파일을 읽을 수 있는지 등을 확인한  열어서 보여주게 된다.

 

파일 시스템의 목적은 성능과 안정성이다.

그래서 파일시스템을 디자인할 때 다음을 고려해야 한다.

  • 메타데이터가 어떤 정보를 가지고 있어야 하는지
  • 메타데이터를 어떤 구조로 어떻게 저장할 것인가?
    • 이름과 메타데이터를 어떻게 연관시킬 수 있는지 포함
  • data block의 어디에 배치할 것인가
  • 메타데이터와 데이터 block을 어떻게 관리할까
  • 파일 시스템이 고장 난 후 파일 시스템을 어떻게 복구할 수 있을까?
    • 보통은 성능을 위해서 파일을 지웠다면 이름과 메타데이터를 지운다.

파일 속성은 굉장히 많은 게 존재하는데 일반적으로 Protection 등등은 꼭 쓰인다.

 

유닉스에서 creat(create 아님), open, close, read, write, chmod 등 파일 operation을 많이 제공한다.


Directories

디렉터리의 역할

  • 사용자에게는, 파일을 조직화할 수 있는 구조적인 방법을 제공한다.
  • 파일 시스템에게는, 편리한 naming 인터페이스를 제공한다.
    • logical file organization을 디스크의 피지컬한 파일 배치화 분리할 수 있도록 한다.

Hierarchical directory system

  • 대부분의 파일 시스템은 멀티 레벨 디렉터리를 제공한다. 하나의 디렉토리 안에 여러 하위 디렉터리와 파일을 가질 수 있는 것이다.
  • 대부분의 파일 시스템은 현재 디렉터리(작업 디렉토리)의 개념을 지원한다. 현재 작업 중인 디렉토리를 기준으로 파일을 참조하고 상대 경로를 지정할 수 있는 것이다.
  • 상대 경로 : 현재 디렉토리를 기준으로 파일이나 디렉토리를 지정한다.
  • 절대 경로 : 디렉토리 트리의 루트에서 시작하는 경로를 지정한다.

디렉토리 내부

  • 디렉터리는 사실 특별한 metatdata를 포함하는 파일이다.
  • (file name, file attributes) 구조의 list가 디렉터리이다.
    • Attribute는 Size, protection, creation time, access time, Location on dist 등 다양한 속성을  포함한다.
  • 보통은 unordered 되어 있어서 random으로 보인다. 일반적으로 파일 시스템이 항목을 추가한 순서대로 저장된다.
    • 디렉터리를 읽는 프로그램(ls)에 의해 엔트리가 정렬될 수 있다. 

Pathname Translation

open("/a/b/c")를 생각해 보자.

  • "/" 디렉터리를 연다.
  • 디렉토리 "a"를 찾고 "a"의 위치를 얻는다.
  • 디렉토리 "a"를 열고 "b"를 찾고 위치를 얻는다.
  • 디렉토리 "b"를 열고 "c"를 찾고 위치를 얻는다.
  • "c" 파일을 연다.
  • 물론 모든 스텝마다 permission은 체크된다.

디렉토리 경로를 탐색하는데 많은 시간이 소요된다.

  • open 시스템 콜이 read/write와 분리되어 있는 이유이다.
    • open 시스템 콜이 디렉토리 경로를 따라 디렉터리와 파일을 탐색하며 오래 걸린다.
    • read/write 시스템 콜은 열려있는 파일에 대해 데이터를 읽고 쓰는 작업을 수행한다. 한 번 열어두면 파일 경로를 다시 하지 않아서 효율적이다.
  • 성능을 향상하기 위해 OS는 prefix search 결과를 캐시 해둔다.
    • 예를 들어 "/a/b", "/a/bb", "/a/bbb"는 모두 "/a" prefix를 공유하므로 "/a"에 대한 검색 결과를 캐싱하여 성능을 향상할 수 있다.

Unix에서는 디렉터리가 파일로 구현되어 있어서 파일 operation을 통해 디렉터리를 조작할 수 있다.

C 런타임 라이브러리는 디렉터리를 읽기 위한 abstraction을 제공한다.

  •  opendir, readdir, seekdir, closedir...
  • rename, link, unlink 등 디렉터리와 관련된 추가적인 시스템 콜도 있다.

마운팅

USB를 꽂으면 파일 시스템에 usb가 추가되는데 이게 마운팅이다.

운영체제가 어떤 storage가 붙었고 거기에는 어떤 파일 시스템이 있고 이런 걸 인식하는 과정이다.

  • 윈도우에서는 C:\, D:\ 이런 식으로 드라이브 문자를 하나 잡는다.
  • 유닉스에서는 마운트 포인트를 잡을 수 있다.

여기서 포인트 밑에 붙은 피라미드가 마운트 포인트이다. 빈 디렉터리를 계속 추가해 간다.


파일 쉐어링

파일쉐어링이 굉장히 중요하다. 

  • communication과 동기화의 기반이 된다.
  • 분산 시스템에서 파일은 NFS 같은 네트워크를 통해 파일을 공유할 수 있다.
    • NFS는 storage 서버라고도 불리고 하나의 storage에 여러 기기가 연결되는 파일 쉐어링 네트워크이다. 

파일 쉐어링에 있어서 다음 세 가지 이슈를 유의해야 한다.

  • 동시에 액세스 하는 것에 대한 규칙이 있어야 한다. 어떤 프로세스가 파일을 읽는 동안 다른 프로세스가 write 하면? 두 프로세스가 동시에 파일을 write 하려고 하면?...
  • Concurrency control using locks
  • Protection

즉, consistency를 유지해야 한다는 뜻이다.

유닉스에서는 파일을 열어서 쓰면 즉시 다른 사용자(프로세스)에게도 즉시 보인다.

 

AFS에서는 즉시 보이지는 않고 파일을 닫으면 그때 다 보인다. 실제로 많이 사용된다. sink system call이 있어서 그걸 호출하면 다른 사람에게도 즉시 보이긴 한다.

 

Immutable : 파일이 share 되면 다른 사람이 수정하지 못하게 한다.


file locking

flock이라는 함수를 통해 파일 전체에 락을 걸 수 있다.

a.txt open → flcok을 하면 규칙에 따라 다른 사람들이 접근할 수 있고 못할 수도 있다.

POSIX에는 파일의 일부에도 락을 걸 수 있다. 락을 건 부분만 건드리지 못하는 것이다. fcntl 함수와 struct flock를 사용하여 lock 범위와 유형을 설정할 수 있다.


프로텍션 시스템

a.txt를 만들면 리눅스에서 rwx rwx rwx 이런 식으로 권한이 붙는다. 그 권한에 관한 얘기이다. 파일 시스템은 아래의 protection system을 반드시 구현해야 한다.

  • 누가 파일에 액세스 할 수 있을지 컨트롤해야 한다.
  • 어떻게 엑세스할 수 있을지 컨트롤해야 한다.
  • 결국에는 어느 파일에(objects, file) 누가(subject, user) 어떻게(action, read/write)를 정해야 한다.

Protection에는 주로 두 방식이 있다.

ACLs, Access control list : 파일을 기준으로 누가 action이 가능한지 리스트로 관리하는 것이다., 사진에서 column에 해당한다.

Capabilites : user를 기준으로 어떤 파일에 권한이 있는지 관리하는 것이다. 사진에서 row에 해당한다.

 

Capabilites를 쓰면 권한을 전송하기 좋다. 권한을 쉐어링 하거나 다른 머신으로 전송할 때 유리하다.

 

일반적으로 ACL을 더 많이 사용한다. 권한을 부여하고 삭제하는 것이 쉽다.

capabilites로 특정 user 권한을 삭제하려면 해당 권한을 가지고 있는 모든 usr를 추적해야 한다.

 

파일과 사용자가 많아지면 ACL 리스트가 길어져서 권한을 관리하는 일이 힘들어질 수 있다.

따라서 요즘에는 그룹을 사용한다. rwx rwx rwx 이렇게 리눅스에 있으면 이것도 그룹으로 관리한다. 그룹을 사용하면 사용자 셋으로 하는 거라 오버헤드가 별로 안 커진다.