08_week_C_pintos_systemcall-3

신치우·2022년 11월 28일
0

data_structure_and_Pintos

목록 보기
23/36

이어서
구현된 부분
(exec, open, file size, read, write) + exception.c

exec

file을 실행가능한 파일로 변경함 - 성공하면 아무것도 return 안하고 실패하면 -1을 return
process_exec 는 앞에서 load를 구현할때 사용하였다. load에 문제가 없다면 정상적으로 동작할 것임

//syscall.c
int
exec_handler (const char *file) {   // exec handler가 정상 동작을 한다면 아무것도
                          // return하지 않고 실패한다면 -1 을 return 한다
  check_add (file);
  char *file_name_copy = palloc_get_page (PAL_ZERO);

  if (file_name_copy == NULL)   // page를 정상적으로 할당 받지 못했다면
    exit_handler (-1);

  strlcpy (file_name_copy, file,
           strlen (file) + 1);   // +1은 NULL 문자를 위해서

  if (process_exec (file_name_copy) == -1)   // process_exec에 성공하지 못하면 -1을 return 함
    return -1;

}

open

file을 open을 하고 open된 file을 이중포인터로 관리한다

//syscall.c

int   // open 하는데 성공하면 0 이상의 정수를 반환함 실패하면 음수를 반환
open_handler (const char *file) {
  check_add (file);
  struct file *file_st = filesys_open (file);   // 일단 파일을 open하고
  if (file_st == NULL) {   // open 한게 Null이 아니면 if문을 통과
    return -1;
  }

  int fd_idx = add_file_to_FDT (file_st);   // open한 file 을 table로 관리함
  // 현재 thread가 가진 구조체 내부 fd table에 빈공간이 있으면
  // 추가 후 해당 위치를 return 하고 추가하지 못했으면 -1을 return함

  if (fd_idx == -1) {   // 추가하지 못했다면
    file_close (file_st);   // 열린걸 다시 닫아줘야함 (열린 상태로 두면 안됨)
  }

  return fd_idx;   // 파일이 잘 열렸다면 열린 파일의 fd table에서의 index를
                   // 반환함 (아마도 열린 파일의 개수랑 동일할 것으로 보임)
}
//syscall.c

int
add_file_to_FDT (
    struct file *file) {   // 각 process에서 open한 부분을 기억하는 부분
  struct thread *cur = thread_current ();
  struct file **fdt = cur->fd_table;
  int fd_index = cur->fd_idx;

  while (fdt[fd_index] != NULL &&
         fd_index < FD_COUNT_LIMT) {   // 현재 fd_table의 빈공간을 찾는 작업
    fd_index++;
  }

  if (fd_index >= FD_COUNT_LIMT) {   // fd_index가 FD_count_limit 보다 크다는건
                                     // 공간이 없다는 의미
    return -1;
  }

  cur->fd_idx = fd_index;   // fd_index를 thread에 저장해주고
  fdt[fd_index] = file;     // fd table에 file을 저장
  return fd_index;
}

file size

file_length 는 사전에 구현되어 있는 함수임
들어온 fd를 이용하여 file을 찾고 그 크기를 찾아 return 함

int
file_size_handler (
    int fd) {   // input된 fd를 이용하여 file의 size를 찾아주는 handler
  struct file *file_ =
      find_file_using_fd (fd);   // 들어온 fd에 맞는 file을 찾아주고

  if (file_ == NULL)   // 만일 적합한 file을 찾지 못했다면 -1 을 return 함
    return -1;

  return file_length (file_);   // 미리 구현되어있는 file_length 함수를 사용하여
                                // file_의 크기를 찾아서 return 해줌
}

read

int
read_handler ( int fd, const void *buffer, unsigned size) {   // open 된 file을 읽고 + 읽은 file의 크기를 반환
  check_add (buffer);
  int read_result;   // file을 읽고 난 후 크기를 저장하기 위한 선언
  struct file *file_obj = find_file_using_fd (fd);   // 받은 식별자에 해당하는 file을 찾음

  if (file_obj == NULL)
    return -1;

  if (fd == STDIN_FILENO) {   // fd == STDIN_FILENO 는 표준 입력을 얘기한다 == 키보드 등으로 input 받음
    char word;   // 키보드로 입력을 한글자씩 받기위한 공간
    for (read_result = 0; read_result < size; read_result++) {   // read_result는 0부터 input들어온 개수 또는 처음 들어온 size까지 받아서 출력함
      word = input_getc ();
      if (word == "\0")   // 중간에 NULL 문자가 들어오면 break
        break;
    }
  } else if (fd == STDOUT_FILENO) {   // 표준 출력이면 출력부인데 읽을수 없으니 실패를 의미하는 -1을 return 함
    return -1;
  } else {
    lock_acquire (&filesys_lock);   // file_read를 사용하기 전에 lock을 걸어야함 - 내가 읽는 동안에 file이 수정되거나 간섭받으면 안되니깐
    read_result = file_read (file_obj, buffer, size);   // file_read는 구현이 되어있는 함수임
    lock_release (&filesys_lock);   // lock을 release해줌
  }
  return read_result;   // 읽은 크기를 return함
}

write

int
write_handler (int fd, const void *buffer, unsigned size) {
  check_add (buffer);
  struct file *file_obj = find_file_using_fd (fd);
  if (fd == STDIN_FILENO)   // fd == STDIN이면 표준 입력이라서 write가 불가함 따라서 return 0
    return 0;

  if (fd == STDOUT_FILENO) {   // fd == STDOUT이면 표준 출력 따라서
    putbuf (buffer, size);   // putbuf (사전에 구현된 함수) 함수릍 통해서 buffer와 size를 출력함
    return size;   // 그리고 결과로 크기만큼 return 함
  } else {
    if (file_obj == NULL)   // file_obj가 NULL이면 return 0;
      return 0;
    lock_acquire (&filesys_lock);   // file write를 하기 전에 lock을 걸고
    off_t write_result = file_write (file_obj, buffer, size);   // file에 buffer를 size만큼 쓰고
    lock_release (&filesys_lock);              // lock 을 풀어줌
    return write_result;   // 결과로 write 크기 (buffer에 적힌 크기) 를 return 함
  }
}

write 와 read의 중요한 점은 file_write, file_read를 사용할때 앞뒤로 lock을 걸어줘야한다는 것이다. 안그러면 니가 읽는동안에 또는 쓰는 동안에 file이 바뀔수도 있다

exception.c - page fault를 발생시키기 위해서

  1. 유효하지 않은 user 주소를 사용하거나
  2. 유저 프로그램이 커널 가상 메모리에 접근하려는 시도
//exception.c - page_fault 함수 안에
  if (user) {
    f->R.rdi = -1;
    exit_handler (f->R.rdi);
  }
profile
하루에 집중을

0개의 댓글

관련 채용 정보