Putting 'read-normal' into the file system...
Executing 'read-normal':
(read-normal) begin
(read-normal) open "sample.txt" for verification
(read-normal) size of sample.txt (8) differs from expected (373)
Page fault at 0x8: not present error reading page in kernel context.
Interrupt 0x0e (#PF Page-Fault Exception) at rip=800421eb0b
cr2=0000000000000008 error= 0
rax 0000000000000000 rbx 0000000000000000 rcx 000000004747fd18 rdx 0000000000000175
rsp 00000080042b8e90 rbp 00000080042b8ec0 rsi 000000004747fd18 rdi 0000000000000000
rip 000000800421eb0b r8 0000000000000000 r9 0000000000000000 r10 0000000000000000
r11 0000000000000206 r12 000000800421d277 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000206
es: 001b ds: 001b cs: 0008 ss: 0010
Kernel PANIC at ../../userprog/exception.c:97 in kill(): Kernel bug - unexpected interrupt in kernel
Call stack: 0x80042186d4 0x800421cf30 0x800421d0af 0x8004209680 0x8004209a9e 0x800421d6e7 0x800421d35f 0x800421d124 0x4007f8 0x400981 0x400111 0x40016f 0x400c10.
The `backtrace' program can make call stacks useful.
Read "Backtraces" in the "Debugging Tools" chapter
of the Pintos documentation for more information.
Timer: 337 ticks
Thread: 46 idle ticks, 270 kernel ticks, 21 user ticks
hd0:0: 0 reads, 0 writes
hd0:1: 87 reads, 234 writes
hd1:0: 103 reads, 0 writes
Console: 1896 characters output
read-normal test case에서 발생한 오류이다.. 페이지 폴트가 발생한 모습..
test를 통과하기 위해서 test case 출력문을 확인해봤다.
# -*- perl -*-
use strict;
use warnings;
use tests::tests;
check_expected ([<<'EOF']);
(read-normal) begin
(read-normal) open "sample.txt" for verification
(read-normal) verified contents of "sample.txt"
(read-normal) close "sample.txt"
(read-normal) end
read-normal: exit(0)
EOF
pass;
close 함수가 호출되는 것을 확인
아직 구현하지 않은 close를 구현하고 난 후 log
Putting 'read-normal' into the file system...
Executing 'read-normal':
(read-normal) begin
(read-normal) open "sample.txt" for verification
(read-normal) open "sample.txt" for verification: FAILED
read-normal: exit(1)
뭔데 fail이 나는데...? 그런데 exit을 보면 1(정상 종료)를 하고 있음...아...
그리고 write-normal test 도전!!
Putting 'write-normal' into the file system...
Executing 'write-normal':
(write-normal) begin
(write-normal) create "test.txt"
(write-normal) open "test.txt"
Page fault at 0x8: not present error reading page in kernel context.
Interrupt 0x0e (#PF Page-Fault Exception) at rip=800421ebf2
cr2=0000000000000008 error= 0
rax 0000000000000000 rbx 0000000000000000 rcx 0000000000604d60 rdx 0000000000000175
rsp 00000080042b8eb0 rbp 00000080042b8ee0 rsi 0000000000604d60 rdi 0000000000000000
rip 000000800421ebf2 r8 0000000000000000 r9 0000000000000000 r10 0000000000000000
r11 0000000000000202 r12 000000800421d277 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000202
es: 001b ds: 001b cs: 0008 ss: 0010
Kernel PANIC at ../../userprog/exception.c:97 in kill(): Kernel bug - unexpected interrupt in kernel
Call stack: 0x80042186d4 0x800421cf30 0x800421d0af 0x8004209680 0x8004209a9e 0x800421d4e0 0x800421d39a 0x800421d124 0x4001bd 0x40024c 0x400ced.
The `backtrace' program can make call stacks useful.
Read "Backtraces" in the "Debugging Tools" chapter
of the Pintos documentation for more information.
Timer: 477 ticks
Thread: 46 idle ticks, 410 kernel ticks, 21 user ticks
hd0:0: 0 reads, 0 writes
hd0:1: 110 reads, 251 writes
hd1:0: 105 reads, 0 writes
Console: 1834 characters output
바로 오류를 마주침...
일단 페이지 폴트가 발생했으므로 디버깅을 해본다.
이 로그를 봤을 때 create를 먼저 확인함. 해당 test는 create, open, write 함수만 호출하고, write는 대충 봤을 때 문제가 없었음. open은 create 확인하고 보면 되고.
bool create(const char *file, unsigned initial_size){
check_addr(file);
return filesys_create(file, initial_size);
}
(gdb) p file
$1 = 0x404402 "test.txt"
(gdb) p initial_size
$2 = 373
file은 test.txt이고, file size 373
(gdb) p $rax
$3 = 549833561090
(gdb) n
135 }
(gdb) p $rax
$4 = 1
filesys_create의 반환값이 1인 걸 확인하고 write로 넘어감.
int write (int fd, const void *buffer, unsigned size) {
check_addr(buffer);
if (fd > 64 || size == 0){
exit(-1);
}
// fd가 1이면 표준 출력
if (fd == 1) {
// putbuf: 커널 콘솔에 buffer의 내용을 size만큼 출력
putbuf(buffer, size);
return size; // 출력한 바이트 수 반환
}
struct file *find_f = find_file(fd);
return file_write (find_f, buffer, size);
}
여기서 앞 부분은 문제가 없기 때문에 putbuf함수를 확인해봄
(gdb) p buffer
$6 = 0x604f00 "(write-normal) begin\n"
(gdb) n
146 putchar_have_lock (*buffer++);
(gdb)
145 while (n-- > 0)
(gdb) p buffer
$7 = 0x604f01 "write-normal) begin\n"
(gdb) display buffer
1: buffer = 0x604f01 "write-normal) begin\n"
(gdb) n
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f01 "write-normal) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f02 "rite-normal) begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f02 "rite-normal) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f03 "ite-normal) begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f03 "ite-normal) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f04 "te-normal) begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f04 "te-normal) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f05 "e-normal) begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f05 "e-normal) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f06 "-normal) begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f06 "-normal) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f07 "normal) begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f07 "normal) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f08 "ormal) begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f08 "ormal) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f09 "rmal) begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f09 "rmal) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f0a "mal) begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f0a "mal) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f0b "al) begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f0b "al) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f0c "l) begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f0c "l) begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f0d ") begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f0d ") begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f0e " begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f0e " begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f0f "begin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f0f "begin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f10 "egin\n"
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f10 "egin\n"
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f11 "gin\n"
(gdb) p n
$8 = 4
(gdb) display n
2: n = 4
(gdb) n
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f11 "gin\n"
2: n = 3
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f12 "in\n"
2: n = 3
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f12 "in\n"
2: n = 2
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f13 "n\n"
2: n = 2
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f13 "n\n"
2: n = 1
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f14 "\n"
2: n = 1
(gdb)
146 putchar_have_lock (*buffer++);
1: buffer = 0x604f14 "\n"
2: n = 0
(gdb)
145 while (n-- > 0)
1: buffer = 0x604f15 ""
2: n = 0
(gdb)
147 release_console ();
1: buffer = 0x604f15 ""
2: n = 18446744073709551615
정상적으로 버퍼에 저장된 문자열을 읽고, byte size를 반환
한참 찾았지만 보이지 않았던 이 문제의 해결은 간단했다
case SYS_OPEN:
f->R.rax = open(f->R.rdi);
break;
system handler에 open()함수를 추가해 주지 않았던 것...
근데 이상하다?? 그러면 오류가 발생했을 때 open은 왜 출력됐던 거지??
write-normal) begin
(write-normal) create "test.txt"
(write-normal) open "test.txt" <- 이거 왜 출력됨??
Putting 'write-normal' into the file system...
Executing 'write-normal':
(write-normal) begin
(write-normal) create "test.txt"
(write-normal) open "test.txt"
(write-normal) open "test.txt": FAILED
write-normal: exit(1)
이러면 이렇게 나온다.... 젠장... 또 fail...
그래서 좀 더 찾아봤다..
int allocate_fd(struct file *f){
struct thread *t = thread_current();
if (f == NULL || t->next_fd >= 64){
return -1;
}
t->fdt[t->next_fd] = f;
return t->next_fd++;
}
file descripter는 0, 1, 2는 file을 할당하지 않는다. file input, output과 error를 담당하기 때문에 남겨둔다. 따라서
(gdb) p t->next_fd
$9 = 0
현재 fd의 번호는 0번
(gdb) p t->fdt[t->next_fd]
$11 = (struct file **) 0x800423c038
근데 0번의 file addr을 저장하네? 이거 잘못된 거 아닌가? 라고 생각해서
int allocate_fd(struct file *f){
struct thread *t = thread_current();
if (f == NULL || t->next_fd >= 64){
return -1;
}
if(t->next_fd >= 3){
for(int i = 3; i<64; i++){
if(t->fdt[i] == NULL){
t->fdt[i] = f;
return i;
}
}
return -1;
}
t->fdt[t->next_fd] = f;
return t->next_fd++;
}
이렇게 바꾸긴 했는데 솔직히 현재 스레드의 fd가 0인데 이렇게 수정하는 게 무슨 상관이냐고...
삽질한 것 같다...