시스템 콜 구현을 위해 유저 가상 주소 공간에 데이터를 읽고 쓰기 위한 방법
시스템콜의 인자로 들어온 포인터로부터 데이터를 읽어야할 때라면 이 방법을 통해 해야한다
유저가 유효하지 않은 포인터라면?/ ..
-> user memory가 맞는지 확인한다
/* Returns true if VADDR is a user virtual address. */
#define is_user_vaddr(vaddr) (!is_kernel_vaddr((vaddr)))
이미 구현되어있는 코드
-> 주소가 유저 영역인지 확인, 단순히 주소 범위만 확인한다
시스템 콜의 인자로 들어온 포인터가 안전하게 접근 가능한지 확인해야한다
is_user_vaddr는 주소 범위만 확인하기때문에 부족하다
유저 주소 범위안에 있으면서, 실제로 매핑되어있고, 읽거나 쓸 수 있는 주소인지 확인해야한다
void check_address(void *addr){
if (is_kernel_vaddr(addr) || //커널주소인지 확인 -> 커널영역에 접근하려는 시도 차단
pml4_get_page(cur->pml4, addr)==NULL){ //현재 프로세스의 pml4에 해당 주소가 실제 매핑되어있는지 확인
exit(-1);
}
}
//받아온 주소값이 유저 영역을 가리키고 할당된 페이지를 가리킴
//fd를 이용해서 file 찾기
전달받은 fd가 유효한 범위내인지 확인 후, 유효하다면 현재 프로세서의 파일 디스크립터 테이블에서 해당 파일 포인터 반환
static struct file *find_file_by_fd(int fd){
if (fd < 0 || fd >= FDCOUNT_LIMIT){
return NULL; // 유효하지 않은 fd면 NULL 반환
}
return cur->fd_table[fd]; // 현재 실행 중인 스레드의 파일 디스크립터 테이블에서 파일 반환
}
현재 프로세서의 fd table에서 비어있는 슬롯을 찾아 전달된 파일 저장, 해당 인덱스를 fd로 반환
int add_file_to_fdt(struct file *file){
struct file **fdt = cur-> fd_table;
while (cur -> fd_idx < FDCOUNT_LIMIT && fdt[cur -> fd_idx]){
cur->fd_idx++; //이미 사용중인 인덱스는 건너뜀
}
if (cur ->fd_idx>=FDCOUNT_LIMIT){
return -1;
} //파일 테이블이 가득 찼다면 실패
fdt[cur->fd_idx]=file; //현재 프로세스인덱스에 파일 저장
return cur ->fd_idx; //해당 fd반환
}
fd index는 이전에 마지막으로 사용한 fd이후부터 검색하여, 중복을 피하고 새로운 fd할당 (다음에 할당할 fd 후보 인덱스를 나타냄)
목표: userprog/syscall.c 안에 시스템 콜 핸들러를 구현
시스템 콜 번호를 받아오고, 어떤 시스템 콜 인자들을 받아오고, 그에 알맞는 액션을 취해야함
x86-64에서 syscall 명령어 사용
%rax: 시스템 콜 번호
시스템 콜 핸들러 syscall_handler() 가 제어권을 얻으면, 시스템 콜 번호는 rax 에 있고, 인자는 %rdi, %rsi, %rdx, %r10, %r8, %r9 순서로 전달됩니다.
시스템 콜 핸들러를 호출한 콜러의 레지스터는 전달받은 struct intr_frame 에 접근할 수 있습니다. (struct intr_frame은 커널 스택에 있습니다.)
함수리턴 값을 위해 그 값을 rax 레지스터에 넣음. 값을 리턴하는 시스템콜도 struct intr_frame의 rax멤버를 수정하는 식으로 ㄱㄱ
/* Projects 2 and later. */
SYS_HALT, /* Halt the operating system. */
SYS_EXIT, /* Terminate this process. */
SYS_FORK, /* Clone current process. */
SYS_EXEC, /* Switch current process. */
SYS_WAIT, /* Wait for a child process to die. */
SYS_CREATE, /* Create a file. */
SYS_REMOVE, /* Delete a file. */
SYS_OPEN, /* Open a file. */
SYS_FILESIZE, /* Obtain a file's size. */
SYS_READ, /* Read from a file. */
SYS_WRITE, /* Write to a file. */
SYS_SEEK, /* Change position in a file. */
SYS_TELL, /* Report current position in a file. */
SYS_CLOSE, /* Close a file. */
power_off () 호출해서 핀토스 종료
void halt(void){
power_off();
} //핀토스 종료
void exit(int status){
cur->exit_status=status; //종료시 상태
printf("%s: exit(%d)\n",thread_name(),status);
thread_exit();
}
//현재 동작 중인 유저 프로그램 종료, 커널에 상태를 리턴하면서 종료
//만약 부모 프로세스가 현재 유저 프로그램의 종료를 기다리던 중이라면, 종료되면서 리턴될 상태를 기다린다
//status ==0 : success