PintOS_2 | User Programs | System Call

wony·2022년 6월 26일

file 관련 system call

준비?

  • thread.h : thread 구조체 수정

    
    #include "threads/synch.h"	// synch.h 추가
    
    
    	/* 자식 프로세스 순회용 리스트 */
    	struct list child_list;
    	struct list_elem child;
    
    	/* wait_sema 를 이용하여 자식 프로세스가 종료할때까지 대기함. 종료 상태를 저장 */
    	struct semaphore wait_sema;
    	int exit_status;
    
    	/* 자식에게 넘겨줄 intr_frame
    	 * fork가 완료될때 까지 부모가 기다리게 하는 forksema
    	 * 자식 프로세스 종료상태를 부모가 받을때까지 종료를 대기하게 하는 free_sema
    	 */
    	struct intr_frame parent_if;
    	struct semaphore fork_sema;
    	struct semaphore free_sema;
    
    	/* fd table 파일 구조체와 fd index
    	 * 각 프로세스는 자신의 File Descriptor 테이블을 가지고 있음 (파일 객체 포인터의 배열)
    	 */
    	struct file **fdTable;
    	int fdIdx;
    
    	/* stdin_count와 stdout_count?
    	 * 표준입출력인 fd가 여러 개인 경우를 고려하여 만든 변수.
    	 * 즉, 입출력 fd가 0이 될 때까지 close를 닫으면 안 된다.
    	 */
    	int stdin_count;
    	int stdout_count;
    
    	/* 현재 실행 중인 파일 */
    	struct file *running;
  • thread.c : init_thread() 초기화

        	/* 자식 리스트 및 세마포어 초기화 */
        	/* project - user programs */
        	t->exit_status = 0;
        
  • exeception.c : page_fault() 수정

      static void
      page_fault (struct intr_frame *f) {
      	...
      	exit(-1);
      	...
      }
      ```
      
  • syscall.c : 함수 선언

      int open(const char *file);
      int filesize(int fd);
      int read(int fd, void *buffer, unsigned size);
      int write(int fd, void *buffer, unsigned size);
      void seek(int fd, unsigned position);
      unsigned tell (int fd);
      void close(int fd);
      
      static struct file *find_file_by_fd(int fd);
      int add_file_to_fdt(struct file *file);
      void remove_file_from_fdt(int fd);
      ```
      
    

구현할 내용

  • 수정 - for file system
    • 스레드 생성 시 File Descriptor를 초기화하도록 수정 pintos/src/threads/thread.c tid_t thread_create(const char name, int priority, thread_func function, void *aux)
      • struct thread에 추가된 필드 초기화

      • File Descriptor 테이블 메모리 할당

      • 프로세스 종료 시 열린파일을 모두 닫도록 수정

        pintos/src/userprog/process.c

        void process_exit(void)

      • 프로세스 종료가 일어날 경우 프로세스에 열려있는 모든 파일을 닫음

  • 추가 - for file system
    • File Descriptor 사용을 위한 함수 추가

      pintos/src/userprog/process.c

      int process_add_file(struct file *f)

      • 파일 객체에 대한 파일 디스크립터 생성

      struct file *process_get_file(intfd)

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

      void process_close_file(intfd)

      • 파일 디스크립터에 해당하는 파일을 닫고 해당 엔트리 초기화
    • File Descriptor 테이블 추가

      pintos/src/threads/thread.h

      struct thread

    • 파일 객체 포인터의 배열 // **fdTable

    • 현재 테이블에 할당된 파일 fd + 1 // fdIdx

    • File Descriptor 초기화

      pintos/src/threads/thread.c

      tid_t thread_create(constcharname, intpriority, thread_funcfunction, void*aux)

      • fd 초기값 : 2
      • fd 테이블 메모리 할당
    • File Descriptor 생성

      pintos/src/userprog/process.c

      int process_add_file(structfile *f)

      • 파일객체(structfile)를 File Descriptor 테이블에 추가
      • 프로세스의 File Descriptor의 최대값1 증가
      • 파일객체의 File Descriptor반환
    • 파일 객체(struct file) 검색

      pintos/src/userprog/process.c

      struct file *process_get_file(intfd)

      • File Descriptor 값에 해당하는 파일 객체 반환(fd 테이블 이용)
      • 해당 테이블에 파일 객체가 없을 시 NULL 반환
    • 모든 열린 파일 닫기

      pintos/src/userprog/process.c

      void process_exit(void)

      • 프로세스가 종료될 때 메모리누수를 방지하기 위해 프로세스에 열린 모든 파일을 닫음
      • File Descriptor 테이블 메모리 해제
  • 추가- for synchronization
    • 동시 접근이 일어날 수 있으므로 lock 사용 pintos/src/threads/synch.h struct lock filesys_lock 생성
      • userprog/syscall.h 헤더파일에 전역변수로 추가
      • read(), write() 시스템콜에서 파일에 접근하기전에 lock을 획득하도록 구현
      • 파일에 대한 접근이 끝난 뒤 lock 해제
  • 수정 - for synchronization
    • syscall_init() 함수에서 filesys_lock 초기화 코드 추가
      pintos/src/userprog/syscall.c
      • lock_init(structlock*) 인터페이스사용

갖다쓸 함수

  • for file system
       #include <filesys/filesys.h>
       
       struct file *filesys_open(constchar *name)
       // 파일 이름에 해당하는 파일을 여는 함수
       
       /*----------*/
       
       #include <filesys/file.h>
       
       void file_close(structfile *)
       // 파일을 닫는 함수
       
       off_t file_read(structfile *, void*, off_t)
       // 파일에 데이터를 읽는 함수
       
       off_t file_write(structfile *, constvoid *, off_t);
       // 파일에 데이터를 기록하는 함수
       
       void file_seek(structfile *, off_t);
       // 파일의 위치(offset)를 이동하는 함수
       
       off_t file_tell(structfile *);
       // 파일의 위치(offset)를 알려주는 함수
       
       off_t file_length(structfile *);
       // 파일의 크기를 알려주는 함수
       
       /*----------*/
       
       #include <devices/input.h>
       
       uint8_t input_getc(void)
       // 키보드로 입력받은 문자를 반환하는 함수
       
       /*----------*/
       
       #include <stdio.h>
       void putbuf(constchar *, size_t)
       // 문자열을 화면에 출력해주는 함수
     
  • 갖다쓸 함수 - for synchronization
    pintos/src/threads/synch.h
    
    void lock_init(structlock *)
    // lock을초기화
    
    void lock_acquire(structlock *)
    // 다른프로세스가접근하지못하도록lock을잠금
    
    void lock_release(structlock *)
    // 다른프로세스가접근할수있도록lock을해제
    

계층구조 관련 system call

준비?

  • thread.h : thread 구조체 수정
       #include "threads/synch.h"
       
       ...
       
       	/* 자식 프로세스 순회용 리스트 */
       	struct list child_list;
       	struct list_elem child;
       
       	/* wait_sema 를 이용하여 자식 프로세스가 종료할때까지 대기함. 종료 상태를 저장 */
       	struct semaphore wait_sema;
       	int exit_status;
       
       	/* 자식에게 넘겨줄 intr_frame
       	 * fork가 완료될때 까지 부모가 기다리게 하는 forksema
       	 * 자식 프로세스 종료상태를 부모가 받을때까지 종료를 대기하게 하는 free_sema
       	 */
       	struct intr_frame parent_if;
       	struct semaphore fork_sema;
       	struct semaphore free_sema;
       
       	/* fd table 파일 구조체와 fd index
       	 * 각 프로세스는 자신의 File Descriptor 테이블을 가지고 있음 (파일 객체 포인터의 배열)
       	 */
       	struct file **fdTable;
       	int fdIdx;
       
       	/* stdin_count와 stdout_count?
       	 * 표준입출력인 fd가 여러 개인 경우를 고려하여 만든 변수.
       	 * 즉, 입출력 fd가 0이 될 때까지 close를 닫으면 안 된다.
       	 */
       	int stdin_count;
       	int stdout_count;
       
       	/* 현재 실행 중인 파일 */
       	struct file *running;
       ```
       
  • thread.c
    • init_thrad() 초기화
       	/* 자식 리스트 및 세마포어 초기화 */
       	/* project - user programs */
       	t->exit_status = 0;	
       	list_init(&t->child_list);
       	sema_init(&t->wait_sema, 0);
       	sema_init(&t->fork_sema, 0);
       	sema_init(&t->free_sema, 0);
       ```
       
    • thread_create()
        /* 부모프로세스저장*/
        /* 프로그램이로드되지않음*/
        /* 프로세스가종료되지않음*/
        /* exit 세마포어0으로초기화*/
        /* load 세마포어0으로초기화*/
        /* 자식리스트에추가*/
        /* Add to run queue. */
        
        /* project2 - user programs */
        	/* parent-child */
        
        	struct thread *parent = aux;
        	sema_init(&t->wait_sema, 0);
        	sema_init(&t->free_sema, 0);
        	sema_init(&t->fork_sema, 0);
        **// 이게 어디드가야해??**
        
        	list_push_back(&parent->child_list, &t->child);
        
        thread_unblock(t);
        ```
        
    • get_child_process()
       /* 자식리스트에접근하여프로세스디스크립터검색*/
       /* 해당pid가존재하면프로세스디스크립터반환*/
       /* 리스트에존재하지않으면NULL 리턴*/
       
       struct thread *get_child_process(tid_t tid){
       	struct thread *curr = thread_current();
       	struct list_elem *child;
       	struct thread *t;
       
       	for(child=list_begin(&curr->child_list); child!=list_end(&curr->child_list); child=list_next(child)){
       		t = list_entry(child, struct thread, child);
       		if(tid == t->tid){
       			break;
       		}
       	}
       	if(!child){
       		return NULL;
       	}
       	return t;
       
       }
       ```
       
    • remove_child_process()
       /* 자식리스트에서제거*/
       /* 프로세스디스크립터메모리해제*/
       
       void remove_child_process(tid){
       	struct thread *curr = thread_current();
       	struct list_elem *child;
       	struct thread *t;
       	
       	for(child=list_begin(&curr->child_list); child!=list_end(&curr->child_list); child=list_next(child)){
       		t = list_entry(child, struct thread, child);
       		
       		if(tid == t->tid){
       			list_remove(child);
       			return;
       		}
       	}
       
       	if(!child){
       		return;
       	}
       	
       	return;
       }
       ```
       
      
    • exeception.c : page_fault() 수정
      static void
      page_fault (struct intr_frame *f) {
      	...
      	exit(-1);
      	...
      }
    • syscall.c : 함수 선언
      int exec (const char *cmd_line);
      int wait (pid_t pid);
      pid_t fork (const char *thread_name);

구현할 내용

  • 추가 및 수정 - exec
    • 메모리 적재 완료 시 부모 프로세스 다시 진행
      • pintos/src/threads/process.c
      • start_process() 세마포 이용한 제어
      • success = load 하고나서 메모리 적재 완료 시 다시 진행(세마포)
      • load의 성공실패 → 프로세스 디스크립터(thread)에 메모리 적재 성공 실패
    • 시스템 콜 핸들러에 추가
      • pintos/src/userprog/syscall.c
      • syscall_handler() 에 추가
  • 추가 및 수정 - wait
    - 부모 프로세스의 대기방식 수정(process_wait())
    - 원래 while(1) 였는데
    - sleep상태로 대기하도록
    - 자식 종료를 확인함
    - 프로세스 종료시 thread_exit()호출
    - thread 구조체에 프로세스 종료 표시(exit_status)
    - 유저 프로세스가 종료되면 부모 프로세스는 대기상태를 이탈하고 원래 것들을 진행(세마업)
    - 프로세스 디스크립터를 삭제하지 않도록??
    - thread_schedule_tail()
    - exit() 호출할때(userprog/syscall.c)
    - exit_status 저장
    - wait()은 process_wait을 부름
    • 그림으로 보는 wait()

  • 부모 프로세스와 자식 프로세스의 상태

갖다쓸 함수

  • 공유자원에 접근할 수 있는 프로세스의 수를 제한
    - 초과하면 대기해야함
    - value : 현재 공유자원에 접근할 수 있는 프로세스의 수
    - waiters : 공유 자원에 접근대기중인 프로세스 리스트

    pintos/src/threads/synch.h
    
    struct semaphore{
    
    	unsignedvalue; 
    	structlist waiters;  
    
    };
    void sema_init(struct semaphore *, unsignedvalue)
    // 세마포어의 value 값을 초기화
    
    void sema_down(struct semaphore *)
    // 세마포어의 value가 0일 경우 현재 스레드를 THREAD_BLOCK 상태로 변경 후 schedule() 호출
    
    void sema_up(struct semaphore *sema)
    // ready_list에 스레드가 있으면 맨앞(head)에 위치한 스레드를 THREAD_READY 상태로 변경 후 schedule()호출
    

0개의 댓글