π©π»βπ» GITHUB λ ν¬μ§ν 리
π©π»βπ» GITHUB File Descriptor μ΄μ
νν μ€μλ νμΌ λμ€ν¬λ¦½ν° λΆλΆμ΄ λλ½λμ΄μλ€. νμΌ μ μΆλ ₯μ μν΄μλ νμΌ λμ€ν¬λ¦½ν°μ ꡬνμ΄ νμνλ€.
open ()
: νμΌμ μ΄ λ μ¬μ©νλ μμ€ν
μ½filesize ()
: νμΌμ ν¬κΈ°λ₯Ό μλ €μ£Όλ μμ€ν
μ½read ()
: μ΄λ¦° νμΌμ λ°μ΄ν°λ₯Ό μ½λ μμ€ν
μ½write ()
: μ΄λ¦° νμΌμ λ°μ΄ν°λ₯Ό κΈ°λ‘ μμ€ν
μ½seek ()
: μ΄λ¦° νμΌμ μμΉ(offset)λ₯Ό μ΄λνλ μμ€ν
μ½tell ()
: μ΄λ¦° νμΌμ μμΉ(offset)λ₯Ό μλ €μ£Όλ μμ€ν
μ½close ()
: μ΄λ¦° νμΌμ λ«λ μμ€ν
μ½ tid_t thread_create (const char *name, int priority, thread_func *function, void *aux)
: function ν¨μλ₯Ό μννλ μ€λ λ μμ± void process_exit (void)
: νλ‘μΈμ€ μ’
λ£ μ νΈμΆλμ΄ νλ‘μΈμ€μ μμμ ν΄μ int process_add_file (struct file *f)
: νμΌ κ°μ²΄μ λν νμΌ λμ€ν¬λ¦½ν° μμ± struct file *process_get_file (int fd)
: νλ‘μΈμ€μ νμΌ λμ€ν¬λ¦½ν° ν
μ΄λΈμ κ²μνμ¬ νμΌ κ°μ²΄μ μ£Όμλ₯Ό λ¦¬ν΄ void process_close_file (int fd)
: νμΌ λμ€ν¬λ¦½ν°μ ν΄λΉνλ νμΌμ λ«κ³ ν΄λΉ μνΈλ¦¬ μ΄κΈ°ν /** project2-System Call */
#define FDT_PAGES 3 // test `multi-oom` ν
μ€νΈμ©
#define FDCOUNT_LIMIT FDT_PAGES * (1 << 9) // μνΈλ¦¬κ° 512κ° μΈ μ΄μ : νμ΄μ§ ν¬κΈ° 4kb / νμΌ ν¬μΈν° 8byte
/** project2-System Call */
int exit_status;
int fd_idx; // νμΌ λμ€ν¬λ¦½ν° μΈλ±μ€
struct file **fdt; // νμΌ λμ€ν¬λ¦½ν° ν
μ΄λΈ
tid_t
thread_create (const char *name, int priority,
thread_func *function, void *aux) {
struct thread *t;
tid_t tid;
ASSERT (function != NULL);
/* Allocate thread. */
t = palloc_get_page (PAL_ZERO);
if (t == NULL)
return TID_ERROR;
/* Initialize thread. */
init_thread (t, name, priority);
tid = t->tid = allocate_tid ();
#ifdef USERPROG
/** project2-System Call */
t->fdt = palloc_get_multiple(PAL_ZERO, FDT_PAGES);
if (t->fdt == NULL)
return TID_ERROR;
t->exit_status = 0; // exit_status μ΄κΈ°ν
t->fd_idx = 3;
t->fdt[0] = 0; // stdin μμ½λ μ리 (dummy)
t->fdt[1] = 1; // stdout μμ½λ μ리 (dummy)
t->fdt[2] = 2; // stderr μμ½λ μ리 (dummy)
.
.
.
return tid;
}
/** project2-System Call */
int process_add_file(struct file *f);
struct file *process_get_file(int fd);
int process_close_file(int fd);
// νμ¬ μ€λ λ fdtμ νμΌ μΆκ°
int
process_add_file(struct file *f)
{
struct thread *curr = thread_current();
struct file **fdt = curr->fdt;
if (curr->fd_idx >= FDCOUNT_LIMIT)
return -1;
fdt[curr->fd_idx++] = f;
return curr->fd_idx - 1;
}
// νμ¬ μ€λ λμ fdλ²μ§Έ νμΌ μ 보 μ»κΈ°
struct file
*process_get_file(int fd)
{
struct thread *curr = thread_current();
if (fd >= FDCOUNT_LIMIT)
return NULL;
return curr->fdt[fd];
}
// νμ¬ μ€λ λμ fdtμμ νμΌ μμ
int
process_close_file(int fd)
{
struct thread *curr = thread_current();
if (fd >= FDCOUNT_LIMIT)
return -1;
curr->fdt[fd] = NULL;
return 0;
}
void
process_exit (void) {
struct thread *curr = thread_current ();
/* TODO: Your code goes here.
* TODO: Implement process termination message (see
* TODO: project2/process_termination.html).
* TODO: We recommend you to implement process resource cleanup here. */
for (int fd = 0; fd < curr->fd_idx; fd++) // FDT λΉμ°κΈ°
close(fd);
file_close(curr->runn_file); // νμ¬ νλ‘μΈμ€κ° μ€νμ€μΈ νμΌ μ’
λ£
palloc_free_multiple(curr->fdt, FDT_PAGES);
process_cleanup();
sema_up(&curr->wait_sema); // μμ νλ‘μΈμ€κ° μ’
λ£λ λκΉμ§ λκΈ°νλ λΆλͺ¨μκ² signal
sema_down(&curr->exit_sema); // λΆλͺ¨ νλ‘μΈμ€κ° μ’
λ£λ λκΉμ§ λκΈ°
}
/** project2-System Call */
struct lock filesys_lock; // νμΌ μ½κΈ°/μ°κΈ° μ© lock
.
.
.
void
syscall_init (void) {
write_msr(MSR_STAR, ((uint64_t)SEL_UCSEG - 0x10) << 48 |
((uint64_t)SEL_KCSEG) << 32);
write_msr(MSR_LSTAR, (uint64_t) syscall_entry);
/* The interrupt service rountine should not serve any interrupts
* until the syscall_entry swaps the userland stack to the kernel
* mode stack. Therefore, we masked the FLAG_FL. */
write_msr(MSR_SYSCALL_MASK,
FLAG_IF | FLAG_TF | FLAG_DF | FLAG_IOPL | FLAG_AC | FLAG_NT);
/** project2-System Call */
// read & write μ© lock μ΄κΈ°ν
lock_init(&filesys_lock);
}
.
.
.
int open(const char *file);
int filesize(int fd);
int read(int fd, void *buffer, unsigned length);
int write(int fd, const void *buffer, unsigned length);
void seek(int fd, unsigned position);
int tell(int fd);
void close(int fd);
int
open(const char *file)
{
check_address(file);
struct file *newfile = filesys_open(file);
if (newfile == NULL)
return -1;
int fd = process_add_file(newfile);
if (fd == -1)
file_close(newfile);
return fd;
}
int
filesize(int fd) {
struct file *file = process_get_file(fd);
if (file == NULL)
return -1;
return file_length(file);
}
input_getc()
μ΄μ©)int
read(int fd, void *buffer, unsigned length)
{
check_address(buffer);
if (fd == 0) { // 0(stdin) -> keyboardλ‘ μ§μ μ
λ ₯
int i = 0; // μ°λ κΈ° κ° return λ°©μ§
char c;
unsigned char *buf = buffer;
for (; i < length; i++) {
c = input_getc();
*buf++ = c;
if (c == '\0')
break;
}
return i;
}
// κ·Έ μΈμ κ²½μ°
if (fd < 3) // stdout, stderrλ₯Ό μ½μΌλ €κ³ ν κ²½μ° & fdκ° μμμΌ κ²½μ°
return -1;
struct file *file = process_get_file(fd);
off_t bytes = -1;
if (file == NULL) // νμΌμ΄ λΉμ΄μμ κ²½μ°
return -1;
lock_acquire(&filesys_lock);
bytes = file_read(file, buffer, length);
lock_release(&filesys_lock);
return bytes;
}
putbuf()
μ΄μ©)int
write(int fd, const void *buffer, unsigned length)
{
check_address(buffer);
off_t bytes = -1;
if (fd <= 0) // stdinμ μ°λ €κ³ ν κ²½μ° & fd μμμΌ κ²½μ°
return -1;
if (fd < 3) { // 1(stdout) * 2(stderr) -> consoleλ‘ μΆλ ₯
putbuf(buffer, length);
return length;
}
struct file *file = process_get_file(fd);
if (file == NULL)
return -1;
lock_acquire(&filesys_lock);
bytes = file_write(file, buffer, length);
lock_release(&filesys_lock);
return bytes;
}
void
seek(int fd, unsigned position)
{
struct file *file = process_get_file(fd);
if (fd < 3 || file == NULL)
return;
file_seek(file, position);
}
int
tell(int fd)
{
struct file *file = process_get_file(fd);
if (fd < 3 || file == NULL)
return -1;
return file_tell(file);
}
void
close(int fd)
{
struct file *file = process_get_file(fd);
if (fd < 3 || file == NULL)
return;
process_close_file(fd);
file_close(file);
}
create-bad-ptr, read-bad-ptr λ± 15κ°μ test caseμμ Page fault λ°μ
userprog/exception.c
static void
page_fault (struct intr_frame *f) {
bool not_present; /* True: not-present page, false: writing r/o page. */
bool write; /* True: access was write, false: access was read. */
bool user; /* True: access by user, false: access by kernel. */
void *fault_addr; /* Fault address. */
/* Obtain faulting address, the virtual address that was
accessed to cause the fault. It may point to code or to
data. It is not necessarily the address of the instruction
that caused the fault (that's f->rip). */
fault_addr = (void *) rcr2();
/* Turn interrupts back on (they were only off so that we could
be assured of reading CR2 before it changed). */
intr_enable ();
/* Determine cause. */
not_present = (f->error_code & PF_P) == 0;
write = (f->error_code & PF_W) != 0;
user = (f->error_code & PF_U) != 0;
/** project2-System Call */
exit(-1);