일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- stack growth
- scaffold
- Flutter
- materialapp
- pintos
- algorithm
- file
- flutter
- vm
- Copy-on-write
- BFS
- Cow
- icon button
- System call
- widget
- create
- Today
- Total
JunHyeok
[PintOS - Userprog] Open & Close 본문
구현 가이드
Opens the file called file
. Returns a nonnegative integer handle called a "file descriptor" (fd), or -1
if the file could not be opened. File descriptors numbered 0 and 1 are reserved for the console: fd 0 (STDIN_FILENO
) is standard input, fd 1 (STDOUT_FILENO
) is standard output. The open
system call will never return either of these file descriptors, which are valid as system call arguments only as explicitly described below. Each process has an independent set of file descriptors. File descriptors are inherited by child processes. When a single file is opened more than once, whether by a single process or different processes, each open returns a new file descriptor. Different file descriptors for a single file are closed independently in separate calls to close and they do not share a file position. You should follow the linux scheme, which returns integer starting from zero, to do the extra.
file
이라는 이름의 파일을 엽니다.- "파일 디스크립터" (fd)라고 불리는 음수가 아닌 정수 핸들을 반환합니다.
- 파일을 열 수 없는 경우
-1
을 반환합니다.
- 파일 디스크립터 0과 1은 콘솔을 위해 예약되어 있습니다:
- fd 0 (
STDIN_FILENO
): 표준 입력 - fd 1 (
STDOUT_FILENO
): 표준 출력
- fd 0 (
open
시스템 호출은 이 두 파일 디스크립터를 반환하지 않습니다.- 이 두 파일 디스크립터는 아래에 명시된 경우에만 시스템 호출 인자로 유효합니다.
- 각 프로세스는 독립적인 파일 디스크립터 집합을 가지고 있습니다.
- 파일 디스크립터는 자식 프로세스에 의해 상속됩니다.
- 하나의 파일이 여러 번 열리면:
- 단일 프로세스에 의해 열리든 다른 프로세스에 의해 열리든 각 열림은 새로운 파일 디스크립터를 반환합니다.
- 단일 파일에 대한 서로 다른 파일 디스크립터:
close
호출에서 독립적으로 닫힙니다.- 파일 위치를 공유하지 않습니다.
open
int open (const char *file) {
is_valid_addr(file);
char *tmp;
int fd = -1;
tmp = filesys_open(file);
if (tmp == NULL) {
return -1;
}
fd = process_get_fd(tmp);
if (fd == -1) {
file_close(tmp); // file.c
}
return fd;
}
system call 구현이 생각보다 많이 간단하다. 🤔
그렇다면 무엇이 이렇게 구현을 쉽게 만들어 주는 것 일까?
파일 열기 과정
파일을 여는 과정은 filesys_open
함수를 중심으로 이루어집니다!
이 함수는 파일 시스템의 루트 디렉터리를 통해 지정된 파일을 찾아 엽니다. (즉, 대부분의 과정이 이미 구현되어 있습니다!)
함수 정의
struct file *filesys_open(const char *name) {
struct dir *dir = dir_open_root(); // 1. 루트 디렉터리 열기
struct inode *inode = NULL; // 2. inode 포인터 초기화
if (dir != NULL)
dir_lookup(dir, name, &inode); // 3. 파일을 찾고 inode 갱신
dir_close(dir); // 4. 디렉터리 닫기
return file_open(inode); // 5. 파일 열기
}
세부 설명
- 루트 디렉터리 열기 (
dir_open_root
):- 파일 시스템의 루트 디렉터리를 엽니다.
- 이 과정에서 루트 디렉터리에 대한 포인터(
dir
)를 반환합니다. - 루트 디렉터리는 파일 시스템에서 최상위 디렉터리로, 모든 파일과 디렉터리의 시작점입니다.
- inode 포인터 초기화:
inode
포인터는 찾고자 하는 파일의 inode를 가리키기 위해 초기화됩니다.inode
는 파일 시스템에서 파일의 메타데이터를 나타내는 구조체로, 파일의 크기, 위치, 권한 등의 정보를 담고 있습니다.
- 디렉터리에서 파일 찾기 (
dir_lookup
):dir_lookup
함수는 디렉터리 내에서 지정된 이름(name
)을 가진 파일을 검색합니다.- 검색이 성공하면 해당 파일의
inode
를 반환합니다.
- 디렉터리 닫기 (
dir_close
):- 파일을 찾은 후에는 더 이상 디렉터리가 필요 없으므로 닫아줍니다.
- 열려 있는 디렉터리를 닫아 자원을 해제하고, 시스템 리소스를 효율적으로 관리합니다.
- 파일 열기 (
file_open
):- 찾은
inode
를 사용하여 파일을 엽니다. file_open
함수는 주어진inode
에 대한 파일 구조체를 생성하고, 파일 포인터를 반환합니다.- 이 파일 포인터는 이후 파일 읽기, 쓰기 등의 작업에 사용됩니다.
- 찾은
파일 열기의 원리
- 디렉터리 (Directory):
- 파일 시스템의 디렉터리는 파일과 다른 디렉터리의 집합입니다.
- 디렉터리는 파일 이름과 해당 파일의 inode 번호를 저장하는 디렉터리 엔트리를 가집니다.
- inode (Index Node):
- inode는 파일의 메타데이터를 저장하는 구조체입니다.
- 파일 시스템에서 각 파일은 고유한 inode를 가지며, 이는 파일의 실제 데이터 블록 위치, 크기, 생성 시간, 권한 등을 포함합니다.
- 파일 포인터 (File Pointer):
- 파일 포인터는 열려 있는 파일에 대한 참조입니다.
- 파일 포인터를 통해 파일의 데이터를 읽거나 쓸 수 있습니다.
- 파일 포인터는 파일의 현재 읽기/쓰기 위치를 저장하며, 파일 디스크립터를 통해 관리됩니다.
process_add_file?
int
process_add_file(struct file *f) {
struct thread *cur = thread_current();
int tmp_fd;
for (tmp_fd = 2; tmp_fd < 128; tmp_fd++) {
if (cur->fd_table[tmp_fd] == NULL) {
cur->fd_table[tmp_fd] = f;
cur->cur_fd = tmp_fd;
return cur->cur_fd;
}
}
return -1;
}
fd table을 순회하며, 가용 가능한 공간을 찾으면 fd를 리턴해줍니다!
Close
/* Closes FILE. */
void
file_close (struct file *file) {
if (file != NULL) {
file_allow_write (file);
inode_close (file->inode);
free (file);
}
}
file_close 함수 설명
- 파일이 NULL인지 확인
함수가 전달된file
포인터가NULL
이 아닌지 확인합니다.NULL
인 경우 아무 작업도 하지 않습니다. - 파일 쓰기 허용
file_allow_write
함수를 호출하여 파일에 쓰기 작업을 허용합니다. 삭제하려면 당연히 write 할 수 있는 권한이 있어야겠죠? - inode 닫기
파일의inode
를 닫습니다. 파일을 닫을 때inode
구조체를 반드시 닫아야 합니다. - 파일 메모리 해제
파일 구조체에 할당된 메모리를 해제합니다.
결론
결과적으로, 우리는 open
시스템 콜을 통해서 fd를 최종적으로 return 받습니다.
또한, close
시스템 콜을 통해 FDT
를 갱신하고, 열린 파일을 닫을 수 있습니다.
read (int fd, void *buffer, unsigned size);
이제 우리는 read
와 같은 시스템 콜을 통해서 open
된 파일에 대한 작업을 수행한 뒤 close
를 통해서 파일을 닫을 수 있게 됐습니다! 😼
'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] Create & Remove (0) | 2024.05.28 |
[PintOS - Userprog] Read (0) | 2024.05.28 |