πŸ“€ KAIST:PINTOS | Implementation | create

μ΄μˆœκ°„Β·2025λ…„ 5μ›” 22일

KAIST:PINTOS

λͺ©λ‘ 보기
18/23

1. λͺ©ν‘œ

  • μœ μ € ν”„λ‘œκ·Έλž¨μ—μ„œ create() μ‹œμŠ€ν…œ μ½œμ„ ν˜ΈμΆœν–ˆμ„ λ•Œ,
    νŒŒμΌμ„ μƒμ„±ν•˜κ³  성곡 μ—¬λΆ€λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ 컀널 μ½”λ“œλ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€.
  • NULL, 비정상 포인터, 파일 이름 길이 μ œν•œ λ“±μ˜ λ‹€μ–‘ν•œ 상황에 λŒ€ν•œ μ˜ˆμ™Έ 처리λ₯Ό 포함해야 ν•©λ‹ˆλ‹€.

2. μˆ˜μ •ν•œ 파일

  • userprog/syscall.c
  • userprog/syscall.h

3. syscall.c κ΅¬ν˜„

#include "userprog/syscall.h"       // μ‹œμŠ€ν…œ 콜 μΈν„°νŽ˜μ΄μŠ€ μ •μ˜
#include <stdio.h>                  // printf μ‚¬μš©
#include <syscall-nr.h>             // μ‹œμŠ€ν…œ 콜 번호 μ •μ˜
#include "threads/interrupt.h"      // μΈν„°λŸ½νŠΈ λ“±λ‘μš©
#include "threads/thread.h"         // thread_current λ“±
#include "threads/loader.h"         // μ‚¬μš©μž ν”„λ‘œκ·Έλž¨ λ‘œλ”© κ΄€λ ¨
#include "userprog/gdt.h"           // μ„Έκ·Έλ¨ΌνŠΈ 정보
#include "threads/flags.h"          // ν”Œλž˜κ·Έ λΉ„νŠΈ
#include "intrinsic.h"              // write_msr λ“±

#include "devices/input.h"          // input_getc() μ‚¬μš©μ„ μœ„ν•΄
#include "threads/init.h"           // power_off() μ‚¬μš©μ„ μœ„ν•΄
#include "threads/synch.h"          // lock μ‚¬μš©μ„ μœ„ν•΄
#include "filesys/filesys.h"        // filesys_create() μ‚¬μš©μ„ μœ„ν•΄
#include "threads/vaddr.h"          // is_user_vaddr() μ‚¬μš©μ„ μœ„ν•΄
#include "threads/mmu.h"            // pml4_get_page() μ‚¬μš©μ„ μœ„ν•΄

struct lock file_lock;              // 파일 μ‹œμŠ€ν…œ 동기화λ₯Ό μœ„ν•œ μ „μ—­ 락

void syscall_entry (void);          // syscall μ§„μž… ν•¨μˆ˜
void syscall_handler (struct intr_frame *);  // syscall ν•Έλ“€λŸ¬

#define MSR_STAR 0xc0000081         // syscall μ„Έκ·Έλ¨ΌνŠΈ μ§€μ • MSR
#define MSR_LSTAR 0xc0000082        // syscall ν•Έλ“€λŸ¬ μ£Όμ†Œ MSR
#define MSR_SYSCALL_MASK 0xc0000084 // syscall μ§„μž… μ‹œ λ§ˆμŠ€ν‚Ήν•  ν”Œλž˜κ·Έ

void syscall_init (void) {
  // μ‚¬μš©μž/컀널 λͺ¨λ“œ μ „ν™˜ μ‹œ μ„Έκ·Έλ¨ΌνŠΈ μ„€μ •
  write_msr(MSR_STAR, ((uint64_t)SEL_UCSEG - 0x10) << 48  |
                      ((uint64_t)SEL_KCSEG) << 32);
  // syscall μ§„μž… 지점 μ„€μ •
  write_msr(MSR_LSTAR, (uint64_t) syscall_entry);

  // μΈν„°λŸ½νŠΈ λ§ˆμŠ€ν‚Ή μ„€μ • (IF, TF, DF λ“±)
  write_msr(MSR_SYSCALL_MASK,
            FLAG_IF | FLAG_TF | FLAG_DF | FLAG_IOPL | FLAG_AC | FLAG_NT);

  // 파일 μ‹œμŠ€ν…œ 락 μ΄ˆκΈ°ν™”
  lock_init(&file_lock);
}

// μ‹œμŠ€ν…œ 콜 ν•Έλ“€λŸ¬
void syscall_handler(struct intr_frame *f) {
  uint64_t syscall_num = f->R.rax; // syscall λ²ˆν˜ΈλŠ” rax에 μ €μž₯됨

  switch (syscall_num) {
    case SYS_HALT:
      sys_halt(); // μ‹œμŠ€ν…œ μ’…λ£Œ
      break;

    case SYS_EXIT:
      sys_exit((int)f->R.rdi); // ν˜„μž¬ ν”„λ‘œμ„ΈμŠ€ μ’…λ£Œ
      break;

    case SYS_WRITE:
      f->R.rax = sys_write((int)f->R.rdi, (const void *)f->R.rsi, (unsigned)f->R.rdx);
      break;

    case SYS_READ:
      f->R.rax = sys_read((int)f->R.rdi, (void *)f->R.rsi, (unsigned)f->R.rdx);
      break;

    case SYS_CREATE:
      f->R.rax = sys_create((const char *)f->R.rdi, (unsigned)f->R.rsi);
      break;

    default:
      printf("Unknown system call: %lld\n", syscall_num);
      sys_exit(-1); // μ •μ˜λ˜μ§€ μ•Šμ€ μ‹œμŠ€ν…œ 콜이면 κ°•μ œ μ’…λ£Œ
      break;
  }
}

// μ‹œμŠ€ν…œ 콜: create
bool sys_create(const char *file, unsigned initial_size) {
  // file이 NULLμ΄κ±°λ‚˜ μœ μ € μ˜μ—­μ΄ μ•„λ‹ˆκ±°λ‚˜, λ§€ν•‘λ˜μ§€ μ•Šμ€ 가상 μ£Όμ†ŒμΌ 경우 μ’…λ£Œ
  if (file == NULL || !is_user_vaddr(file) || pml4_get_page(thread_current()->pml4, file) == NULL) {
    sys_exit(-1);
  }

  lock_acquire(&file_lock); // 동기화λ₯Ό μœ„ν•΄ 락 νšλ“
  bool success = filesys_create(file, initial_size); // μ‹€μ œ 파일 생성
  lock_release(&file_lock); // 락 ν•΄μ œ

  return success; // 성곡 μ—¬λΆ€ λ°˜ν™˜
}

4. syscall.h μˆ˜μ •

#ifndef USERPROG_SYSCALL_H
#define USERPROG_SYSCALL_H

#include <stdbool.h> // bool νƒ€μž… μ‚¬μš©μ„ μœ„ν•œ 헀더

void syscall_init(void); // syscall μ„€μ • ν•¨μˆ˜

void sys_halt(void); // μ‹œμŠ€ν…œ μ’…λ£Œ
void sys_exit(int status); // ν”„λ‘œμ„ΈμŠ€ μ’…λ£Œ
int sys_write(int fd, const void *buffer, unsigned size); // 좜λ ₯
int sys_read(int fd, void *buffer, unsigned size); // μž…λ ₯
bool sys_create(const char *file, unsigned initial_size); // 파일 생성

#endif /* userprog/syscall.h */

5. ν…ŒμŠ€νŠΈ 톡과 κ²°κ³Ό

ν•΄λ‹Ή κ΅¬ν˜„μœΌλ‘œ λ‹€μŒμ˜ ν…ŒμŠ€νŠΈλ₯Ό λͺ¨λ‘ ν†΅κ³Όν•˜μ˜€μŠ΅λ‹ˆλ‹€:

  • create-normal
  • create-empty
  • create-null
  • create-bad-ptr
  • create-long
  • create-exists
  • create-bound

각 ν…ŒμŠ€νŠΈλŠ” λ‹€μŒκ³Ό 같은 μΌ€μ΄μŠ€λ₯Ό κ²€μ¦ν•©λ‹ˆλ‹€:

ν…ŒμŠ€νŠΈ 이름검증 λ‚΄μš©
create-normal일반 파일 생성이 κ°€λŠ₯ν•œκ°€
create-empty크기 0인 νŒŒμΌμ„ λ§Œλ“€ 수 μžˆλŠ”κ°€
create-nullfile μΈμžκ°€ NULL일 λ•Œ μ˜ˆμ™Έμ²˜λ¦¬ ν•˜λŠ”κ°€
create-bad-ptr잘λͺ»λœ μ£Όμ†ŒμΌ λ•Œ ν”„λ‘œμ„ΈμŠ€λ₯Ό μ’…λ£Œν•˜λŠ”κ°€
create-long파일 이름이 맀우 길어도 λ™μž‘ν•˜λŠ”κ°€
create-exists이미 μ‘΄μž¬ν•˜λŠ” 파일이 있으면 μ‹€νŒ¨ν•˜λŠ”κ°€
create-bound경계 길이의 이름도 ν—ˆμš©ν•˜λŠ”κ°€

6. μˆ˜μ •ν•œ 파일

이번 create() μ‹œμŠ€ν…œ 콜 κ΅¬ν˜„μ—μ„œ μ‹€μ œλ‘œ 직접 μˆ˜μ •ν•œ νŒŒμΌμ€ λ‹€μŒ 두 κ°œλΏμž…λ‹ˆλ‹€:

파일 κ²½λ‘œμ„€λͺ…
userprog/syscall.cμ‹œμŠ€ν…œ 콜 본체 κ΅¬ν˜„ (sys_create() ν•¨μˆ˜ μ •μ˜ 포함)
userprog/syscall.hμ‹œμŠ€ν…œ 콜 ν•¨μˆ˜ μ„ μ–Έ 및 #include <stdbool.h> μΆ”κ°€

λ˜ν•œ, λ‹€μŒ νŒŒμΌλ“€μ€ μˆ˜μ •ν•˜μ§€ μ•Šμ•˜μ§€λ§Œ syscall.c λ‚΄λΆ€μ—μ„œ ν•„μš”ν•œ κΈ°λŠ₯을 μ‚¬μš©ν•˜κΈ° μœ„ν•΄ include만 ν•˜μ˜€μŠ΅λ‹ˆλ‹€:

파일 κ²½λ‘œμ‚¬μš© λͺ©μ 
filesys/filesys.hfilesys_create() ν•¨μˆ˜ ν˜ΈμΆœμ„ μœ„ν•΄
threads/synch.h락 자료ꡬ쑰 및 lock_acquire, lock_release μ‚¬μš©μ„ μœ„ν•΄
threads/vaddr.his_user_vaddr()둜 μ‚¬μš©μž μ£Όμ†ŒμΈμ§€ ν™•μΈν•˜κΈ° μœ„ν•΄
threads/mmu.hpml4_get_page()둜 μ£Όμ†Œ λ§€ν•‘ μ—¬λΆ€λ₯Ό ν™•μΈν•˜κΈ° μœ„ν•΄
threads/init.hpower_off() ν˜ΈμΆœμ„ μœ„ν•΄
devices/input.h(ν˜„μž¬λŠ” μ‚¬μš©ν•˜μ§€ μ•Šμ•˜μœΌλ‚˜, read() κ΅¬ν˜„ μ‹œ ν•„μš” μ˜ˆμ •)

μš”μ•½ν•˜λ©΄, 직접 μˆ˜μ •ν•œ 건 syscall.c, syscall.h 단 두 파일이며,
λ‚˜λ¨Έμ§€λŠ” 이미 PintOS에 μ •μ˜λœ κΈ°λŠ₯듀을 λΆˆλŸ¬μ™€μ„œ ν™œμš©ν•˜λŠ” λ°©μ‹μœΌλ‘œ κ°œλ°œμ„ μ§„ν–‰ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
μ΄λŠ” 이후 λ‹€λ₯Έ μ‹œμŠ€ν…œ μ½œμ„ κ΅¬ν˜„ν•  λ•Œλ„ λ™μΌν•œ νŒ¨ν„΄μœΌλ‘œ 반볡될 κ²ƒμž…λ‹ˆλ‹€.

profile
μ„œνˆ΄μ§€μ–Έμ • 늘 행동이 먼저이기λ₯Ό

0개의 λŒ“κΈ€