SIGSEGV vs -EFAULT
우리가 흔히 SIGSEGV 받으면 아 잘못된 페이지를 참조했구나! 라고 안다.
그렇다면, 만약 write(1, buf , 0x1000) 같은 저수준의 syscall도 buf가 잘못된 주소를 가리키면
SIGSEGV 가 일어날까? 정답은 아니다.
유저레벨과 커널레벨이 존재하는 것은 모두 알것이다. 이 2개의 레벨 마다 다른데
| 유저 코드가 잘못된 포인터를 직접 역참조(*p = 1, mov (%rsi),%eax 등) | user mode | 커널의 페이지-폴트 핸들러가 “사용자 잘못” 판정 → do_user_addr_fault() | SIGSEGV(or SIGBUS) 시그널 |
| 유저가 잘못된 포인터를 시스템콜 인자로 넘김(write(fd, bad_ptr, len)) | user → kernel mode 로 스위치 | 커널이 copy_from_user()/copy_to_user()에서 fault 감지 | 리턴값 −1 & errno=EFAULT |
다음과 같다.
즉, 커널레벨에서 복구 할 수 있는 오류는 간단히 오류코드를 가지고 프로세스가 계속 실행된다.
단 다음과 경우에는 프로세스가 정지될 수 도 있다.
커널이 복구할 수 없는 컨텍스트
매우 드물지만, 인터럽트가 꺼진 구간 등 “fault 허용 불가” 영역에서 사용자 주소를 잘못 만지면 커널이 BUG/Oops로 프로세스를 SIGKILL 하거나 커널 패닉이 날 수도 있다. (하지만 정상적인 sys_write 경로에선 그런 일이 없다.