[정글93일차]Pintos Project4(filesystem) WIL

김희산·2022년 12월 20일

개요

  1. FAT
  2. filesys_create() 안에서 작동되는 코드중에 의문점이 생긴 부분 ( subdirectories part ) 정리

Allocation of File Data in Disk

1. Contiguous Allocation(연속 할당)

- 하나의 파일이 디스크 상에 연속으로 저장되는 방식.
    

  • 파일의 크기에 따라 블록(하나 이상의 섹터)이 연속으로 할당되어 있음
  • 디렉토리 → 파일의 이름, 위치, 길이 정보
  • 단점
  • 외부 단편화 발생
  • file growth 어려움 → grow 할 공간 미리 확보 ? → grow 가능 but 내부단편화

2. Linked Allocation(링크로 연결 할당)

  • externel fragmentation 발생하지 않음
  • 임의접근 성능 ⬇️
  • Reliability 문제
  • 만약 bad sector 발생 → bad sector 이후 sector 접근 불가

→ Linked Allocation 기반 File-allocation table(FAT) 파일 시스템 도입


FAT

  • 디스크 포맷시 블록(클러스터)를 제어하는 테이블을 만들어 놓은 것
  • 보통 한 섹터당 512byte , 섹터를 하나 이상으로 묶은 단위가 블록(클러스터( 1 sector = 1 cluster in pintos))
  • 디렉토리 엔트리에 start block과 next block이 명시
  • FAT는 메모리에 캐시될수 있어서 기존 Linked Allocation 보다 탐색속도가 빠름

filesys_create()

Here you can see inline code.

The following is a code block:

  • file_name 을 입력받은 경로(name)만큼 할당받는가?
bool filesys_create(const char *name, off_t initial_size)
{
	char *path_name = (char *)malloc(strlen(name) + 1);
	strlcpy(path_name, name, strlen(name) + 1);

	***char *file_name = (char *)malloc(strlen(name) + 1);
	// 현재 디렉토리의 파일 실행한다는 최악의 상황 고려***

	struct dir *dir = ***parse_path(path_name, file_name);***

	cluster_t new_cluster = fat_create_chain(0); 
	if (new_cluster == 0)
		return false;
	disk_sector_t inode_sector = cluster_to_sector(new_cluster);

	
	bool success = (dir != NULL && inode_create(inode_sector, initial_size, 0)
 && *dir_add(dir, **file_name**, inode_sector));*
	// dir_add : 할당받은 sector에 file_name의 디렉토리 생성
	if (!success)
	{
		fat_remove_chain(new_cluster, 0);
	}

	dir_close(dir);
	free(path_name);
	free(file_name);
	return success;
}

→ file_name의 길이가 name보다 커질 수는 없고 name에 경로가아닌 파일이름만 들어왔을경우 file_name의 길이가 name의 길이랑 같음.

이러한 경우를 고려해서 메모리가 조금 낭비되더라도 인자로 받는 *name 만큼 할당받는다고 생각했음

보통 ex) /a/b/c/file.c

ex ) hello.c

parse_path()

  • parse_path() 함수의 반환값은 dir 인데 parsing된 값을 복사한 file_name은 어디서 사용되는가?
struct dir *parse_path(char *path_name, char *file_name)
{
	struct dir *dir;
	struct inode *inode;

	if (path_name == NULL || file_name == NULL)
		goto fail;

	if (strlen(path_name) == 0)
		return NULL;

	if (path_name[0] == '/'){
		dir = dir_open_root();
	}
	else{
		dir = dir_reopen(thread_current()->cur_dir);
	}

	char *token, *nextToken, *savePtr;
	token = strtok_r(path_name, "/", &savePtr);
	nextToken = strtok_r(NULL, "/", &savePtr);

	if (token == NULL){ 
		token = (char *)malloc(2);
		strlcpy(token, ".", 2);
	}

	while (token != NULL && nextToken != NULL)
	{
		if (!dir_lookup(dir, token, &inode))
		{
			dir_close(dir);
			return NULL;
		}

		if (inode_is_dir(inode) == 0)
		{
			dir_close(dir);
			inode_close(inode);
			return NULL;
		}

		dir_close(dir);

		dir = dir_open(inode);

		token = nextToken;
		nextToken = strtok_r(NULL, "/", &savePtr);
	}
	***// token(파일 이름)을 file_name에 저장
	strlcpy(file_name, token, strlen(token) + 1);***
	// dir 정보 반환
	return dir;
fail:
	return NULL;
}

→ filesys_create() 안에 dir_add()가 호출될 때 인자로 들어가서 할당받은 sector에 file_name의 디렉토리 생성

dir_add()

  • inode_read_at() → 구조체 멤버 업데이트 → inode_write_at() → 왜 inode_write_at() 을 하는지?
bool // dir_add : 할당받은 sector에 file_name의 디렉토리 생성
dir_add (struct dir *dir, const char *name, disk_sector_t inode_sector) {
	
	struct dir_entry e;
	off_t ofs;
	bool success = false;

	ASSERT (dir != NULL);
	ASSERT (name != NULL);

	/* Check NAME for validity. */
	if (*name == '\0' || strlen (name) > NAME_MAX)
		return false;

	/* Check that NAME is not in use. */
	if (lookup (dir, name, NULL, NULL)) // dir에 name을 가진 file이 있는지 확인
		goto done;

	/* Set OFS to offset of free slot.
	 * If there are no free slots, then it will be set to the
	 * current end-of-file.

	 * inode_read_at() will only return a short read at end of file.
	 * Otherwise, we'd need to verify that we didn't get a short
	 * read due to something intermittent such as low memory. */
	for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
			ofs += sizeof e)
		if (!e.in_use)
			break;

	/* Write slot. */
	e.in_use = true;
	strlcpy (e.name, name, sizeof e.name);
	e.inode_sector = inode_sector;

	success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e;

done:
	return success;
}

→ dir_add() 함수가 실행될때 디렉토리엔트리는 디스크에 있고 작업은 메모리상에서 하기 때문에 저장된 오프셋값을 이용해 수정사항을 다시 디스크에 업데이트해줘야 함.

profile
성공은 제로섬 게임이 아니라 주변인들과 함께 나아가는 것이다.

0개의 댓글