
2025.05.28
블로그를 참고하자.
Make.vars 파일
맨 아래 3줄 #(주석)을 제거해야
테스트가 수행 가능해짐
-----------------------------------
# -*- makefile -*-
os.dsk: DEFINES = -DUSERPROG -DFILESYS
KERNEL_SUBDIRS = threads tests/threads tests/threads/mlfqs
KERNEL_SUBDIRS += devices lib lib/kernel userprog filesys
TEST_SUBDIRS = tests/userprog tests/filesys/base tests/userprog/no-vm tests/threads
GRADING_FILE = $(SRCDIR)/tests/userprog/Grading.no-extra
# Uncomment the lines below to submit/test extra for project 2.
TDEFINE := -DEXTRA2
TEST_SUBDIRS += tests/userprog/dup2
GRADING_FILE = $(SRCDIR)/tests/userprog/Grading.extra
syscall.c
/* int dup2(int oldfd, int newfd); 호출 시 */
case SYS_DUP2:
{
int oldfd = (int)f->R.rdi;
int newfd = (int)f->R.rsi;
f->R.rax = sys_dup2(oldfd, newfd);
break;
}
--------------------------------------------------
/* dup2를 위한 sys_dup2 */
int sys_dup2(int oldfd, int newfd)
{
struct thread *cur = thread_current();
// 유효성 검사
if (oldfd < 0 || oldfd >= MAX_FD || newfd < 0 || newfd >= MAX_FD ||
cur->fd_table[oldfd] == NULL)
return -1;
// fd 같으면 그냥 바로 리턴
if (oldfd == newfd)
return newfd;
// newfd 열려있다면 닫아주고
if (cur->fd_table[newfd] != NULL) // newfd가 열려있다면
file_close(cur->fd_table[newfd]);
// fd 복제 수행
cur->fd_table[newfd] = file_duplicate(cur->fd_table[oldfd]);
return newfd;
}
file.c
struct file
{
struct inode *inode; /* File's inode. */
off_t pos; /* Current position. */
bool deny_write; /* Has file_deny_write() been called? */
int ref_cnt; /* fd 참조 개수 */ <---------- 추가
};
----------------------
/* 콘솔을 가리키는 가짜 file 구조체 두 개 */
static struct file console_in;
static struct file console_out;
void console_file_init(void) {
/* inode == NULL 이면 콘솔 입출력 분기로 처리하도록 */
console_in.inode = NULL;
console_in.pos = 0;
console_in.deny_write = false;
console_in.ref_cnt = 1;
console_out.inode = NULL;
console_out.pos = 0;
console_out.deny_write = false;
console_out.ref_cnt = 1;
}
----------------------
struct file *
file_open(struct inode *inode)
{
....
if (inode != NULL && file != NULL)
{
file->inode = inode;
file->pos = 0;
file->deny_write = false;
file->ref_cnt = 1; /* 초기 참조 카운트 */ <----- 추가
}else ...
dup2를 위한 함수 추가
struct file *
file_dup2(struct file *file)
{
file->ref_cnt++;
return file;
}
---------------------------------
void file_close(struct file *file)
{
if (file == NULL)
return;
if (file == &console_in || file == &console_out)
return;
lock_acquire(&filesys_lock);
/* 먼저 참조 카운트만 감소 */
file->ref_cnt--;
/* 마지막 복제본이 닫힐 때만 실제로 해제 작업 수행 */
if (file->ref_cnt == 0)
{
file_allow_write(file);
inode_close(file->inode);
free(file);
}
lock_release(&filesys_lock);
}
file_read()
{
...
/* 읽기인데 출력디스크립터 일때 */
if (file == &console_out)
{
lock_release(&filesys_lock);
return -1;
}
/* 표준 입력 일때 */
else if (file->inode == NULL)
{
/* stdin 역할 */
for (off_t i = 0; i < size; i++)
((char *)buffer)[i] = input_getc();
lock_release(&filesys_lock);
return size;
}
/* 정상 디스크립터일때 */
...
}
file_wirte() 도 read와 비슷하게 수정
thread.c
/* fd를 위한 #define 추가*/
#define MAX_FD 512 //dup2 test는 463만큼은 필요함
---------------------
struct thread{
...
/* fd 테이블을 추가*/
struct file **fd_table; // fd_table 동적할당으로 변경
int next_fd;
...
}
thread_create(){
...
/* fd 테이블을 동적 페이지로 할당 */
t->fd_table = palloc_get_page(PAL_ZERO);
if (t->fd_table == NULL)
{
/* palloc 실패 시, 구조체 페이지도 돌려주고 에러 처리 */
palloc_free_page(t);
return TID_ERROR;
}
/* fd 테이블은 palloc_zero된 페이지라 이미 NULL로 초기화됨 */
t->next_fd = 2; /* 0: stdin, 1: stdout 예약 */
...
}
thread_exit(){
...
/* fd_table 페이지 해제 */
palloc_free_page(thread_current()->fd_table);
thread_current()->fd_table = NULL;
...
}
process.c
--do_fork(){
...
for (int fd = 0; fd < MAX_FD; fd++)
{
struct file *f = parent->fd_table[fd];
if (f == NULL)
{
current->fd_table[fd] = NULL;
}
else if (f == &console_in || f == &console_out)
{
/* stdin : console_in 공유 */
current->fd_table[fd] = f;
}
else
current->fd_table[fd] = file_duplicate(f);
}
current->next_fd = parent->next_fd;
...
}
이 외에도 좀 자잘한 것들을 수정을 좀 많이했다.
dup2 되게 건드릴게 많더라,,

어찌저찌 dup2는 해결을 했는데,, 갑자기 oom이 안된다. 주말 전까지는 이거 해결해보고
vm 넘어가야겠다..