사용자 모드
운영체제가 일반 응용 프로그램을 실행할 때 사용하는 제한된 권한의 CPU 실행 모드입니다.
왜 필요한가?
모든 프로그램이 하드웨어에 직접 접근할 수 있다면 악성 프로그램이 디스크를 포맷하거나 다른 프로세스의 메모리를 훼손할 수 있습니다. 이를 방지하기 위해 CPU는 모드 비트(Mode Bit)로 실행 권한을 분리합니다.
사용자 모드 vs 커널 모드
| 항목 | 사용자 모드 | 커널 모드 |
|---|---|---|
| 모드 비트 | 1 | 0 |
| 실행 주체 | 응용 프로그램 | OS 커널 |
| 권한 | 제한된 명령어만 실행 | 모든 명령어(특권 명령 포함) 실행 가능 |
| 메모리 접근 | 자신의 가상 주소 공간만 | 전체 메모리 접근 가능 |
| 하드웨어 접근 | 불가 (시스템 콜 필요) | 직접 접근 가능 |
| 오류 발생 시 | 해당 프로세스만 종료 | 시스템 전체 크래시(커널 패닉) 가능 |
모드 전환 흐름
┌─────────────────────────────────────────┐
│ 사용자 모드 (모드 비트: 1) │
│ │
│ 응용 프로그램 실행 중 │
│ │ │
│ ▼ 시스템 콜 / 인터럽트 / 예외 │
├─────────── Trap (모드 전환) ──────────────┤
│ 커널 모드 (모드 비트: 0) │
│ │
│ 커널이 요청 처리 │
│ │ │
│ ▼ 처리 완료 │
├─────────── Return (모드 복귀) ────────────┤
│ 사용자 모드 (모드 비트: 1) │
└─────────────────────────────────────────┘
모드 전환이 발생하는 3가지 경우
| 원인 | 설명 | 예시 |
|---|---|---|
| 시스템 콜 | 프로세스가 커널 기능을 명시적으로 요청 | read(), fork(), open() |
| 인터럽트 | 하드웨어가 CPU에 이벤트 알림 | 키보드 입력, 디스크 I/O 완료, 타이머 |
| 예외(Exception) | 프로그램 실행 중 오류 발생 | 0으로 나누기, 페이지 폴트, 잘못된 메모리 접근 |
사용자 모드에서 할 수 없는 것 (특권 명령)
- I/O 장치 직접 제어 (
in,out명령) - 인터럽트 비활성화 (
cli명령) - 다른 프로세스의 메모리 영역 접근
- 모드 비트 직접 변경
- 메모리 관리 레지스터(페이지 테이블 베이스) 수정
이러한 명령을 사용자 모드에서 시도하면 예외(Exception)가 발생하고, 커널이 해당 프로세스를 강제 종료합니다.
Java에서의 예시
// 모든 Java 코드는 사용자 모드에서 실행됨
int sum = 1 + 2; // 사용자 모드 (모드 전환 없음)
String s = "hello".toUpperCase(); // 사용자 모드 (모드 전환 없음)
// 아래 코드는 내부적으로 커널 모드 전환이 발생
System.out.println("hello"); // write() 시스템 콜 → 커널 모드 전환
FileInputStream fis = new FileInputStream("a.txt"); // open() 시스템 콜
Thread.sleep(1000); // nanosleep() 시스템 콜