파일 열기
구현전 힌트
int
open(const char *file)
{
check_address(file);
struct file *f = filesys_open(file);
if (f == NULL)
{
return -1;
}
int fd = process_add_file(f);
if (fd == -1)
{
file_close(f);
}
return fd;
}
파일의 크기 탐색
구현 전 힌트
int filesize(int fd)
{
// 1. 현재 스레드 정보 가져오기
struct thread *curr = thread_current();
// 2. 파일 디스크립터 유효성 검사
if (fd < 2 || fd >= FD_MAX || curr->fd_table[fd] == NULL)
{
return -1;
}
struct file *f = curr->fd_table[fd];
return file_length(f);
}
열린 파일의 데이터를 읽기
구현 전 힌트
int
read(int fd, void *buffer, unsigned size)
{
check_address(buffer);
struct thread *curr = thread_current();
lock_acquire(&filesys_lock);
if (fd < 0 || fd >= FD_MAX || buffer == NULL)
{
lock_release(&filesys_lock);
return -1;
}
if (fd == 0)
{
for (int i = 0; i < size; i++)
{
((char *)buffer)[i] = input_getc();
}
lock_release(&filesys_lock);
return size;
}
struct file *f = curr->fd_table[fd];
if (f == NULL)
{
lock_release(&filesys_lock);
return -1;
}
int bytes_read = file_read(f, buffer, size);
lock_release(&filesys_lock);
return bytes_read;
}
열린 파일의 데이터를 기록
구현 전 힌트
int
write(int fd, void *buffer, unsigned size)
{
// 1. 주소 유효성 검사
check_address(buffer);
lock_acquire(&filesys_lock); // 파일에 동시 접근이 일어날 수 있으므로 lock 사용
struct thread *curr = thread_current();
// fd와 버퍼 유효성 검사
if (fd < 1 || fd >= FD_MAX || buffer == NULL)
{
lock_release(&filesys_lock);
return -1;
}
// 5. 표준 입력 처리
if (fd == 1)
{
putbuf((char *)buffer, size);
lock_release(&filesys_lock);
return size;
}
// 6. 파일 객체 가져오기
struct file *f = curr->fd_table[fd];
if (f == NULL)
{
lock_release(&filesys_lock);
return -1;
}
// 7. 파일에 데이터 쓰기
int bytes_written = file_write(f, buffer, size);
// 8. 파일 시스템 락 해제
lock_release(&filesys_lock);
return bytes_written;
}
열린 파일의 위치 이동
구현 전 힌트
void
seek(int fd, unsigned position)
{
if (fd < 0 || fd >= FD_MAX)
{
return;
}
struct thread *curr = thread_current();
struct file *f = curr->fd_table[fd];
if (f != NULL)
{
file_seek(f, position);
}
}
열린 파일의 위치(offset) 알려줌
구현 전 힌트
unsigned
tell(int fd)
{
if (fd < 0 || fd >= FD_MAX)
{
return;
}
struct thread *curr = thread_current();
struct file *f = curr->fd_table[fd];
if (f != NULL)
{
return file_tell(f);
}
}
열린 파일을 닫기
구현 전 힌트
close(int fd)
{
process_close_file(fd);
}
void syscall_handler(struct intr_frame *f UNUSED)
{
int syscall_number = f->R.rax;
switch (syscall_number)
{
case SYS_HALT:
halt();
break;
case SYS_EXIT:
exit(f->R.rdi);
break;
case SYS_FORK:
f->R.rax = fork(f->R.rdi);
break;
case SYS_EXEC:
f->R.rax = exec(f->R.rdi);
break;
case SYS_WAIT:
wait(f->R.rdi);
break;
case SYS_CREATE:
f->R.rax = create(f->R.rdi, f->R.rsi);
break;
case SYS_REMOVE:
f->R.rax = remove(f->R.rdi);
break;
case SYS_OPEN:
f->R.rax = open(f->R.rdi);
break;
case SYS_FILESIZE:
f->R.rax = filesize(f->R.rdi);
break;
case SYS_READ:
f->R.rax = read(f->R.rdi, f->R.rsi, f->R.rdx);
break;
case SYS_WRITE:
f->R.rax = write(f->R.rdi, f->R.rsi, f->R.rdx);
break;
case SYS_SEEK:
seek(f->R.rdi, f->R.rsi);
break;
case SYS_TELL:
f->R.rax = tell(f->R.rdi);
break;
case SYS_CLOSE:
close(f->R.rdi);
break;
default:
thread_exit();
break;
}
}
프로세스 디스크립터에 파일 디스크립터 테이블 추가
// thread.h 파일에
// struct thread{ } 여기에 추가
struct file *fd_table[FD_MAX];
int max_fd;
스레드 생성 시 파일 디스크립터 초기화
// thread.c 파일에
// init_thread 함수에 추가
t->fd_table[0] = 0;
t->fd_table[1] = 1;
t->max_fd = 2; //
파일 객체를 파일 디스크립터 테이블에 추가
구현 전 힌트
int process_add_file(struct file *f)
{
struct thread *cur = thread_current();
// 새로운 파일 디스크립터 할당(가장 큰 파일 디스크립터 번호)
int fd = cur->max_fd;
// 파일 디스크립터 테이블 크기 확인.
if (fd >= FD_MAX)
return -1; // 파일 디스크립터 테이블이 꽉 찬 경우
// 파일 디스크립터 테이블에 파일 포인터 추가.
cur->fd_table[fd] = f;
// 파일 디스크립터 번호 증가
cur->max_fd++;
return fd;
}
파일 객체 검색
구현 전 힌트
struct
file *process_get_file(int fd)
{
struct thread *t = thread_current();
if (2 <= fd < FD_MAX)
{
if (t->fd_table[fd] != NULL)
{
return t->fd_table[fd];
}
}
return NULL;
}
파일 디스크립터에 해당하는 파일을 닫고 해당 엔트리 초기화
구현 전 힌트
void process_close_file(int fd)
{
struct thread *t = thread_current();
if (2 <= fd < FD_MAX)
{
// 파일 닫기
file_close(t->fd_table[fd]);
// 엔트리 제거
t->fd_table[fd] = NULL;
}
}
모든 열린 파일 닫기
구현 전 힌트
void
process_exit(void)
{
struct thread *curr = thread_current ();
// 열린 파일들 닫기
for(int fd = 2; fd < FD_MAX; fd++)
{
process_close_file(fd);
}
// 프로세스와 관련된 자원 정리하는 함수 호출
process_cleanup();
// 스레드의 종료를 알리기 위해 세마포어 업
sema_up(&thread_current()->sema_exit);
}