[Pintos] - User Program(System call) - 2

Junyeong Fred Kim·2022년 1월 5일
0

운영체제

목록 보기
13/27

이어서 진행해보도록 하겠다.

이전 글에서는 비교적 쉬운(?) 시스템 콜들을 다루어보았는데, 이번 글에서는 wait(), open(), filesize() 등을 다루어 보겠다.

📟 int wait (pid_t);

구현 설명

  • process_wait()함수를 호출
  • 자식 스레드가 실행될 때까지 기다렸다가, 자식 스레드의 status를 return한다.

✏️ 구현

// userprog/syscall.c

int wait (tid_t tid)
{
    /* 자식 프로세스가 종료 될 때까지 대기 */
    /* process_wait() 사용 */
    process_wait (tid);
}

🙋 help func.

int process_wait (tid_t child_tid UNUSED);

// userprog/process.c

int process_wait (tid_t child_tid UNUSED)
{

    /* 자식 프로세스의 프로세스 디스크립터 검색 */
    /* 예외 처리 발생시 -1 리턴 */
    /* 자식프로세스가 종료될 때까지 부모 프로세스 대기(세마포어 이용) */
    /* 자식 프로세스 디스크립터 삭제 */
    /* 자식 프로세스의 exit status 리턴 */
    
    struct thread *curr = thread_current ();
    struct thread *child_th = get_child_with_pid(child_tid);

    if (child_th == NULL)
        return -1;

    sema_down(&child_th->wait_sema);

    int exit_status = child_th->exit_status;

    list_remove(&child_th->child_elem);

    sema_up(&child_th->free_sema);
    return exit_status;
}

프로세스의 정보를 알기 위해 프로세스 디스크립터 검색
자식 프로세스가 종료되지 않았으면 부모 프로세스 대기
유저 프로세스가 정상적으로 종료 시 exit status 반환, 아닐 시 -1 반환


📟 int open (const char *file);

구현 설명

  • 파일을 열 때 사용하는 시스템 콜
  • 성공시 fd를 생성하고 반환, 실패 시 -1 반환
  • File: 파일의 이름 및 경로 정보

✏️ 구현

// userprog/syscall.c

int open (const char *file)
{
    check_address(file);
    struct file *file_obj = filesys_open(file);

    if (file_obj == NULL)
        return -1;

    int fd = process_add_file(file_obj);

    if (fd == -1)
        file_close(file_obj);

    return fd;
}

파일을 open,
해당 파일 객체에 파일 디스크립터 부여
파일 디스크립터 리턴
해당 파일이 존재하지 않으면 -1 리턴

🙋 help func.

int process_add_file (struct file *f)

  • 파일 객체에 대한 파일 디스크립터 생성
  • 파일 객체(struct file)를 File Descriptor 테이블에 추가
  • 프로세스의 File Descriptor의 최대값 1 증가
  • 파일 객체의 File Descriptor 반환
  • 파일 객체 포인터의 배열
  • File Descriptor 등록 시 2부터 순차적으로 File Descriptor 1씩 증가
    fd 0(STDIN_FILENO)은 표준 입력이고,
    fd 1(STDOUT_FILENO)은 표준 출력입니다
  • open() 시 File Descriptor를 리턴
// userprog/syscall.c

int process_add_file (struct file *f)
{
    struct thread *curr = thread_current();
    struct file **fdt = curr->fdTable; // file descriptor table

    while (curr->fdIdx < FDCOUNT_LIMIT && fdt[curr->fdIdx])
        curr->fdIdx++;

    if (curr->fdIdx >= FDCOUNT_LIMIT)
        return -1;

    fdt[curr->fdIdx] = f;
    return curr->fdIdx;
}

fdTable이 꽉 차면 넣을수 없기 때문에 -1을 반환해준다.

  • thread 구조체에 새롭게 추가할 것
    fdTable: 프로세스가 현재 사용 중인 파일을 관리하기 위한 테이블이며, 프로세마다 하나씩 가지고 있다.
    fdIdx: fdTable과 해당 테이블을 인덱싱할 때 사용하기 위해 추가해준다.
// thread.h

struct thread {
    struct file **fdTable;	
    int fdIdx;
};
  • 또한, thread가 생성할 때, thread_create(): fdTablefdIdx를 초기화주어야한다.

📟 int filesize (int fd);

  • 파일의 크기를 알려주는 시스템 콜
  • 성공 시 파일의 크기를 반환, 실패시 -1 반환

✏️ 구현

// userprog/syscall.c

int filesize (int fd)
{
	struct file *file_obj = process_get_file(fd);
	if (file_obj == NULL)
		return -1;

	return file_length(file_obj);
}

fd 로 열려 있는 파일의 크기(바이트)를 반환한다.
file.c안에 file_length라는 wrapper function 이용

🙋 help func.

struct file *process_get_file (int fd);

  • File Descriptor값에 해당하는 파일 객체 반환. (File Descriptor 테이블 이용)
  • 해당 테이블에 파일 객체가 없을 시 NULL 반환
struct file *process_get_file (int fd)
{
	struct thread *curr = thread_current ();
	if (fd < 0 || fd >= FDCOUNT_LIMIT)
		return NULL;

	return curr->fdTable[fd];
}

프로세스의 파일 디스크립터 테이블을 검색하여 파일 객체의 주소를 리턴

profile
기억보다 기록

1개의 댓글

comment-user-thumbnail
2024년 3월 21일

안녕하세요, could you please share the slides?Thank u very much:)

답글 달기