[Operating Systems] 파일 시스템과 I/O 프로그래밍
운영체제에서 파일 시스템이 담당하는 역할과 I/O 프로그래밍의 기본 원리, 그리고 파일 정보의 저장 방식에 대해 알아보고자 한다.
🖥️ 운영체제에서 파일 시스템의 역할
운영체제는 하드웨어와 사용자 사이의 중간 계층 역할을 수행한다. 그 중에서도 파일 시스템은 저장 장치와 사용자 애플리케이션을 연결하는 핵심 인터페이스이다.
📋 파일 시스템의 핵심 기능
-
하드웨어 추상화
- HDD, SSD, USB 등 다양한 저장 장치를 하나의 통일된 인터페이스로 제공
- 물리적 블록과 섹터를 논리적인 파일과 디렉토리로 변환
- 사용자는 하드웨어 구조를 몰라도 파일 이름만으로 접근 가능
-
자원 관리
- 저장 공간의 할당과 해제
- 동시 접근 제어 및 잠금 메커니즘
- 메모리와 디스크 간의 버퍼 관리
-
보안 및 권한 관리
- 파일별, 사용자별 접근 권한 설정
- 읽기, 쓰기, 실행 권한의 세분화된 제어
- 시스템 파일 보호
🔌 I/O 프로그래밍
I/O 프로그래밍은 Input/Output, 즉 입출력 데이터를 다루는 프로그래밍 방식이다. 파일 시스템을 통해 파일이나 디렉토리에 접근하는 작업도 포함된다.
🏗️ 시스템콜과 API
-
시스템콜 (System Call)
운영체제의 기능을 호출하는 프로그래밍 인터페이스로, 사용자 프로그램이 커널 기능에 접근할 수 있게 해준다.
// Node.js - 저수준 I/O 예시 const fs = require("fs"); const fd = fs.openSync("example.txt", "w"); // 파일 열기 fs.writeSync(fd, "Hello"); // 파일 쓰기 fs.closeSync(fd); // 파일 닫기
-
고수준 API
프로그래밍 언어가 제공하는 간편한 I/O 인터페이스로, 내부적으로 시스템콜을 호출한다.
// Node.js - 고수준 I/O 예시 const fs = require("fs"); fs.writeFileSync("example.txt", "Hello World"); // 파일 쓰기 const data = fs.readFileSync("example.txt"); // 파일 읽기
⚙️ 저수준 vs 고수준 I/O
구분 | 저수준 I/O | 고수준 I/O |
---|---|---|
특징 | 시스템콜 직접 호출 | 고수준 함수 사용 |
장점 | 성능 우수, 세밀한 제어 가능 | 간결하고 사용 편의성 높음 |
단점 | 복잡하고 오류 처리 필요 | 세부 제어 어려움 |
💾 파일 시스템 정보의 저장 방식
파일 시스템은 단순히 데이터를 저장하는 것뿐만 아니라, 각 파일에 대한 정보도 함께 관리한다. 이를 메타데이터 라고 부른다.
📝 메타데이터의 종류
-
기본 메타데이터
- 파일명: 사용자가 지정한 파일 이름
- 크기: 파일이 차지하는 바이트 수
- 생성일/수정일: 파일이 언제 만들어지고 변경되었는지
- 권한: 누가 읽고, 쓰고, 실행할 수 있는지
-
시스템 메타데이터
- inode 번호: 파일을 고유하게 식별하는 번호
- 블록 위치: 실제 데이터가 저장된 디스크 위치
- 링크 수: 해당 파일을 가리키는 하드링크 개수
💻 인메모리 방식
인메모리 파일 시스템은 디스크 대신 메모리(RAM)를 사용하여 데이터를 저장하는 방식이다.
인메모리 방식은 디스크 접근 없이 메모리에서 직접 처리하므로 속도가 매우 빠르며, 복잡한 디스크 I/O 로직이 없어 구현이 간단하다.
하지만 메모리에만 데이터를 저장하므로 프로그램 종료나 시스템 재부팅 시 데이터가 사라지는 휘발성 문제가 있으며, RAM 크기에 따라 저장 용량이 제한된다는 단점이 있다.
🔄 버퍼링과 캐싱
I/O 성능을 향상시키기 위해 운영체제는 버퍼링과 캐싱 기법을 사용한다.
📦 버퍼링 (Buffering)
여러 개의 작은 I/O 요청을 모아서 한 번에 처리하는 기법이다.
버퍼링 없이:
fs.writeFileSync('log.txt', 'A'); // 디스크 접근
fs.appendFileSync('log.txt', 'B'); // 디스크 접근
fs.appendFileSync('log.txt', 'C'); // 디스크 접근
버퍼링 사용:
let buffer = '';
buffer += 'A'; // 메모리에 저장
buffer += 'B'; // 메모리에 저장
buffer += 'C'; // 메모리에 저장
fs.writeFileSync('log.txt', buffer); // "ABC" 한 번에 디스크 쓰기
🗄️ 캐싱 (Caching)
자주 사용되는 데이터를 메모리에 보관해두어 빠르게 접근할 수 있게 하는 기법이다.
- 읽기 캐시: 한 번 읽은 파일을 메모리에 보관
- 쓰기 캐시: 쓰기 데이터를 일시적으로 메모리에 보관 후 나중에 디스크에 반영
Leave a comment