일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- System call
- Cow
- BFS
- Copy-on-write
- icon button
- pintos
- scaffold
- flutter
- create
- vm
- materialapp
- stack growth
- file
- algorithm
- widget
- Flutter
- Today
- Total
JunHyeok
[PintOS - Userprog] Create & Remove 본문
create
시스템 콜
create
bool create (const char *file, unsigned initial_size) {
is_valid_addr(file);
return filesys_create(file, initial_size);
}
create
시스템 콜 함수는 주어진 파일 이름(file
)과 초기 크기(initial_size
)를 사용하여 파일을 생성하는 시스템 콜입니다. 입력된 주소가 유효한지 확인한 후, filesys_create
함수를 호출하여 실제 파일을 생성합니다.
🤔 이 함수도 open, read와 같이 구현 자체는 정말 간단하다! 😼
2. filesys_create
/* Creates a file named NAME with the given INITIAL_SIZE.
* Returns true if successful, false otherwise.
* Fails if a file named NAME already exists,
* or if internal memory allocation fails. */
bool filesys_create (const char *name, off_t initial_size) {
disk_sector_t inode_sector = 0;
struct dir *dir = dir_open_root ();
bool success = (dir != NULL
&& free_map_allocate (1, &inode_sector)
&& inode_create (inode_sector, initial_size)
&& dir_add (dir, name, inode_sector));
if (!success && inode_sector != 0)
free_map_release (inode_sector, 1);
dir_close (dir);
return success;
}
filesys_create
함수는 파일 시스템에서 주어진 이름(name
)과 초기 크기(initial_size
)를 가진 파일을 생성합니다. 주요 과정은 다음과 같습니다:
- 루트 디렉토리를 엽니다.
- free map 에서 새로운 섹터를 할당합니다.
- 새 inode를 생성합니다.
- 디렉토리에 파일 이름을 추가합니다.
3. free_map_allocate
bool free_map_allocate (size_t cnt, disk_sector_t *sectorp) {
disk_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false);
if (sector != BITMAP_ERROR
&& free_map_file != NULL
&& !bitmap_write (free_map, free_map_file)) {
bitmap_set_multiple (free_map, sector, cnt, false);
sector = BITMAP_ERROR;
}
if (sector != BITMAP_ERROR)
*sectorp = sector;
return sector != BITMAP_ERROR;
}
free_map_allocate
함수는 free map 에서 연속적인 섹터를 할당하고, 첫 번째 섹터를 sectorp
에 저장합니다.
✅ 성공 시 true
❌ 실패 시 false
를 반환합니다.
4. inode_create
bool inode_create (disk_sector_t sector, off_t length) {
struct inode_disk *disk_inode = NULL;
bool success = false;
ASSERT (length >= 0);
disk_inode = calloc (1, sizeof *disk_inode);
if (disk_inode != NULL) {
size_t sectors = bytes_to_sectors (length);
disk_inode->length = length;
disk_inode->magic = INODE_MAGIC;
if (free_map_allocate (sectors, &disk_inode->start)) {
disk_write (filesys_disk, sector, disk_inode);
// Inode 생성 로직 ........
free(disk_inode)
}
inode_create 설명
- 메모리 할당
disk_inode = calloc (1, sizeof *disk_inode);
disk_inode
는 calloc
함수를 통해 메모리를 할당받습니다. calloc
은 메모리를 0으로 초기화하며, sizeof *disk_inode
크기만큼 할당합니다.
- 초기화
if (disk_inode != NULL) {
size_t sectors = bytes_to_sectors(length);
disk_inode->length = length;
disk_inode->magic = INODE_MAGIC;
할당받은 메모리가 NULL이 아닌지 확인한 후, 파일의 길이에 맞게 필요한 섹터 수를 계산합니다. 그리고 disk_inode
의 길이와 매직 넘버를 설정합니다.
- 섹터 할당 및 기록
if (free_map_allocate (sectors, &disk_inode->start)) {
disk_write (filesys_disk, sector, disk_inode);
free_map_allocate
함수를 호출하여 필요한 섹터를 할당받고, 성공하면 disk_write
함수를 사용해 디스크에 disk_inode
를 기록합니다.
메모리 해제
마지막에 free (disk_inode)
를 해주는 이유는 동적 메모리 할당 후, 사용이 끝난 메모리를 해제하여 메모리 누수를 방지하기 위함입니다.
왜냐하면 우리는 disk_write (filesys_disk, sector, disk_inode)
을 사용하여, disk에 기록했기 때문이죠! 🥳
disk_inode
를 동적으로 할당하고 초기화합니다.- 필요한 섹터를 할당받고, 할당이 성공하면
disk_write
합니다. disk_inode
의 사용이 끝난 후, 할당된 메모리를free
를 사용해 해제합니다.
5. dir_add
bool 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))
goto done;
/* Set OFS to offset of free slot. */
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
함수는 디렉토리에 파일 이름을 추가합니다.
- 이름의 유효성을 검사하고
(*name == '\0' || strlen (name) > NAME_MAX)
, - 디렉토리에 이미 같은 이름의 파일이 있는지 확인한 후
lookup (dir, name, NULL, NULL)
- 새로운 디렉토리 엔트리를 작성합니다.
Remove 시스템 콜
remove
bool remove(const char *file) {
is_valid_addr(file);
return filesys_remove(file);
}
filesys_remove
함수
/* Deletes the file named NAME.
* Returns true if successful, false on failure.
* Fails if no file named NAME exists,
* or if an internal memory allocation fails. */
bool
filesys_remove (const char *name) {
struct dir *dir = dir_open_root ();
bool success = dir != NULL && dir_remove (dir, name);
dir_close (dir);
return success;
}
filesys_remove
함수 설명
remove
시스템 콜주소 유효성 검사
is_valid_addr(file);
file
포인터가 유효한 주소인지 확인합니다. 유효하지 않은 경우 시스템 콜이 실패할 수 있습니다.파일 삭제 시도
return filesys_remove(file);
filesys_remove
함수를 호출하여 파일을 삭제합니다. 이 함수는 파일 삭제의 성공 여부를 반환합니다.
filesys_remove
함수루트 디렉토리 열기
struct dir *dir = dir_open_root ();
파일 시스템의 루트 디렉토리를 엽니다.
dir_open_root
함수는 루트 디렉토리의 inode를 열고, 이를 사용하여 디렉토리 구조체를 반환합니다.파일 제거 시도
bool success = dir != NULL && dir_remove (dir, name);
- 루트 디렉토리가 성공적으로 열렸는지 확인합니다 (
dir != NULL
). dir_remove
함수를 호출하여 주어진 이름의 파일을 삭제합니다. 이 함수는 성공하면true
를, 실패하면false
를 반환합니다.
- 루트 디렉토리가 성공적으로 열렸는지 확인합니다 (
디렉토리 닫기
dir_close (dir);
dir_close
함수를 호출하여 디렉토리를 닫고, 메모리를 해제합니다.결과 반환
return success;
파일 삭제 작업의 성공 여부를 반환합니다.
요약
remove
시스템 콜file
주소가 유효한지 확인합니다.filesys_remove
함수를 호출하여 파일을 삭제합니다.- 파일 삭제의 성공 여부를 반환합니다.
filesys_remove
함수- 루트 디렉토리를 엽니다.
- 루트 디렉토리가 성공적으로 열리고, 파일이 성공적으로 삭제되었는지 확인합니다.
- 디렉토리를 닫고, 메모리를 해제합니다.
- 파일 삭제의 성공 여부를 반환합니다.
Pintos와 Linux의 system call
비교. 🐣 🆚 🐧
공통점
- 파일 이름과 초기 크기: 두 시스템 모두 파일을 생성할 때 파일 이름과 초기 크기를 인자로 받습니다.
- 파일 시스템 내 데이터 구조: 파일을 생성할 때 내부적으로
inode
와 같은 데이터 구조를 사용하여 파일 메타데이터를 관리합니다.
차이점
- 구현 세부사항:
- Pintos: 교육 목적으로 설계된 간단한 운영체제로, 파일 시스템이 메모리 내에 간단하게 구현되어 있습니다. 파일 생성 과정에서
free_map_allocate
,inode_create
,dir_add
와 같은 함수들을 통해 파일 시스템의 내부 구조를 다룹니다. - Linux: 복잡하고 성능 최적화된 파일 시스템을 가지고 있습니다. Linux의
create
시스템 콜은VFS
(Virtual File System) 레이어를 통해 다양한 파일 시스템(ext4, xfs 등)을 지원하며, 각 파일 시스템별로 최적화된 파일 생성 방식을 사용합니다.
- Pintos: 교육 목적으로 설계된 간단한 운영체제로, 파일 시스템이 메모리 내에 간단하게 구현되어 있습니다. 파일 생성 과정에서
- 동시성 처리:
- Pintos: 간단한 락 메커니즘을 사용하여 동시성 문제를 처리합니다.
- Linux: 복잡한 락킹 메커니즘과 다양한 동시성 제어 기법(RCU, 스핀락 등)을 사용하여 높은 성능과 안정성을 보장합니다.
- 에러 리턴 방식:
- Pintos: 주로
bool
타입을 사용하여 성공 여부를 반환합니다. - Linux: 다양한 에러 코드를 반환하여 세밀한 오류 정보를 제공합니다 (예: -ENOMEM, -EEXIST 등).
- Pintos: 주로
- 파일 시스템 확장성:
- Pintos: 교육 목적이므로 확장성이 제한적입니다.
- Linux: 다양한 파일 시스템을 지원하며(
Virtual File System
), 대규모 파일 시스템에서도 효율적으로 작동하도록 설계되어 있습니다.
결론
PintOS로 파일 시스템을 다뤄봤다고 하지만, 아직 부족한게 많다고 느꼇다. 실제로 File system이 어떻게 관리되는지 궁금해졌으며 시간이 날 때마다 추가적으로 정리를 해야겠다! 😼😼
'PintOS' 카테고리의 다른 글
[PintOS - Userprog] Fork, Exec, Wait 에 들어가기 앞서... (0) | 2024.05.29 |
---|---|
[PintOS - Userprog] Write (0) | 2024.05.28 |
[PintOS - Userprog] Seek & Tell (0) | 2024.05.28 |
[PintOS - Userprog] Read (0) | 2024.05.28 |
[PintOS - Userprog] Open & Close (0) | 2024.05.27 |