[Pint OS] System Calls (6)

2023. 6. 17. 14:52·프로젝트/Pint OS

x86-64 기반 Pint OS 프로젝트 2의 System Calls를 구현하기 위해 공부한 개념을 정리한다.

파일 시스템 콜

파일 조작을 위한 인터페이스를 제공한다. Pint OS - Project 2(System Calls)에서 구현해야 할 파일 관련 시스템 콜은 다음과 같다.

read

정의

int filesize (int fd, void *buffer, unsigned size);

열린 파일 'fd'에서 'size' 만큼의 바이트를 읽고 'buffer'에 저장한다. 실제로 읽은 바이트 크기를 반환하고, 실패했다면 -1을 반환한다. fd가 표준 입력(0)일 때는 input_getc() 함수를 사용해서 키보드 입력을 받는다.

락

  • include/userprog/syscall.h

    struct lock filesys_lock;
  • userprog/syscall.c

    void
    syscall_init (void) {
      ...
      lock_init (&filesys_lock);
    }
  • 파일 작업을 처리하기 위한 전역변수 락(filesys_lock)을 생성한다.

read ()

int
read (int fd, void *buffer, unsigned size) {
    check_address (buffer);
    lock_acquire (&filesys_lock);

    char *ptr = (char *)buffer;
    int bytes_read = 0;

    if (fd == STDIN_FILENO) {
        for (int i = 0; i < size; i++) {
            *ptr++ = input_getc ();
            bytes_read++;
        }
        lock_release (&filesys_lock);
    }
    else {
        if (fd < 2) {
            lock_release (&filesys_lock);
            return -1;
        }

        struct file *file = process_get_file (fd);
        if (file == NULL) {
            lock_release (&filesys_lock);
            return -1;
        }

        bytes_read = file_read (file, buffer, size);
        lock_release (&filesys_lock);
    }

    return bytes_read;
}
  • 인자로 받은 buffer의 유효성을 체크한다.
  • filesys_lock을 잠근다.
  • fd가 표준 입력이라면, input_getc 함수로 키보드 입력을 받는다.
  • 아니라면 현재 프로세스에서 fd에 해당하는 file 구조체를 가져와서 file 라이브러리의 file_read 함수를 사용해서 바이트를 읽는다.
  • filesys_lock을 풀어준다.

process_get_file ()

struct file *
process_get_file (int fd) {
    struct thread *curr = thread_current ();
    struct file **fdt = curr->fdt;

    if (fd < 2 || fd >= FDT_COUNT_LIMIT)
        return NULL;
    return fdt[fd];
}
  • 현재 프로세스의 파일 스크립터 세트에서 fd에 해당하는 file 구조체를 가져온다.

write

정의

int write (int fd, const void *buffer, unsigned size);

buffer의 size 만큼의 바이트 데이터를 fd에 write한다. fd가 STDOUT_FILENO(표준 출력)인 경우, putbuf() 함수를 사용해서 콘솔에 출력한다. 그 외의 경우에는 process_get_file(fd) 함수를 호출해서 fd에 해당하는 file을 호출해서 file에서 데이터를 읽는다. 파일에 접근할 때는 filesys_lock을 잠가준다.

write ()

int
write (int fd, const void *buffer, unsigned size) {
    check_address (buffer);
    int bytes_write = 0;
    if (fd == STDOUT_FILENO) {
        putbuf (buffer, size);
        bytes_write = size;
    }
    else {
        if (fd < 2)
            return -1;

        struct file *file = process_get_file (fd);
        if (file == NULL)
            return -1;

        lock_acquire (&filesys_lock);
        bytes_write = file_write (file, buffer, size);
        lock_release (&filesys_lock);
    }
    return bytes_write;
}
  • 인자로 받은 buffer의 유효성을 체크한다.
  • fd가 STUOUT_FILENO인 경우, 콘솔에 출력한다.
  • 그 외의 경우, file_write()를 호출해서 파일에 작성한다.
    • 이 때, filesys_lock을 잠가주어야 한다.

seek

정의

void seek (int fd, unsigned position);

fd에서 다음에 읽거나 쓸 바이트의 위치(position)를 지정한다. file 라이브러리에 구현된 함수를 사용하면 간단하다.

seek ()

void
seek (int fd, unsigned position) {
    struct file *file = process_get_file (fd);
    if (file == NULL)
        return;
    file_seek (file, position);
}

tell

정의

unsigned tell (int fd);

fd에서 다음에 읽거나 쓸 바이트의 위치를 반환한다. file 라이브러리에 구현된 함수를 사용하면 간단하다.

tell ()

unsigned
tell (int fd) {
    struct file *file = process_get_file (fd);
    if (file == NULL)
        return;
    return file_tell (file);
}

close

정의

void close (int fd);

fd를 닫는다. 프로세스를 끄거나 강제 종료할 때 close를 호출함으로써 fd를 명시적으로 닫아주어야 한다.

close ()

void
close (int fd) {
    if (fd < 2)
        return;
    struct file *file = process_get_file (fd);
    if (file == NULL)
        return;
    file_close (file);
    process_close_file (fd);
  • fd가 0(표준 출력)과 1(표준 입력)인 경우, 닫아선 안 된다.
  • fd에 해당하는 file 구조체를 가져온다.
  • file 라이브러리의 file_close() 함수를 사용해서 닫는다.
  • process_close_file() 함수를 호출해서 현재 스레드의 file descriptor set에서 제거한다.

process_close_file ()

void
process_close_file (int fd) {
    struct thread *curr = thread_current ();
    struct file **fdt = curr->fdt;

    if (fd < 2 || fd >= FDT_COUNT_LIMIT)
        return NULL;
    fdt[fd] = NULL;
}
  • 현재 스레드의 file descriptor set에서 fd에 할당된 값을 제거한다(NULL).

'프로젝트 > Pint OS' 카테고리의 다른 글

[Pint OS] Lazy loading(2)  (0) 2023.06.19
[Pint OS] Lazy loading(1)  (0) 2023.06.18
[Pint OS] 에러: multi-oom  (0) 2023.06.17
[Pint OS] System Calls (5)  (1) 2023.06.14
[Pint OS] System Calls (4)  (0) 2023.06.11
'프로젝트/Pint OS' 카테고리의 다른 글
  • [Pint OS] Lazy loading(2)
  • [Pint OS] Lazy loading(1)
  • [Pint OS] 에러: multi-oom
  • [Pint OS] System Calls (5)
KimCookieYa
KimCookieYa
무엇이 나를 살아있게 만드는가
  • KimCookieYa
    쿠키의 주저리
    KimCookieYa
  • 전체
    오늘
    어제
    • 분류 전체보기 (576)
      • 혼잣말 (88)
      • TIL (3)
      • 커리어 (24)
        • Sendy (21)
        • 외부활동 기록 (2)
      • 프로젝트 (186)
        • 티스토리 API (5)
        • 코드프레소 체험단 (89)
        • Web3 (3)
        • Pint OS (16)
        • 나만무 (14)
        • 대회 (6)
        • 정글 FE 스터디 (16)
        • MailBadara (12)
        • github.io (1)
        • 인공지능 동아리, AID (5)
        • 졸업과제 (18)
        • OSSCA 2024 (1)
      • 크래프톤 정글 2기 (80)
      • IT (169)
        • 코딩 (4)
        • CS (18)
        • 에러 (5)
        • 블록체인 (23)
        • Front-End (40)
        • 알고리즘&자료구조 정리 (3)
        • 코딩테스트 (3)
        • BOJ 문제정리 (41)
        • WILT (12)
        • ML-Agents (4)
        • 강화학습 (1)
        • Android (0)
        • LLM (2)
      • 전공 (1)
        • 머신러닝 (1)
      • 자기계발 (20)
        • 빡공단X베어유 (2)
        • 독서 (15)
  • 블로그 메뉴

    • 홈
    • 방명록
    • Github
    • Velog
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    니어프로토콜
    OS
    Pint OS
    해커톤
    알고리즘
    리액트
    머신러닝
    MailBadara
    딥러닝
    나만무
    센디
    JavaScript
    코드프레소
    사이드프로젝트
    부산대
    numpy
    docker
    파이썬
    RNN
    자바스크립트
    pintos
    NEAR Protocol
    프로그래머스
    react
    핀토스
    Flutter
    졸업과제
    블록체인
    크래프톤정글
    글리치해커톤
  • hELLO· Designed By정상우.v4.10.3
KimCookieYa
[Pint OS] System Calls (6)
상단으로

티스토리툴바