입출력장치: 입력으로는 , 몇 번 블록을 읽어라. 출력은 하드웨어에 맞는 기계적 명령이다.
장치드라이버들로 이루어져 있을 듯.
기본 파일 시스템 : 블록입출력 서브시스템, 적절한 장치 드라이버에게 명령을 내리는 층.
논리블록주소를 기반으로 드라이버에게 명령을 내린다.
버퍼/캐시 등도 관리한다.
file-org-module : 파일과 상응하는 논리블록을 알고 있다.
논리파일시스템 : 실질적으로 보이는 파일들.
파일구조는 FCB(INODE)같은 것으로 구현된다.
부트 제어 블록
부트관련
볼륨제어블록
블록의 수, 블록의 크기, 가용블록의 수 등 관리정보를 가진다.
슈퍼블록(UFS), 혹은 NTFS(마스터 파일 테이블)
디렉터리구조
INODE에서는 그냥 파일에
NTFS에서는 마스터파일테이블에
파일에 대한 자세한 정보
INODE에서는 INODE안에
NTFS에서는 마스터 파일 테이블 안에
논리적 파일 시스템에 파일 이름을 넘긴다
글로벌 파일테이블이 열려있는지?를 확인한다.
안 열려있으면, 주어진 파일 이름을 디렉터리에서 찾고,
그거 에 대한 FCB를 가지고 온다.
그리고 글로벌 파일 테이블에 이걸 연다.
그 후, 접근 모드나 포인터 항목에 대한 거를 채워서 프로세스 파일 테이블에 연다.
오픈을할때캐싱하네
그리고, 해당 파일테이블의 포인터를 리턴한다.
Start + Length로 구현한다.
순차적으로 저장되는게 진짜 개 큰일 아니겠니?
외부단편화,,
파일 직접접근 가능
순차접근은 존내좋은데
외부단편화도 없다.
직접 접근은 정말 큰일난다.
클러스터 기법
그냥 블록 4개 쌍으로 I /O
포인터 적게 참조하므로 개이득
하지만 내부단편화
게다가 작은 데이터들을 다룰 떄는 비효율 적일수도 있따.
신뢰성의 문제가 있을 수 있다.(포인터가 끊기면 폭망)
한가지 중요한 변형인 FAT
그냥 진짜 저거만 가지고 메모리에다가 주소만 넣어 놓는 것.
엄청난 램 소모량 예상된다.
요게 아이노드랑 비슷하다 이말이지
크기가 제한적이기에 여러가지 기법을 이용한다
연결기법, 101번째는 다음 블록인거
다중 수준 색인, 그냥 첫번째 보이는 거는 다음 레벨의 블록을 가리키게 되는
12개는 직접, 3개는 간접
→아이노드
블록이 비면 1, 채워지면 0
메인 메모리에 이게 다 올라와 있어야 함.
모든 공간에 대해 이거를 가지고 있다는 것이 비효율적일듯
입출력장치들은 블록에 대한 캐시를 가지고 있다.
따라서, 회전지연 기다리지 않아도 데이터를 fetch할 수 있다.
페이지캐시를 하면
굉장히 빠르게 쓰기를 할 수 있다. 나중에 실제로 디스크에 대입하면 되니까.
페이지 캐시 최적화
블록 미리 읽기 정책 사용 가능
k번째 블록을 읽어 오면, k+1도 읽어 올 수 있따.
물론 순차 파일에만 효과
따라서, 랜덤 파일의 경우는 사용 X
일부는 페이지캐시(파일자체를 페이지에캐시해서 빨리쓰기)
read,wrtie 입출력을 하기 위해서는, 실제 드라이버에 꽂히는 버퍼캐시가 필요하게 된다.
그러기 위해선, 페이지캐시가 버퍼캐시로 가야 된다는 것.
그러면, 결국 이중캐싱이 되고 개손해가 된다.
그러니까, 이거 두개를 합쳐서 하나의 캐시로 만들어야지 손해가 덜하다.
sequential writing을 지원하기 위함
먼저 메모리에 버퍼링하고,
어느 정도 세그먼트가 차면 이를 블록에 저장한다. 그리고 이 때, 새로운 inode 블록의 위치를 함께 저장한다. 만약 writing이 일어난다면, inode에 갱신이 일어나고 이 복사본이 다른 inode 블록에 지정된 후 포인터가 지정될 것이다.
inode가 고정된 위치에 있지 않기 때문에, inode 블록의 위치를 지정하는 inode map이 따로 있다.
메모리에 쓰기가 발생할 때 마다, 해당하는 inode의 포인터들을 아이노드 맵에 저장합니다. 이렇게 떨어진 애들을 관리하기 위해서, 하나의 아이노드 체크포인트가 있고, 이거는 모두 메모리에 저장될만큼 작다.
할당이 풀린 애들은,
copying으로 한 곳으로 밀어넣던ㄷ가, 아니면 구멍이 뚫린 곳을 연결리스트로 이어서 사용한다.
새그먼트클리닝(외부단편화 최소)
클리너쓰레드가 존재해서, 아이노드를 모두 검사해 현재 해당 블록이 유효한 블록인지를 검사하고, 만약 해당 새그먼트(아이노드 맵 + 블록)의 정보가 현재 유효하지 않다면, 제거한다.
파일 삭제 시 상황을 확인하자.
1,2 와 2,3 사이에서 crash가 일어난다고 하면,
1~2 : inode가 낭비되고, 파일은 확인이 안 된다.
2~3 : inode는 없어지고, 블록에서 확인이 불가능 하다.
그렇기에, JFS에서는 1,2,3을 로그를 다 써 놓는다. 그리고 만약 크래쉬가 일어나면, 그냥 1,2,3을 다 다시 한다. 이렇게 다시 해도 전혀 문제가 없는 연산이여야 한다.
그리고 1,2,3을 완전 끝내면, 로그를 지운다.
그림 4-27와 같이,
두개의 array를 만들어 일일이 블록을 검사한다.
하나는 inode에서 가용한 블록을 하나씩 찍는 것
나머지 하나는 free block에서 하나씩 찍는 것
두 개가 매칭이 안되면 문제있다.
기본적으로 아이노드 방식이다.
디스크의 논리-물리블록 번호를 이런 식으로 매핑해서, sequential read 성능을 극대화 했다.
fragmentation을 이용해서(블록보다 더 작은 단위) 메모리 버리는 걸 최소화했다.
기존 슈퍼블록 기반의 S5FS에서 발견되었던, 슈퍼블록이 깨지면 큰일나는 문제 해결
아이노드 블록을 새 디렉토리는 멀리, 가까운친구들은 가까이 배치했다.
→ 여러 곳에 분산 배치. 실린더 그룹별로 분산 배치
디렉토리 내의아이노드를 확인하기 위해 너무 긴 시간이 걸렸던 문제를 해결했다.
→ ls -l 시, 곳곳에 흩어져있는 아이노드를 다 읽어야 하기 때문에 엄청난 성능 저하.
→ 디렉토리 내의 아이노드는 인접 실린더 그룹에 배치
아이노드에 대한 테이블과, 실제 데이터를 비슷한 곳(실린더 그룹)에 배치아이노드에 대한 테이블과, 실제 데이터를 비슷한 곳(실린더 그룹)에 배치
실린더 그룹이 아니라, 블록 그룹으로 나누었다.
실린더 그룹으로 나누게 되면, 실린더 그룹마다 용량이 다르기 때문에 적절하지 않다.
블록들은 1,2,4,8KB등 다양하다
파일 할당 시, 블록그룹을 선택하자. 아이노드는 블록그룹 내에 존재하고, 할당도 동일블록그룹으로 간다.
디스크 부하를 줄이기 위해 디렉터리를 널리 분산시키는 일이 많다.
먼저 가용 바이트를 찾고, 실패하면 그 다음에 가용 비트를 찾는다.
바이트 단위로 할당을 하기 위함.
그냥 쭉쭉 찾는다.
e2fsck가 확장버전이기 때문에 실질적으로 현재 리눅스 배포판에서 fsck명령 실행하면 e2fsck가 실행돼요.
fask명령은 손상된 디렉터리나 파일을 수정할 때 임시로 /lost+found 디렉터리에서 작업을 수행하고 정상적인 복구가 되면 사라집니다.
fsck 명령어를 수행하면 내부적으로 동작 단계는 다음과 같습니다.
https://t1.daumcdn.net/cfile/tistory/997C86455C48CBE20F
시작
단계1 - 블록들과 파일 크기 검사
단계2a - 중복된 이름이 있는지 검사
단계2b - 경로명 검사
단계3 - 연결성 검사
단계3b - Shadows/ACLs 인증
단계4 - 참조 수 검사
단계5 - 싸이클 그룹 검사