int open (const char *file);
첫번째 인자의 이름을 가진 파일을 오픈한 후 비음수 정수인 file descriptor (이하 fd)를 반환한다. fd 번호로 0번, 1번은 이미 역할이 정해져있으므로 (0: STDIN, 1: STDOUT) open 시스템콜이 이 두 번호를 리턴하는 일은 없다. 이 두 번호는 시스템콜을 호출할때의 인자로서만 유효하다.
🔎 file descriptor 유의할 점
close()
호출에 의해 닫힌다.위의 내용을 고려하여 fd 구조체를 생성한다.
struct fd
{
int value;
struct file *file;
struct list_elem elem;
};
fd 구조체가 가져야 하는 멤버변수는 fd 값을 나타내는 value
, 이 fd와 연결된 file을 나타내는 file
, 그리고 fd 자체를 list로 관리해야 하기 때문에 필요한 list_elem 인 elem
이다.
이제 스레드 구조체 멤버변수를 수정한다. 프로세스가 오픈한 fd 들을 담는 fd_list를 추가하고, 다음 생성할 fd의 value를 계산하기 위해 현재 fd 값 중 최고 값을 보관하는 fd_count 값을 추가한다.(왜냐면 현재 최고 fd값이 n이라면 그 다음 fd값은 n+1이 될 것이기 때문)
/* thread.h 의 thread 구조체 */
...
struct list fd_list;
int fd_count;
...
이제 스레드 구조체를 수정했으니, 스레드를 시작할 때 fd_list를 init 하고, fd_count를 초기화 하는 코드를 추가한다.
t->fd_count = 1;
list_init(&t->fd_list);
fd 값은 2부터 시작해야 하기 때문에 (0,1 은 이미 사용처가 정해졌으니까) fd_count는 1로 초기화 하고, list_init을 통해 fd_list 리스트를 init 한다.
시스템콜 open이 호출되면 시스템콜 핸들러에 의해 실행되는 syscall_open 를 다룰 준비가 끝났다! file_open() 함수는 아래와 같이 정의된다.
int syscall_open (struct intr_frame *f){
check_addr(f->R.rdi);
struct list * fd_list;
struct file *open_file;
struct ELF64_hdr ehdr;
fd_list = &thread_current()->fd_list;
open_file = filesys_open(f->R.rdi);
if(open_file == NULL){
f->R.rax = -1;
return -1;
}
struct fd *fd = (struct fd*)malloc(sizeof(struct fd));
fd->value = thread_current()->fd_count + 1;
fd->file = open_file;
list_push_back(fd_list,&fd->elem);
thread_current()->fd_count +=1;
// open 시 해더파일을 읽어서 excutable 한 파일인지 확인
if(!(file_read (fd->file, &ehdr, sizeof ehdr) != sizeof ehdr
|| memcmp (ehdr.e_ident, "\\177ELF\\2\\1\\1", 7)
|| ehdr.e_type != 2
|| ehdr.e_machine != 0x3E // amd64
|| ehdr.e_version != 1
|| ehdr.e_phentsize != sizeof (struct ELF64_PHDR)
|| ehdr.e_phnum > 1024)){
file_deny_write(fd->file);
}
open_file->pos=0;
f->R.rax = fd->value;
return fd->value;
}