우리는 이전까지 virtual memory 까지 구현하였다.
하지만 구현하면서 filesys 부분은 신경쓰지 않고 그냥 가져다 사용하였다.
이제 우리는 filesys directory를 수정할 것입니다.
project 2를 base로도 사용 가능하고
project 3를 base로도 사용 가능함
이론적인 부분은 아래를 참조하세요
FAT entry 는 0번, 1번 index는 사용하지 않습니다.
0번은 media type, 1번은 partition type 으로 정의가 되어있습니다.
이론 1: https://hec-ker.tistory.com/268
이론 2: http://forensic-proof.com/archives/378
partition type : https://en.wikipedia.org/wiki/Partition_type


Make.vars 를 아래와 같이 수정하면 project 3를 base로 make를 진행할 수 있다.
#Uncomment the lines below to enable VM.의 아래 부분의 주석을 지우면된다.
# -*- makefile -*-
os.dsk: DEFINES = -DUSERPROG -DFILESYS -DEFILESYS
KERNEL_SUBDIRS = threads devices lib lib/kernel userprog filesys
KERNEL_SUBDIRS += tests/threads tests/threads/mlfqs
TEST_SUBDIRS = tests/threads tests/userprog tests/filesys/base tests/filesys/extended
GRADING_FILE = $(SRCDIR)/tests/filesys/Grading.no-vm
# Uncomment the lines below to enable VM.
os.dsk: DEFINES += -DVM
KERNEL_SUBDIRS += vm
TEST_SUBDIRS += tests/vm tests/filesys/buffer-cache
GRADING_FILE = $(SRCDIR)/tests/filesys/Grading.with-vm
그리고 우리는 지금까지 Pintos 를 한번만 실행시켰습니다.
하지만 file system의 중요 목적은 재부팅시에도 같은 데이터에 계속 접근 가능하도록 보장하는 것입니다.
따라서 지금부터는 Pintos를 두번 실행 시킵니다.
두 번째 실행에서 file system의 모든 파일과 디렉토리를 하나의 파일로 결합하고,
해당 파일을 핀토스 파일 시스템에서 호스트(Unix)의 file system으로 복사
이제부터는 구현을 하도록 하겠습니다.
구현을 하기 위해서는 fat_fs와 fat_boot 의 structure에 대해서 알아야합니다.
사전에 fat_fs와 fat_boot는 정의가 되어있고 우리는 이를 사용하기만 하면 됩니다.
/* Should be less than DISK_SECTOR_SIZE */
struct fat_boot {
unsigned int magic;
unsigned int sectors_per_cluster; /* Fixed to 1 */
unsigned int total_sectors;
unsigned int fat_start;
unsigned int fat_sectors; /* Size of FAT in sectors. */
unsigned int root_dir_cluster;
};
/* FAT FS */
struct fat_fs {
struct fat_boot bs;
unsigned int *fat;
unsigned int fat_length;
disk_sector_t data_start;
cluster_t last_clst;
struct lock write_lock;
};
static struct fat_fs *fat_fs;

fat_fs_init 에서는 length와 data_start에 대해서 정의해줘야함.
length는 sector의 수를 나타냄(FAT index의 전체 개수)
data_start는 data_block의 시작점
void
fat_fs_init (void) {
/* TODO: Your code goes here. */
// length에는 file system에 몇개의 클러스터 있는지에 대한 정보
// fat_fs는 이미 선언이 되어있고 그 안에 여러 Member 들이 선언되어있음
// FAT의 섹터 수 X 512bytes / cluster 당 sector 수
fat_fs->fat_length = fat_fs->bs.fat_sectors*DISK_SECTOR_SIZE/(sizeof(cluster_t)*SECTORS_PER_CLUSTER);
fat_fs->data_start = fat_fs->bs.fat_start + fat_fs->bs.fat_sectors;
}
fat[clst] 에 value를 넣음
/* Update a value in the FAT table. */
void
fat_put (cluster_t clst, cluster_t val) {
/* TODO: Your code goes here. */
fat_fs->fat[clst] = val;
}
fat[clst] 의 value를 return 함
/* Fetch a value in the FAT table. */
cluster_t
fat_get (cluster_t clst) {
/* TODO: Your code goes here. */
return fat_fs->fat[clst];
}
data_start + clst 로 sector 의 시작점을 이동함
/* Covert a cluster # to a sector number. */
disk_sector_t
cluster_to_sector (cluster_t clst) {
/* TODO: Your code goes here. */
return fat_fs->data_start + clst;
}
cluster chain을 만듦
/* Add a cluster to the chain.
* If CLST is 0, start a new chain.
* Returns 0 if fails to allocate a new cluster. */
cluster_t
fat_create_chain (cluster_t clst) {
/* TODO: Your code goes here. */
// 클러스트를 추가하여 체인을 확장할 수 있다
// 클러스트는 무엇으로 관리하는가? linked_ list로 하는데
// 이걸 전역변수? 아니면 다른걸로 해야하나?
cluster_t i =2; // 왜냐면 FAT entry에 0, 1은 사전에 할당되어있음. 0 = media type, 1 = partition status로 우리가 직접 수정하는 부분은 아님
while(fat_get(i) != 0 && i < fat_fs->fat_length){ // i는 2부터 순회하며 fat_length 크기보다 작은 구간에서 i를 찾음
++i;
}
if (i == fat_fs->fat_length) // 만약 i 가 전체 크기와 FAT_entry의 크기와 같다면 0을 return 함
return 0;
fat_put(i, EOChain); // i번 clust에 EOChain 값을 넣음
if(clst == 0 ) // input된 값이 0 이라면
return i; // i를 그냥 return 해버림 --> i를 가지고 새로운 chain을 create 할거니깐
while(fat_get(clst) != EOChain){ // 그게 아니라면 fat_get을 통해서 얻은 value가 EOChain이 아니라면 계속 순회 하면서 끝을 찾아 갈 것임
clst = fat_get(clst);
}
fat_put(clst, i); // clst에 i 값을 넣음
return i; // 그리고 i 를 return 함
}
여기까지 구현이 완료되면 Project 1은 pass가 뜰 것입니다.
