[TIL/크래프톤 정글] DAY 80

배재준·2025년 5월 29일

크래프톤 정글 - TIL

목록 보기
72/93
post-thumbnail

2025.05.28

TIL(TODAY I LEARN)


  • 오늘한 내용 : PintOS - Project2: UserProgram - System calls
    dup2 도전하기.
  • WEEK 11 : 정글 끝까지(PintOS) - UserProgram

dup2 가 뭔데?

블로그를 참고하자.

extra) dup2 구현하기

  • dup2 테스트 수행하기
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와 비슷하게 수정

  • 스레드 구조체에서 fd_table을 동적할당으로 변경
  • dup2 테스트는 fdtable 463번째를 막 쓰기 때문에 512 까지는 넣어주려 했고,
    그러면 정적으로 할당하면 스레드 구조체의 size가 너무 커져서 동적할당으로 변경했다.
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;
...
}

  • do_fork 시 fd 테이블 복제할때 표준입출력에 대한 처리 추가
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 넘어가야겠다..

0개의 댓글