파일 시스템

Sirius·2024년 9월 7일
0

파일과 파일시스템

1. File

일반적으로 비휘발성의 보조기억장치에 저장(HDD)
OS는 다양한 저장장치를 file이라는 동일한 논리적 단위로 볼 수 있게 해줌

  • 연산: create, read, write, reposition(iseek), delete, open, close

2. File attribute(파일의 메타데이터)

파일 자체의 내용이 아니라 파일을 관리하기 위한 각종 정보들
ex> 파일 이름, 유형, 저장된 위치, 파일 사이즈, 접근권한(읽기/쓰기/실행), 시간(생성/변경/사용) 소유자 등

3. File System

1) OS에서 파일을 관리하는 부분
2) 파일 및 파일의 메타데이터, 디렉터리 정보등을 관리
3) 파일의 저장방법 결정
4) 파일 보호 등

Directory and Logical Disk

1. 디렉토리

파일의 메타데이터 중 일부를 보관하고 있는 특별한 파일
연산 -> search for a file, traverse the file system

2. 파티션(=Logical Disk)

OS가 보는 디스크 = 논리적 디스크(파티션)
-> 물리적 디스크를 파티션으로 구성한 뒤 각각의 파티션에 file system을 깔거나 Swapping 등 다른 용도로 사용할 수 있다.

Open()

Open()시 파일의 메타데이터가 메모리로 올라온다.

Open("/a/b/c")를 하면
1) 시스템콜(I/O가 일어난다.
2) CPU 제어권이 OS로 넘어가고 사용자 메모리 영역에서 커널 메모리 영역으로 넘어간다.
3) OS는 이미 root의 메타데이터를 알고있다.
4) root의 content에서 a의 메타데이터를 찾아내고 이를 메모리에 올린다.
5) a의 메타데이터를 기반으로 a의 content를 찾고 b의 메타데이터를 찾는다.
6) b의 메타데이터를 기반으로 b의 content를 찾는다.

File Protection

각 파일에 대해 누구에게 어떤 유형의 접근 (read/write/execution)을 허락할 것인가?

접근제어방법

1) Access Control Matrix

  • ACL: 파일별로 누구에게 어떤 접근 권한이 있는지
  • Capability: 사용자별로 자신이 접근권한을 가진 파일 및 해당권한 표시
    그러나 sparse matrix의 문제점을 가진다.

2) Grouping(지금 쓰는 방식)

rwx | r-- | r--
전체 user를 owner, group, public 3개의 그룹으로 구분

3) Password

파일마다 password를 두는 방법 (디렉터리 파일에 두는 방법도 가능)
모든 접근권한마다 다른 password를 두면 관리와 암기에 대한 문제가 존재한다.

File System의 Mounting


Q: 만약 다른 파티션에 설치되어 있는 파일 시스템 접근시 어떻게?
A: 마운팅한다.

Access Methods

1) 순차접근

카세트 테이프에 다시 듣고 싶은 부분이 있으면 되감아야한다.
(A -> B -> C)

2) 직접접근

LP 레코드판과 같이 접근 (특정위치에 바로 접근이 가능하다)
(A -> C)

파일을 디스크에 할당하는 방법

디스크에 파일 저장시 동일 크기의 섹터(블록) 단위로 저장한다.

1) 연속할당(Contiguous Allocation)
2) 연결할당(Linked Allocation)
3) 인덱스를 이용한 할당(Indexed Allocation)

1. 연속할당

1) 장점

가. 빠른 I/O이다. 한번의 seek로 많이 얻어온다.
나. 직접접근이 가능하다.

2) 단점

가. 외부조각 문제 발생(비어있어도 못들어간다)
나. 파일의 크기가 바뀌면(커지면) 제약이 있다.
ex> 3block -> 5block 되면 뒤에거를 침해하게 된다.
다. 만약 미리 hole을 만들어서 할당자리 만들어 놓으면 내부조각문제가 발생한다. (할당해 놓았는데 아무도 안쓰는...)

2. 연결할당

연속적이 아니라 빈위치면 아무곳이나 들어간다.

1) 장점

외부조각이 발생하지 않는다.

2) 단점

가. 직접접근이 아니라 순차접근이다. 따라서 앞부분 다 탐색해야한다(카세트)
나. Reliability 문제가 있다. 중간에 하나 bad sector 되면 포인터가 유실된다. 다음 위치는 모조리 접근이 불가능 하다.
다. 한 섹터의 들어갈 내용이 포인터 저장(4 byte) 때문에 두 섹터에 저장된다.(공간효율성이 좋지 않다)

FAT(File Allocation Table)를 통해 포인터를 별도위 위치에 보관하여 Reliability와 공간효율성 문제를 하결할 수 있다.

3. 인덱스를 이용한 할당

1) 장점

가. 외부조각 발생X
나. 직접 접근 가능하다.

2) 단점

가. 너무 작은 파일이어도 블록이 2개 필요하다.(인덱스 블록, 실제데이터 저장 블록): 공간낭비
나. 너무 큰 파일은 하나의 block으로 인덱스를 저장하기에 부족하다.
-> 해결방안
1) linked scheme: 인덱스 블록에 실제 파일의 위치를 적다가 결국 이 파일의 크기를 커버못하면 마지막에 또 다른 인덱스 블록을 가리키게 한다.
2) multi-level index: 인덱스 블록의 인덱스가 파일의 위치를 직접 가리키는 것이 아니라 또 다른 인덱스를 가리키게 한다. (2번 거침)

Unix의 파일 시스템 구조

1) Boot block: 어떤 파일 시스템이든 boot block이 맨 앞에 나온다.(약속)
-> 전원키면 부팅한다. 즉 Boot block(부팅에 필요한 정보)을 메모리에 올린다.
Boot block이 시키는 대로 하면 이 파일 시스템에서 OS 커널의 위치가 어디인지 찾아서 그것을 메모리에 올려서 부팅이 이루어진다.


2) Super block: 파일 시스템에 관한 총체적인 정보를 담고 있다.
-> 어디가 먼 블록이고, 어디가 파일이 저장되어 있는지 등


3) Inode block: 파일의 메타 데이터를 가진다.
-> 파일 하나당 하나의 Inode가 할당되며, 파일의 위치, 파일 크기, 파일의 소유자, 권한, 마지막 접근 시간, 마지막 수정 시간 등의 정보를 포함한다.


4) Data block: 실제 파일 데이터가 저장되는 블록이다.
-> ex> Directory 파일의 경우 file 이름 : inode 번호 이렇게 가진다.

FAT File System(윈도우즈)

1) FAT: 파일의 메타데이터의 일부를 가진다.(특히 위치 정보를 담고 있는 테이블)
2) Data block: 똑같이 실제 파일 데이터가 저장되는 블록이다.
파일 시스템은 여러 클러스터로 나누어져 있으며, 각 클러스터는 일정 크기의 데이터 블록을 가진다.
-> ex> Directory 파일의 경우 file 이름: 접근 권한, 소유주 등 모든 메타 데이터를 디렉터리가 가진다. 이를 통해 각 파일이 어떤 클러스터에 저장되어 있는지 FAT와 함께 관리한다.

  • 직접 접근이 가능하다 (FAT이 작은 테이블임, 메모리에 올리면 쭉 따라간다)
    Data block가 FAT를 분리하였다. (FAT이 중요해서 2copy 이상 저장함)

비어있는 Blck 관리 방안

1. Bit map or Bit vector

각각의 Block 별로 번호가 있으면 유닉스의 경우 super block에다가 비트를 두어서 사용중인지 비어있는지 0과 1로 표시한다.
비트맵의 크기는 블록의 개수만큼 구성한다.

2. Linked list

비어있는 Block들을 연결한다.
장점: 공간의 낭비가 없다.
단점: 연속적인 빈 공간을 찾기 어렵다.

3. Grouping

처음에 비어있는 위치가 인덱스 역할을 한다.
하나의 Free Block에 비어있는 여러 Block의 인덱스를 저장한다.

4. Counting

연속적인 빈 Block을 찾기에 효과적이다.
1) 빈블록의 첫번째 위치, 2) 거기서 부터 몇개가 빈 블록인지...

디렉토리 구현(Directory Implementation)

1. 선형 리스트(Linear list)

file 이름: x바이트
file size: n바이트 즉 메타 데이터 크기는 고정 되어 있다.
구현은 간단하다 그러나 디렉터리 내에 파일이 있는지 찾기 위해서는 linear search가 필요하다.

2. 해시 테이블(Hash Table)

순차 탐색이 필요 없다.
파일 이름에 해시함수 적용하고 그 결과 엔트리를 찾는다.
ex> F(ccc) -> 3 (3번 엔트리 씀)
그러나 Hash Collection 발생시 문제가 생긴다.

3. File의 메타데이터 보관 위치

1) 디렉터리 내에 직접 보관
2) 디렉터리에는 포인터를 두고 다른 곳에 보관(inode, FAT)

4. Long File name의 지원

파일 이름을 특정 byte수로 제한하는 것은 비효율적

길어서 정해진 엔트리 수 벗어나면 포인터를 두어서 맨 끝에서부터 파일 이름이 거꾸로 저장되도록 한다.

VFS and NFS

1. VFS(Virtual File System)

파일 시스템별로 서로 다른 종류의 System Call 쓰면 사용자가 혼란온다.
VFS인터페이스를 두어서 동일한 시스템 콜 인터페이스(API)를 통해 접근할 수 있도록 해주는 OS 계층이다.

2. NFS(Network File System)

분산 시스템에서는 네트워크를 통해 파일이 공유될 수 있다.
즉 파일 시스템이 로컬 strage에 저장될 수도 있지만 원격에 저장된 파일시스템에 내가 접근할 수도 있다.

Page 캐시와 Buffer 캐시

1. Page 캐시

물리적인 메모리에 있는 프레임들을 페이지 케시라고 부른다.
파일을 읽거나 쓸 때, 데이터를 디스크에서 직접 읽는 대신, 해당 파일의 일부 또는 전체를 메모리에 로드하고 이를 캐시로 사용한다.
이렇게 하면 디스크 I/O를 줄일 수 있고, 캐시된 데이터를 더 빠르게 액세스할 수 있다. 디스크는 물리적으로 느리기 때문에, 디스크 접근 대신 메모리에서 데이터를 읽어오는 것이 성능상 훨씬 유리하다.
-> Swap area보다 빠르다.

2. Memory-Mapped I/O

파일의 일부 또는 전체를 물리 메모리의 특정 주소에 직접 매핑하여, 파일의 데이터에 접근할 때 파일을 읽거나 쓰는 System Call(read, write)을 사용하지 않고, 메모리 접근처럼 처리하는 방식이다.
-> 즉, 메모리에 파일의 데이터를 매핑해 두고, 프로그램은 이 매핑된 메모리를 접근하여 파일의 데이터를 읽거나 쓴다.

3. Buffer 캐시

파일에 대한 데이터를 사용자가 요청시 디스크에서 읽어서 사용자에게 전달하는 것이 아니라 OS가 읽어온 내용을 자기의 영역 중 일부에 저장해놓고 나중에 같은 요청 발생시 디스크까지 가지 않고 Buffer 캐시에서 바로 읽어준다.

4. Unified Buffer 캐시

최근의 OS는 Page 캐시와 Buffer 캐시를 같이 쓴다.

1) 메모리 내의 캐시 영역: 그림의 왼쪽 부분은 운영 체제의 메모리 영역을 나타낸다. 이 영역에는 Page Cache와 Buffer Cache가 통합된 형태로 데이터가 저장된다.


2) 파일 시스템의 데이터 블록: 그림의 오른쪽 부분은 파일 시스템의 데이터 블록을 나타낸다. 여기에는 파일이 저장된 데이터 블록이 있으며, 운영 체제는 필요한 데이터를 이 블록에서 읽어와 캐시에 저장한다.


3) 통합된 캐시 관리: Unified Buffer 캐시는 Page Cache와 Buffer Cache를 통합하여 관리하며, 캐시의 내용이 동일한 파일 시스템 데이터 블록을 가리키도록 한다. 이를 통해 메모리 사용 효율성과 성능을 향상시킨다.

Unified Buffer Cache or Not?

1. Unified Buffer Cache를 이용하지 않는 File I/O

1) read/write I/O

  • read 또는 write system call이 사용자 프로그램으로부터 들어오면, 운영 체제(OS)는 디스크에 있는 파일 데이터를 사용자에게 전달해야 한다.
  • 이를 위해 OS는 파일 시스템에서 요청된 파일의 내용을 디스크에서 읽어와 OS의 Buffer 캐시(Buffer Cache)에 저장한다.
  • 이후, 사용자 프로그램에게 데이터를 전달할 때는 OS의 Buffer 캐시에서 사용자 프로그램의 메모리 영역(사용자 페이지)로 데이터를 복사(Copy) 한다.

2) Memory Mapped I/O

  • Memory-Mapped I/O는 파일의 데이터를 메모리에 직접 매핑(Mapping)하여 파일 내용을 메모리처럼 읽고 쓸 수 있게 하는 방식이다.
  • 이 방식은 사용자가 mmap system call을 호출하여 자신의 프로세스 주소 공간의 일부를 파일에 매핑한다.
  • 매핑이 완료되면, OS는 디스크에 있는 파일의 일부 내용을 Buffer 캐시에 읽어오고, 이를 Page 캐시(Page Cache)에 복사한다.
  • 사용자 프로그램은 자신의 주소 공간에 매핑된 메모리 영역에 대해 직접 메모리 접근(읽기/쓰기)하듯이 파일 데이터를 접근할 수 있다.
    이 때, 파일의 데이터가 이미 Page 캐시에 존재한다면, 사용자 프로그램은 데이터를 메모리에 접근하듯이 빠르게 읽거나 쓸 수 있다.
  • 만약 사용자가 매핑만 해놓고 데이터를 아직 메모리에 읽어오지 않았다면, 메모리 접근 시 페이지 폴트(Page Fault)가 발생한다.

2. Unified Buffer Cache를 이용하는 File I/O

Unified Buffer Cache를 사용하면 운영 체제(OS)는 파일 I/O와 메모리 관리의 효율성을 높이기 위해 Page 캐시와 Buffer 캐시를 통합하여 관리한다. 이 접근 방식은 파일의 데이터를 관리하는 데 필요한 중복을 줄이고, 메모리 사용의 일관성과 효율성을 높인다.

1) read/write I/O

  • Unified Buffer Cache를 사용하는 경우, OS는 Page 캐시와 Buffer 캐시를 따로 나누지 않고, 필요에 따라 같은 메모리 공간(Page 캐시)을 사용한다.
  • 사용자 프로그램이 read 또는 write system call을 호출하면, OS는 CPU의 제어를 가져와서 데이터를 처리한다.
  • 파일의 내용이 이미 메모리에 올라와 있는 경우에 OS는 Page 캐시에서 해당 내용을 사용자 프로그램의 주소 공간으로 복사하여 사용자에게 전달한다.
  • 파일의 내용이 메모리에 올라와 있지 않은 경우에 OS는 디스크의 파일 시스템에서 해당 데이터를 읽어와 Page 캐시에 저장한 후, 이를 사용자 프로그램의 주소 공간으로 복사하여 전달한다.
    -> 결과적으로, 파일 데이터는 Page 캐시에서만 관리되며, Buffer 캐시와 Page 캐시의 중복이 없어집니다.

2) Memory Mapped I/O

  • 사용자 프로그램이 mmap system call을 호출하여, 자신의 주소 공간의 일부를 파일에 매핑한다. 이 때, Page 캐시가 사용자 프로그램의 주소 공간에 직접 매핑된다.
    즉, 파일의 데이터를 별도로 Buffer 캐시에 복사하지 않고, Page 캐시 자체가 사용자 프로세스의 가상 주소 공간에 논리적으로 매핑된다.
  • Page 캐시가 사용자 프로그램의 메모리 주소에 직접 연결되므로, 사용자 프로그램은 파일 데이터를 메모리처럼 읽고 쓸 수 있다.
  • 버퍼 캐시와 페이지 캐시가 분리되지 않고, Page 캐시가 공유되는 방식이기 때문에, 중복된 데이터 복사 과정이 제거된다.
  • 파일의 내용을 읽거나 쓰는 경우, 데이터가 이미 메모리에 존재하면 메모리 접근 속도로 빠르게 접근할 수 있다.

프로그램의 실행

1) 파일 시스템에서 파일이 실행이 되면 프로세스가 되고 이 프로세스는 각자 virtual memory를 가진다.
2) 각자 지닌 virtual memory는 주소변환해주는 HW(MMU)로 인해 당장 필요한 부분만 물리 메모리(RAM)에 올라간다.
나머지는 Swap area로 올라간다.

  • 코드 부분은 물리메모리에 올라갔다가 쫓겨날때 swap area로 가지 않는다.
    -> 코드 부분은 read only로 이미 실행파일 형태로 저장되어 있다.
    -> 코드 부분은 이미 파일 시스템에 있기 때문에 swap area로 내리지 않고, 필요 없으면 물리적 메모리에서 지운다. 나중에 필요하면 파일 시스템에서 가져온다.

프로그램 실행(Memory Mapped I/O)

가상주소의 것을 물리메모리에다가 매핑해서 쓴다.
(그 내용이 곧 이 내용)

  • 프로그램이 실행되다가 데이터 파일을 쓰고 싶다.(Memory Mapped I/O 형태로)
    1) 프로그램이 OS에게 이 데이터 파일의 일부를 내 주소공간 일부에다가 매핑해줘 라고 System Call을 한다.
    2) 프로그램이 매핑된 가상 메모리 영역에 접근하려고 시도하지만, 그 내용이 실제로 물리 메모리에 아직 로드되지 않은 경우 페이지 폴트(Page Fault)가 발생힌다. 이때 CPU 제어권이 OS에게 넘어간다. OS는 페이지 폴트를 처리하기 위해 디스크에서 해당 파일의 필요한 데이터 페이지를 읽어와 물리 메모리에 올린다.
    3) 가상의 페이지가 물리적 메모리의 페이지로 매핑이 된다.
    4) OS는 가상 메모리의 페이지와 물리 메모리의 페이지 프레임을 연결하여 매핑한다.
    이제 가상 주소 공간에서의 메모리 접근은 물리 메모리의 실제 데이터 위치를 참조하게 된다.
    이 매핑이 완료되면, 프로그램은 메모리 주소를 통해 OS의 도움없이 파일 데이터를 직접 접근할 수 있다.
    5) 나중에 물리메모리의 검정색 부분이 쫓겨날때는 swap area로 가는게 아니라 Memory Mapped 파일이기 때문에 파일에다가 수정된 내용을 써주고 쫓아낸다.
    6) 다른 프로그램도 동일한 파일, 동일 데이터에 대해 Memory Mapped I/O 호출이 가능하다. 그럴시 물리메모리의 검정색 부분이 공유된다.

프로그램 실행(read write I/O)

파일에 대해 read/write system call을 해서 사용할 수 도 있다.

  • 이 경우에 프로그램 A가 원하는 파일의 특정 내용을 달라고 OS에게 System Call을 한다.
  • 이 system call을 통해 프로그램 A는 OS에게 "이 파일의 특정 데이터를 나에게 전달해달라"거나 "이 데이터를 파일에 써달라"는 요청을 한다.
  • OS는 요청을 받으면 해당 파일의 데이터를 확인하기 위해 Unified Buffer Cache를 확인한다. Unified Buffer Cache는 Page 캐시와 Buffer 캐시가 통합된 형태로 관리되는 캐시이다. 즉, 물리 메모리에 있는 페이지 캐시가 버퍼 캐시의 역할도 겸하고 있다.
  • 검정색 부분은 해당 파일의 데이터가 이미 물리 메모리(Page 캐시) 내에 올라와 있는 상태를 의미한다.
  • 파일의 특정 내용이 이미 Page 캐시(버퍼 캐시)로 메모리에 로드되어 있는 경우(검정색 부분이 있는 경우)에 OS는 해당 데이터를 Page 캐시에서 읽어와 사용자 프로그램의 메모리 공간으로 복사(Copy) 한다.
  • 파일의 내용이 아직 메모리에 올라와 있지 않은 경우에 OS는 디스크에서 해당 파일의 데이터를 읽어와 Unified Buffer Cache에 저장한다. 데이터를 Page 캐시로 메모리에 로드한 후, 사용자 프로그램의 메모리 공간으로 복사(Copy)하여 전달한다.

즉 OS가 사용자 프로그램 A에게 필요한 데이터를 메모리에 로드하고 이를 복사하여 전달하면, 프로그램 A는 해당 데이터를 사용할 수 있게 된다.

결론

1. Memory Mapped I/O

장점: 빠르고 효율적인 접근 -> 직접 메모리 접근:

  • Memory Mapped I/O를 사용하면, 파일의 데이터가 물리 메모리에 로드된 후에는 System Call 없이 프로그램이 직접 메모리 접근을 통해 데이터를 읽고 쓸 수 있다.
  • 파일의 데이터를 메모리에 매핑하고 나면, 프로그램이 CPU를 가지면서 메모리 접근처럼 빠르게 파일 데이터를 처리할 수 있습니다. 이로 인해 I/O 작업 속도가 매우 빨라진다.
  • Memory Mapped I/O는 파일 데이터를 메모리에 매핑할 때, 해당 데이터가 메모리에 이미 올라와 있다면 추가적인 메모리 복사(copy) 작업 없이 사용할 수 있다.
  • 파일의 내용을 프로세스의 가상 메모리 주소 공간에 직접 매핑하므로, 변경된 내용은 가상 메모리와 물리 메모리 간에 바로 전달된다.
  • 이는 read/write I/O 방식에서 발생하는 메모리 복사 오버헤드가 제거되어 효율성이 증가한다.
  • 파일 데이터가 이미 메모리에 존재한다면, OS의 추가적인 개입 없이 프로그램이 직접 데이터를 읽고 쓸 수 있다.
  • 페이지가 메모리에 없는 경우에만 페이지 폴트가 발생하여 OS가 필요한 데이터를 메모리에 로드하는 방식이므로, system call 호출 횟수가 줄어들어 성능이 향상된다.

2. read/write I/O

  • read/write I/O 방식에서는 파일 데이터가 OS의 Buffer Cache에서 사용자 메모리로 복사되어 전달된다.
  • 프로그램이 데이터를 읽거나 쓰기 위해 매번 시스템 콜을 통해 OS에 요청하고, OS는 해당 데이터를 캐시에서 복사하여 전달하기 때문에, 프로그램 간의 데이터 일관성 문제가 없다.
  • 각 프로그램이 파일의 데이터에 대한 독립적인 복사본을 가지므로, 프로그램 간 충돌이나 일관성 문제가 발생하지 않는다.

3. 결론

Memory Mapped I/O는 파일 데이터가 메모리에 올라와 있는 경우 빠르고 효율적으로 접근할 수 있고, 메모리 복사 오버헤드가 없어서 성능이 뛰어나다. 그러나 여러 프로그램이 같은 메모리 영역을 공유할 때 데이터 일관성 문제가 발생할 수 있어 이를 주의해야 한다.

read/write I/O 방식은 시스템 콜을 통해 데이터를 복사하여 전달하므로 데이터 일관성 문제가 없다. 하지만 메모리 복사로 인한 오버헤드가 발생할 수 있으며, 성능 측면에서는 Memory Mapped I/O보다 느릴 수 있다.

따라서, 사용할 I/O 방식은 파일 접근의 특성과 애플리케이션의 요구 사항에 따라 결정해야 한다. 데이터 일관성이 중요한 경우 read/write I/O를 사용하고, 성능이 중요한 경우 Memory Mapped I/O를 사용할 수 있다.

데이터 일관성 문제란?

데이터 일관성(Consistency) 문제란, 동일한 데이터를 여러 프로그램(프로세스)이 동시에 읽거나 쓸 때, 모든 프로그램이 동일한 최신 데이터를 볼 수 없을 때 발생하는 문제를 말한다. 이 문제는 Memory Mapped I/O를 사용할 때 더 두드러질 수 있습니다. 반면, read/write I/O 방식에서는 이러한 문제를 피할 수 있다.

예시를 통한 데이터 일관성 문제 설명

  • 예시 시나리오: 두 개의 프로그램, 프로그램 A와 프로그램 B가 동일한 파일 data.txt를 사용하여 작업을 하고 있다고 가정한다. 이 파일은 숫자 100을 담고 있는 간단한 텍스트 파일이다.

프로그램 A와 프로그램 B는 각각 Memory Mapped I/O를 사용하여 이 파일의 데이터를 메모리에 매핑하여 사용한다.
프로그램 A는 파일의 숫자를 200으로 업데이트하고, 프로그램 B는 파일의 숫자를 읽어와 더한 다음(+300), 결과를 다시 파일에 쓰는 작업을 수행한다.

1) Memory Mapped I/O 방식에서의 데이터 일관성 문제

  • Step 1: 프로그램 A와 B는 Memory Mapped I/O를 사용하여 data.txt를 메모리에 매핑한다.

    이 과정에서 파일 data.txt의 데이터(100)는 각 프로그램의 메모리에 매핑된다.
    물리 메모리의 동일한 페이지가 매핑되어 프로그램 A와 B가 동일한 메모리 영역을 공유하게 된다.

  • Step 2: 프로그램 A가 Memory Mapped I/O를 통해 파일의 내용을 100에서 200으로 변경한다.

    이때, 프로그램 A의 메모리 영역에서 값이 200으로 변경되고, 그 내용은 물리 메모리에 반영된다.

  • Step 3: 프로그램 B가 같은 메모리 영역을 읽습니다.

    프로그램 B가 동일한 메모리 영역을 읽을 때, 프로그램 A의 변경이 이미 반영되어 있으면 값이 200으로 보이겠지만, 이 시점에서 B가 변경 전의 데이터를 읽고 있으면 값은 여전히 100으로 보일 수 있다.
    만약 프로그램 B가 값이 100인 상태로 데이터를 가져와 작업(+300)을 한다면, B의 연산 결과는 500이 되어야 하지만, 잘못된 값 100에서 시작했기 때문에 400이 된다.

  • Step 4: 프로그램 B가 그 값을 다시 메모리에 쓰면, 메모리에는 값이 400이 저장된다.

    프로그램 A가 200으로 변경한 내용이 무시되었고, 결과적으로 데이터의 일관성이 깨지는 문제가 발생한다.

2) read/write I/O 방식에서의 데이터 일관성 보장

  • Step 1: 프로그램 A와 B는 파일 data.txt를 read/write I/O 방식으로 접근한다.

    프로그램 A가 read 시스템 콜을 통해 파일을 읽어와서 자신의 사용자 메모리 공간에 복사한 후, 값을 100에서 200으로 업데이트한다.
    프로그램 A는 write 시스템 콜을 통해 변경된 데이터를 OS의 버퍼 캐시에 기록하고, 이 데이터는 OS가 관리하는 버퍼에 저장된다.

  • Step 2: 프로그램 B가 read 시스템 콜을 통해 파일의 데이터를 읽습니다.

    프로그램 B의 요청은 OS가 관리하는 버퍼 캐시에서 처리되므로, 프로그램 A가 파일을 수정하여 OS에 반영한 최신 데이터(200)를 가져온다.
    프로그램 B는 200이라는 최신 값을 사용하여 연산(+300)을 수행하고, 결과를 write 시스템 콜을 통해 파일에 기록합니다.
    이 경우, 프로그램 B가 최신 값을 가져왔기 때문에 최종 결과는 일관성 있는 데이터 500이 됩니다.

  • 왜 데이터 일관성 문제가 발생하는가?

    Memory Mapped I/O 방식에서 데이터 일관성 문제가 발생하는 이유는 물리 메모리의 동일한 부분을 여러 프로그램이 동시에 공유하여 사용하는 경우, 변경된 내용을 서로 알지 못하는 상황이 발생할 수 있기 때문이다.
    반면 read/write I/O 방식에서는 모든 데이터 접근이 OS를 통해 이루어지며, OS가 일관성을 유지하는 역할을 수행한다. OS가 이를 순차적으로 처리하면서 데이터의 일관성을 유지한다.
    모든 파일의 읽기/쓰기 요청이 OS의 버퍼 캐시를 통해 이루어지기 때문에, 변경된 데이터는 항상 OS의 버퍼 캐시에 반영되고, 다른 프로그램이 최신 데이터를 읽어올 수 있다.

0개의 댓글