파일
파일의 기본 개념
- 사용자나 응용프로그램 관점 : 정보를 저장하고 관리하는 논리적인 단위
- 컴퓨터 시스템 관점 : 정보를 저장하는 컨테이너 / 0과 1의 데이터
파일이 저장되는 저장 장치 (HDD, SSD, USB, 테이프 저장 장치, 램 디스크) - 파일 관리에서 OS의 역할 : 파일 생성, 기록, 읽기의 모든 과정 관리
- 응용프로그램이 OS 없이 파일을 다루는 것은 불가능 (저장 매체, 빈 공간 등의 관리는 모두 OS가 수행)
파일 입출력 주소
- 디스크 장치는 디스크 물리 주소 사용
- OS는 논리 블록 주소 사용
- 논리 블록 주소(Logical Block Address, LBA) : 저장 매체를 1차원의 연속된 데이터 블록들로 처리 / 저장 매체의 종류에 관계 없음
- 모든 블록을 0부터 시작하는 블록 번호를 매김
- HDD의 경우 바깥 실린더에서 안으로, 위 트랙에서 아래로
- 응용프로그램은 파일 내 바이트 주소 사용 (바이트 주소 : 파일 내 바이트 위치(offset))
파일 주소 변환
- 사용자나 응용프로그램 : 파일 데이터가 바이트 단위로 연속하여 저장된다고 생각
- OS : 파일을 블록 크기로 분할, 각 블록을 디스크에 분할 저장 / 블록은 OS가 입출력하는 단위
- 파일 주소 변환 과정 : 파일 내 바이트 주소 -> 논리 블록 주소 -> 물리 주소
- OS는 파일 내 바이트 주소를 논리 블록 주소로 변환 / 디스크 장치의 펌웨어가 논리 블록 주소를 물리 주소로 변환
파일 시스템 구조
트리 계층 구조로 파일 시스템 구성 : 디렉토리와 파일의 트리 구조
- 루트 디렉토리 : 계층 구조의 최상위 디렉토리
- 서브 디렉토리 : 하부 디렉토리들
- 디렉토리도 하나의 파일 (서브 디렉토리나 파일들의 목록을 저장한 파일)
디렉토리
- 논리적 관점 : 여러 파일 혹은 서브 디렉토리를 포함하는 컨테이너 / 파일에 대한 경로 제공
- 물리적 관점 : 디렉토리는 파일이나 서브 디렉토리 이름, 이들에 관한 위치 정보, 속성 등을 저장하는 특별한 파일
파일 이름과 경로명
- 단순 파일 이름 : abc.exe, draw.jpg, main.cpp 등
- 파일 경로명(pathname) : 루트 디렉토리부터 파일에 이르기까지의 계층 경로 (/Programs/Apps/abc.exe)
운영체제에서 파일 시스템을 다루기 위한 메타 정보
- 파일 시스템 메타 정보 – 파일 시스템 전체에 관한 정보
- 파일 메타 정보 – 파일에 관한 정보
파일 시스템 메타 정보
- 파일 시스템 전체 크기와 현재 사용 크기
- 저장 장치에 구축된 파일 시스템의 비어 있는 크기
- 저장 장치의 빈 블록 리스트 등
파일 시스템 메타 정보가 저장되는 위치
- 운영체제마다 다름, 운영체제가 쉽게 읽고 쓸 수 있도록 저장 매체의 특별한 위치에 저장
파일 메타 정보
- 파일 이름
- 파일 크기
- 파일 생성 시간
- 파일 수정 시간
- 최근 접근 시간
- 파일을 만든 사용자
- 파일 속성(접근 권한)
- 파일이 저장된 위치 등
파일 메타 정보가 저장되는 위치
- 파일 시스템마다 다름
- 특별한 위치(예:i-node)에 저장
파일 시스템 종류
- FAT(File Allocation Table) 파일 시스템 : MS-DOS에서 사용. NTFS의 근간
- UFS(Unix File System) : Unix에서 사용
- ext2, ext3, ext4 : 리눅스에서 사용
- HFS(Hierarchical File System) : Mac 운영체제에서 사용
- NTFS(New Technology File System) : Windows3.1부터 지금까지 사용. FAT 개선, 리눅스에서도 지원됨
파일 시스템 구현 이슈
- 디스크에 파일 시스템 포맷 : 디스크 장치에 비어 있는 블록들의 리스트를 어떻게 관리할 것인가?
- 파일 블록 할당/배치 관리 : 파일 블록들을 디스크의 어느 영역에 분산 배치할 것인가?
- 파일 블록 위치 관리 : 파일 블록들이 저장된 디스크 내 위치들을 어떻게 관리할 것인가?
FAT 파일 시스템
파일 시스템 구조
- 부트 섹터(boot sector) : 섹터 1개, 운영체제 초기 코드를 적재하고 실행시키는 코드
- FAT1, FAT2 : FAT(File Allocation Table)는 파일 블록들의 할당 테이블 / FAT2는 FAT1의 복사본
- 루트 디렉토리 : 고정 크기이므로 루트 디렉토리에 생성되는 파일이나 서브디렉토리의 개수는 유한
- 데이터 블록들 : 파일 블록들이 저장되는 곳. 파일은 블록들로 분할되어 분산 저장
디렉토리
- 파일이나 서브 디렉토리의 목록을 담은 특수 파일 / 파일 이름은 8.3형식 – 이름 최대 8글자, 확장자 3글자
- 디렉토리 항목 : 32바이트 크기로 한 파일에 대한 메타 정보 저장
- 루트 디렉토리나 서브 디렉토리의 구조 동일
FAT 파일 시스템의 파일 블록 저장
- 파일 데이터를 블록 단위로 디스크에 분산 저장
- 파일 메타 데이터는 디렉토리에 저장
- 저장된 파일 블록들의 위치는 FAT 테이블에 기록
FAT 테이블
파일 시스템에 생성된 모든 파일에 대해, 저장된 파일 블록 번호들이 담겨 있는 테이블
FAT 테이블 항목
- 디스크 블록 번호는 FAT 항목 번호와 동일
- FAT 항목에는 다음 디스크 블록 번호 저장 (다음 FAT 항목을 가리킴)
- FAT 항목에 저장된 번호가 -1이면 파일 끝을 나타냄
- FAT 항목에 저장된 번호가 0이면 빈 블록을 나타냄
- FAT 항목들은 연결 리스트로 연결됨
- FAT가 손상되면 심각한 문제 (FAT2 백업으로 해결)
파일이 저장된 모든 블록 알아내기
- 먼저 파일이 포함된 디렉토리 항목 검색
- 디렉토리 항목에는 해당 파일이 시작되는 FAT 항목 번호가 저장
- 디렉토리 항목에는 해당 파일의 크기가 저장되어 있음
- 디렉토리 항목(파일 크기와 파일 시작 블록 번호)을 이용하여 FAT 테이블을 연결 리스트 방식으로 검색하여 파일이 저장된 블록들을 알아냄
하나의 파일을 읽는 데 여러 번의 디스크 탐색(seek) 필요
파일이 여러 개의 블록으로 나뉘어 분산 저장되기 때문
예시
FAT 한 항목의 크기가 16비트, 블록이 4KB라면, FAT 파일 시스템이 저장할 수 있는 최대 데이터양
접근 가능한 총 블록 수 -> 2^16 - 2개=대략 2^16개 -> 216x4KB = 216x212 바이트 -> 256MB
2^16에서 2를 빼는 이유
- 0번과 1번을 제외
- 0번은 비어있는지 여부를 나타냄
- 1번은 혹시 모를 상황을 위해예약해 둔 번호
- 실제로는 2번부터 사용됨
UNIX 파일 시스템
파일 시스템 구조
- 부트 블록(boot block) : 부팅 시 메모리에 적재되어 실행되는 코드로, 운영체제를 적재하는 기능
- 수퍼 블록(super block) : 파일 시스템 메타 정보 저장
- i-node
- i-node : 파일 하나당 1개의 i-node 필요, 파일 메타 정보 저장 - i-node 리스트
- i-node 리스트 : i-node들의 테이블
- i-node 리스트의 크기는 포맷 시 결정. 포맷 후 i-node 개수는 고정
- 파일이 생성될 때마다 빈 i-node 할당, 파일 메타 정보 기록
- i-node 번호는 0부터 시작. 운영체제마다 첫 i-node 번호가 조금씩 다름
- 루트 디렉토리의 i-node 번호는 수퍼 블록에 기록. 리눅스의 경우 2, 유닉스의 경우 1
- 0번 i-node는 오류 처리를 위해 예약 - 데이터 블록 : 파일과 디렉토리가 저장되는 공간
수퍼 블록
- 파일 시스템의 크기와 상태 정보 (수퍼 블록의 수정 여부 등) - 파일 시스템 내의 자유 블록 수 / 자유 블록들의 리스트
- 자유 블록 리스트에서 요청 시 할당할 다음 블록 인덱스 / 파일 시스템 내의 i-node 리스트의 크기
- 파일 시스템 내의 자유 i-node 수 / 파일 시스템 내의 자유 i-node들의 리스트
- 파일 시스템 내의 자유 i-node 리스트에서 요청 시 할당할 다음 자유 inode 인덱스
- 파일 시스템의 논리 블록 크기 / 루트 디렉토리의 i-node 번호 / 수퍼 블록이 갱신된 최근 시간
i-node에 저장된 정보
- 디렉토리 항목 (16바이트)
- 디렉토리 블록과 디렉토리 항목, 그리고 i-node
Unix 파일 시스템의 파일 블록 배치
- Unix 파일 시스템은 파일을 블록 단위로 분산 배치
- i-node에 15개 인덱스를 두고 파일 블록들의 위치 정보 저장
- 12개의 직접 인덱스: 12개의 파일 블록 번호, 파일의 앞부분 12개 블록 가리킴
- 12개의 직접 인덱스로 가리킬 수 있는 파일 크기: 12x4KB = 48KB - 1개의 간접 인덱스: 파일 크기가 12개의 블록을 넘어갈 때 사용
- 인덱스가 가리키는 한 개의 디스크 블록에 파일 블록 번호들이 들어 있음
- 한 블록이 4KB이고, 블록 번호가 32비트(4바이트)일 때
- 간접 인덱스로 가리킬 수 있는 파일 블록 수 : 4KB/4B = 1024블록, 파일 크기는 1024 x 4KB = 4MB - 1개의 2중 간접 인덱스
- 2중 간접 인덱스로 가리킬 수 있는 파일 블록 수 : (1024 x 1024)블록
- 2중 간접 인덱스로 가리킬 수 있는 파일 크기 : 1024 x 1024 x 4KB = 4GB - 1개의 3중 간접 인덱스
- 3중 간접 인덱스로 가리킬 수 있는 파일 블록 수 : (1024 x 1024 x 1024)블록
- 3중 간접 인덱스로 가리킬 수 있는 파일 크기 : 1024 x 1024 x 1024 x 4KB = 4TB - Unix 파일 시스템에서의 파일 최대 크기
- 48KB + 4MB + 4GB+ 4TB
파일의 i-node 찾기
파일을 읽고 쓰기 위해 파일 블록들의 위치 파악 필요
파일 블록들의 위치는 i-node의 15개 인덱스를 통해 알 수 있음
그러므로 파일의 i-node를 먼저 찾아야 함
/usr/source/main.c 파일 찾는 과정
- 루트 디렉토리(/)의 i-node 번호 알아내기 : 루트 디렉토리의 i-node 번호는 수퍼 블록에 있음
- 루트 디렉토리(/)의 i-node 읽기 : 수퍼 블록에 적힌 루트 디렉토리의 i-node 번호로부터 i-node 읽기
- /usr의 i-node 알아내기
- /usr 디렉토리를 읽고 /usr/source 파일의 i-node 번호 알아내기
- /usr/source 디렉토리 읽고 /usr/source/main.c 파일의 i-node 번호 알아내기
- /usr/source/main.c 파일 읽기
파일 입출력 연산
커널은 파일 입출력을 위한 시스템 호출 함수 제공
- open( ), read( ), write( ), close( ), chmod( ), create( ), mount( ), unmount( ) 등
파일 찾기
- 파일의 경로명으로부터 파일의 i-node 찾기
- i-node에 파일 타입, 접근 권한, 파일 데이터가 담겨 있는 블록 번호 등이 저장되어 있기 때문
- 파일 입출력을 위한 시스템 호출은 커널에 의해 수행
파일 열기 과정
- 파일 이름으로 i-node 번호 알아내기 : 파일이 존재하지 않거나 접근 권한이 허용되지 않으면 오류 리턴
- 디스크 i-node를 커널 메모리의 i-node 테이블에 적재
- 오픈 파일 테이블에 새 항목 만들기 : i-node 주소 기록
- 프로세스별 오픈 파일 테이블에 새 항목 만들기 : 프로세스별 오픈 파일 테이블에 항목 할당
파일 테이블의 주소 기록 - open()은 프로세스별 오픈 파일 테이블 항목 번호 리턴
- 프로세스별 오픈 파일 테이블의 항목 번호(정수) 리턴
- 응용프로그램이 open()으로부터 리턴 받은 정수는 프로세스별 오픈 파일 테이블 항목 번호임
(이 정수를 파일 디스크립터(file descriptor)라고 부름) - 응용프로그램은 파일 입출력 시 파일 디스크립터를 사용
파일 열기 후 형성되는 커널 내 구조
파일 읽기 과정
- read(fd,...)는 fd 번호의 프로세스별 오픈 파일 테이블 참조
- 파일 테이블 참조 : R 모드(읽기 허용)가 아닌 경우 오류로 리턴
- i-node 참조 : i-node에서 파일 블록들의 리스트 확보
파일 테이블 항목에 적힌 offset 확인 / offset을 파일 블록 번호로 변환 - 해당 블록이 버퍼 캐시에 있는지 확인
- 해당 블록이 버퍼 캐시에 없으면, 버퍼 캐시를 할당받고 디스크에서 버퍼 캐시로 읽기
- 할당받은 버퍼 캐시가 dirty이면 버퍼 캐시에 들어 있는 블록을 디스크에 쓰기 - 버퍼 캐시로부터 사용자 영역으로 블록 복사
파일 쓰기 과정
- write(fd,...)는 fd 번호의 프로세스별 파일 테이블을 참조
- 파일 테이블 참조 : W 모드(쓰기 허용)가 아니면 오류로 리턴
- i-node 참조 : i-node에서 파일 블록들의 리스트 확보
파일 테이블 항목에 적힌 offset 확인 / offset을 파일 블록 번호로 변환 - 해당 블록이 버퍼 캐시에 있는지 확인
- 해당 블록이 버퍼 캐시에 있으면, 사용자 영역에서 버퍼 캐시에 쓰기
- 해당 블록이 버퍼 캐시에 없으면, 버퍼 캐시를 할당받고 디스크 블록을 버퍼 캐시로 읽어 들이기 - 사용자 공간의 버퍼에서 버퍼 캐시로 쓰기
- 추후 버퍼 캐시가 교체되거나 플러시 될 때, 버퍼 캐시의 내용이 저장 장치에 기록
파일 닫기 과정
- 프로세스의 오픈 파일 테이블 항목에 기록된 내용 지우기
- 프로세스의 오픈 파일 테이블 항목을 지우기 전, 파일 테이블의 항목을 찾고 (지우고) 반환하기
- 파일 테이블 항목을 반환하기 전, 메모리 i-node의 사용 해제
- 버퍼 캐시에 있는 이 파일의 블록들이 수정되었거나 새로 만든 블록인 경우 디스크에 기록
'Operating System [OS]' 카테고리의 다른 글
[OS] 11.Mass-Storage Systems (1) | 2024.01.03 |
---|---|
[OS] 10. File System Implementation (1) | 2024.01.03 |
[OS] 08. Deadlocks (1) | 2024.01.02 |
[OS] 07. Synchronization Tools (1) | 2024.01.02 |
[OS] 06. Threads & Concurrency (2) | 2024.01.02 |