※ 이 글은 Project 4를 구현중인 불확실과 추론의 영역입니다.
특히 이부분은 다른 곳을 구현하면서 수정할 여지가 높은 곳입니다.
착한 어린이들은 따라하지 마세요.
※ fat.c 공부때랑 좀 달라진 곳이 많다. 혹시나 참고하셨던분들은 죄송합니다. ㅎㅎ;;
void
fat_fs_init (void) {
/* TODO: Your code goes here. */
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
fat_fs->fat = NULL;
fat_fs->fat_length = fat_fs->bs.fat_sectors;
fat_fs->data_start = fat_fs->bs.fat_start+fat_fs->bs.fat_sectors;
fat_fs->last_clst = fat_fs->bs.total_sectors-1;
lock_init(&fat_fs->write_lock);
/* ---------------------------- << Project.4 FAT << ---------------------------- */
}
fat_fs를 초기화하는 곳이다.
fat은 fat_create에서 따로 받을 것이기 때문에 NULL을 지정하겠다.
fat_length는 filesystem disk안에 들어가는 disk sector들의 총 갯수이다. 이를 fs_boot에서 받아오자.
data_start는 실제 데이터가 들어가는 곳인데, 여기에 FAT을 포함시켜야되는지 고민이 많았다.
현재 내가 생각하고 있는 sector배치는
0 : fs_boot 구조체
1 : root_directory
2 ~ x : FAT
x+1 ~ : 실제 data
로 생각하고 있기 때문에, 2에 fat_stasrt, x+1에 data_start가 들어갈 예정이다. 다행히, FAT의 (섹터 단위) 크기는 fa_sectors에 저장되어있기 때문에 fat_start + fat_sectors로 하면 실제 data의 시작 sector index가 들어갈 것 같다.
last_clst 는 아직 미정인데, 현재는 disk가 보유하고 있는 sector 중 마지막 sector를 가리키는 걸로 할까 싶다. 나중에 바뀔수도 있겠지만, 일단은 이렇게 하자. (-1을 한 이유는 array의 인덱스를 가리키고 있기 때문이다.)
lock_init 으로 wrtie_lock을 설정하자.
그리고 나는 빈 섹터들을 하나의 linked list로 묶을 생각이다. fat_create()에 구현해놓자.
void
fat_create (void) {
// Create FAT boot
fat_boot_create ();
fat_fs_init ();
// Create FAT table
fat_fs->fat = calloc (fat_fs->fat_length, sizeof (cluster_t));
if (fat_fs->fat == NULL)
PANIC ("FAT creation failed");
// Set up ROOT_DIR_CLST
fat_put (ROOT_DIR_CLUSTER, EOChain);
// Fill up ROOT_DIR_CLUSTER region with 0
uint8_t *buf = calloc (1, DISK_SECTOR_SIZE);
if (buf == NULL)
PANIC ("FAT create failed due to OOM");
disk_write (filesys_disk, cluster_to_sector (ROOT_DIR_CLUSTER), buf);
free (buf);
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
uint32_t i = 0;
for (i ; i < fat_fs->last_clst ; i++)
{
fat_fs->fat[i] = i+1;
}
fat_put(0, EOChain);
fat_put(1, EOChain);
fat_put(fat_fs->bs.fat_start+fat_fs->bs.fat_sectors-1, EOChain);
fat_put(fat_fs->last_clst, EOChain);
/* ---------------------------- << Project.4 FAT << ---------------------------- */
}
이렇게 하면, data_start부터 끝까지 하나의 linked list가 구현되고, 마지막은 EOC이 새겨진다.
일단, 처음부터 끝까지 하나의 연결리스트를 구현하고, EOC를 박는걸로 chain을 끊어주자.
이러면, fat은 하나의 chain이 되고, 빈 블록들도 하나의 chain이 된다.
생각해보니 free_blocks들의 갯수로 저장해놔야할 것 같다. 이도 구현놓자.
/* 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;
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
unsigned int init_free_blocks;
/* ---------------------------- << Project.4 FAT << ---------------------------- */
};
void
fat_boot_create (void) {
unsigned int fat_sectors =
(disk_size (filesys_disk) - 1)
/ (DISK_SECTOR_SIZE / sizeof (cluster_t) * SECTORS_PER_CLUSTER + 1) + 1;
fat_fs->bs = (struct fat_boot){
.magic = FAT_MAGIC,
.sectors_per_cluster = SECTORS_PER_CLUSTER,
.total_sectors = disk_size (filesys_disk),
.fat_start = ROOT_DIR_CLUSTER + 1,
.fat_sectors = fat_sectors,
.root_dir_cluster = ROOT_DIR_CLUSTER,
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
// free_blocks = total_sectors - fat_sectors - boot_sector - root_dir - head and taile
.init_free_blocks = disk_size (filesys_disk) - fat_sectors - 4
/* ---------------------------- << Project.4 FAT << ---------------------------- */
};
}
fat_boot에 init_free_blocks를 추가해놓고 초기 값을 넣어준다.
이는 전체 섹터 - FAT의 섹터 - ROOT_DIR 섹터 - BOOT 정보 섹터 - free_list의 HEAD 블록 (data_start) - TAIL 블록 (last_clst) 로 계산했다.
그러면 fat_fs_init()도 수정해야한다.
/* FAT FS */
struct fat_fs {
struct fat_boot bs;
cluster_t *fat;
unsigned int fat_length;
disk_sector_t data_start;
cluster_t last_clst;
struct lock write_lock;
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
unsigned int free_blocks;
/* ---------------------------- << Project.4 FAT << ---------------------------- */
};
void
fat_fs_init (void) {
/* TODO: Your code goes here. */
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
fat_fs->fat = NULL;
fat_fs->fat_length = fat_fs->bs.total_sectors;
fat_fs->data_start = fat_fs->bs.fat_start+fat_fs->bs.fat_sectors;
fat_fs->last_clst = fat_fs->bs.total_sectors-1;
lock_init(&fat_fs->write_lock);
fat_fs->free_blocks = fat_fs->bs.init_free_blocks;
/* ---------------------------- << Project.4 FAT << ---------------------------- */
}
fat_fs_init()에서 초기값을 넣어준다.
그러고보니 빈 블록 리스트에서 빈 블록을 하나 가져오는 함수를 만들어야할 것 같다.
함수를 만들어보자.
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
cluster_t
get_free_cluster(void)
{
cluster_t start = fat_fs->data_start;
cluster_t free_clst = fat_get(start);
if (free_clst == fat_fs->last_clst)
{
return -1;
}
cluster_t start_next = fat_get(free_clst);
fat_put(start, start_next);
fat_put(free_clst, EOChain);
fat_fs->free_blocks -= 1
return free_clst;
}
/* ---------------------------- << Project.4 FAT << ---------------------------- */
data_start는 항상 고정이다. 그리고 이 다음 블록부터 할당하도록 할 것이다. 그리고 할당한 뒤에는 끊어버린다.
만약 free_clst에 last_clst가 들어왔다면, 더 이상 할당할 수 없다는 말이니 -1을 반환하자.
만약 이 상위 함수에서 free_clst가 필요없어지면 다시 free_block_list에 붙이는 것을 잊지 말자. 그리고 새로운 free_block을 넣을 때는 data_start 바로 뒤에 붙이자. (last_clst가 항상 마지막에 있어야하기 때문에)
/* 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. */
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
cluster_t new = get_free_cluster();
if (new == -1)
{
return 0;
}
if(clst != 0){
fat_put(clst, new);
}
return new;
/* ---------------------------- << Project.4 FAT << ---------------------------- */
}
우선 chain을 새로 만들거나 늘리는 과정이다. clst에 어떤 clst가 들어오는지 헷갈리는데, file의 시작 clst가 들어오는지, 마지막 clst가 들어오는지 아니면 임의의 clst가 들어오는 지 애매하다.
범용성을 위해서 임의의 clst가 들어오고, 만약 이 clst가 chain의 중간 clst라 하더라도, 상위함수에서 이미 chain을 끊어놓은 상태라고 가정한다. 즉, clst는 '현재' chain의 마지막 clst라고 가정한다.
만약 free_clst를 할당하는데 실패한다면 0을 반환한다.
할당에 성공하고, clst가 0이라면 새로운 chain을 만들고, 아니라면 clst에 free_clst를 이어준다.
/* Remove the chain of clusters starting from CLST.
* If PCLST is 0, assume CLST as the start of the chain. */
void
fat_remove_chain (cluster_t clst, cluster_t pclst) {
/* TODO: Your code goes here. */
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
if (pclst != 0)
{
fat_put(pclst, EOChain);
}
cluster_t start = fat_fs->data_start;
cluster_t start_next = fat_get(start);
cluster_t cur = clst;
cluster_t next = fat_get(cur);
fat_put(cur,start_next);
fat_put(start, cur);
fat_fs->free_blocks += 1;
while (next != EOChain)
{
cur = fat_get(next);
start_next = fat_get(start);
fat_put(next, start_next);
fat_put(start, next);
fat_fs->free_blocks += 1;
}
/* ---------------------------- << Project.4 FAT << ---------------------------- */
}
fat_remove_chain은 이렇게 이해했다.
plcst와 clst를 끊어서, plcst로 끝나는 한 체인과, clst로부터 시작하는 한 체인을 만드는 것이라고 생각했다.
생각해보니 chain을 끊어서 두개로 만드는 것이면, 그냥 pclst에 EOC를 넣으면 끝이다.
아마 file삭제나 수정을 위해서 clst부터 cluster를 삭제하는 함수인 것 같다.
그리고 삭제한 cluster는 free_block_list에 넣는다.
/* Update a value in the FAT table. */
void
fat_put (cluster_t clst, cluster_t val) {
/* TODO: Your code goes here. */
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
fat_fs[clst] = val;
/* ---------------------------- << Project.4 FAT << ---------------------------- */
}
/* Fetch a value in the FAT table. */
cluster_t
fat_get (cluster_t clst) {
/* TODO: Your code goes here. */
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
return fat_fs[clst];
/* ---------------------------- << Project.4 FAT << ---------------------------- */
}
/* Covert a cluster # to a sector number. */
disk_sector_t
cluster_to_sector (cluster_t clst) {
/* TODO: Your code goes here. */
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
return clst;
/* ---------------------------- << Project.4 FAT << ---------------------------- */
}
나머지는 간단하니 함수로 표현하겠다. 나중에 생각나면 예외처리도 덧붙여야겠다.
+추가사항+
fat_fs는 static이라 다른 파일에서 호출할 수 없다.
free_blocks를 관리하기 위해 함수를 하나 만든다.
/* ---------------------------- >> Project.4 FAT >> ---------------------------- */
size_t
ctrl_free_blocks_EA(uint32_t a)
{
fat_fs->free_blocks += a;
return fat_fs->free_blocks;
}
/* ---------------------------- << Project.4 FAT << ---------------------------- */
a를 넣으면, free_blocks에 a를 더하고 free_blocks를 반환한다.
만약 a에 0을 넣으면 free_blocks를 그대로 반환할 것이다.
'Pintos Project > Project 4' 카테고리의 다른 글
[PintOS, Project 4] Filesys.c 구현 (0) | 2021.03.04 |
---|---|
[PintOS, Project 4] inode.c 구현 (0) | 2021.03.04 |
[PintOS, Project 4] inode.c 공부 (2) | 2021.03.04 |
[PintOS, Project 4] fat.c 공부 (2) | 2021.03.03 |
[PintOS, Project 4] Indexed and Extensible Files (0) | 2021.03.02 |
댓글