왜 유저모드와 커널모드를 구분해야 하나요?

신뢰할 수 없는 사용자 프로그램으로부터 커널과 하드웨어 자원을 보호하고, 프로세스 간 격리를 보장하여 시스템 전체의 안정성과 보안을 유지하기 위해서입니다. ** 사용자 모드 ** 커널 모드

구분하지 않으면 생기는 문제

[모드 구분이 없는 경우]

악성 프로그램 → 디스크 포맷 명령 직접 실행 → 전체 데이터 손실
버그 프로그램 → 커널 메모리 덮어쓰기     → 시스템 크래시
일반 프로그램 → 다른 프로세스 메모리 접근  → 데이터 유출·변조
무한루프      → CPU 독점                → 다른 프로세스 실행 불가
[모드 구분이 있는 경우]

악성 프로그램 → 디스크 포맷 시도 → CPU가 차단 → 해당 프로세스만 종료
버그 프로그램 → 커널 메모리 접근 → MMU가 차단 → 해당 프로세스만 종료
일반 프로그램 → 다른 프로세스 접근 → 페이지 테이블 격리 → 접근 불가
무한루프      → 타이머 인터럽트 → 커널이 강제 선점 → 다른 프로세스 실행

구분이 필요한 4가지 이유

1. 하드웨어 보호

사용자 프로그램이 하드웨어를 직접 제어하면 시스템이 파괴될 수 있습니다.

위협모드 구분 없을 때모드 구분 있을 때
디스크 직접 쓰기파일 시스템 파괴 가능I/O 명령어가 특권 명령 → 차단
인터럽트 비활성화시스템 먹통 가능cli 명령이 특권 명령 → 차단
NIC 직접 제어네트워크 스니핑 가능시스템 콜로만 접근 가능
사용자 프로그램이 in/out 명령어로 디스크 직접 제어 시도
    │
    ▼
CPU: 모드 비트 = 1 (사용자 모드) → 특권 명령어!
    │
    ▼
General Protection Fault → 프로세스 강제 종료
    │
    ▼
시스템은 안전하게 유지

2. 메모리 보호 (프로세스 격리)

각 프로세스가 독립된 가상 주소 공간을 가지므로 서로의 메모리에 접근할 수 없습니다.

[모드 구분 없을 때]
프로세스 A ──→ 물리 주소 0x1000 직접 접근 ──→ 프로세스 B 데이터 변조

[모드 구분 있을 때]
프로세스 A                     프로세스 B
┌─────────────┐             ┌─────────────┐
│ 가상 주소 공간 │             │ 가상 주소 공간 │
│ 0x0000~0xFFFF│             │ 0x0000~0xFFFF│
└──────┬──────┘             └──────┬──────┘
       │ MMU                       │ MMU
       ▼                           ▼
  물리 주소 0x1000             물리 주소 0x5000
  (서로 다른 물리 영역 → 접근 불가)

3. 커널 무결성 보호

커널 코드와 데이터를 사용자 프로그램이 변조할 수 없도록 보호합니다.

[모드 구분 없을 때]
악성 프로그램 → sys_call_table 주소를 조작
             → read() 호출 시 악성 코드 실행
             → 루트킷 설치 완료

[모드 구분 있을 때]
악성 프로그램 → 커널 메모리 영역 접근 시도
             → 페이지 테이블: User/Supervisor 비트 = Supervisor
             → Page Fault 발생 → 프로세스 종료

4. CPU 보호 (독점 방지)

타이머 인터럽트와 커널의 스케줄러가 협력하여 하나의 프로세스가 CPU를 독점하는 것을 방지합니다.

[모드 구분 없을 때]
프로그램: while(true) {} + cli(인터럽트 비활성화)
→ 타이머 인터럽트도 차단 → CPU 영원히 독점 → 시스템 먹통

[모드 구분 있을 때]
프로그램: while(true) {}
→ cli 실행 시도 → 특권 명령 → 차단
→ 타이머 인터럽트 정상 발생
→ 커널이 강제 선점 → 다른 프로세스에 CPU 할당

Dual Mode가 제공하는 보호 체계 종합

보호 대상위협보호 메커니즘커널 모드에서만 가능한 이유
I/O 장치직접 제어로 장치 파괴I/O 명령어를 특권 명령으로 지정in/out 명령이 특권 명령
메모리다른 프로세스·커널 영역 접근MMU + 페이지 테이블페이지 테이블 수정이 특권 명령
CPU무한루프로 독점타이머 인터럽트 + 선점 스케줄링인터럽트 제어가 특권 명령
커널 코드시스템 콜 테이블 변조커널 메모리 영역 접근 차단CR3 변경이 특권 명령

만약 단일 모드라면? — MS-DOS 사례

MS-DOS (단일 모드)
┌────────────────────────────────────┐
│ 응용 프로그램                       │
│   - 하드웨어 직접 접근 가능          │
│   - 다른 프로그램 메모리 접근 가능    │
│   - 시스템 파일 자유롭게 수정 가능    │
├────────────────────────────────────┤
│ DOS 커널                           │
│   - 보호 기능 없음                  │
│   - 악성 프로그램에 무방비           │
└────────────────────────────────────┘
→ 바이러스가 쉽게 시스템 전체를 감염시킬 수 있었음

현대 OS (Dual Mode)
┌────────────────────────────────────┐
│ 응용 프로그램 (사용자 모드)           │
│   - 제한된 권한                     │
│   - 시스템 콜로만 커널 기능 사용      │
├──────────── 모드 경계 ──────────────┤
│ OS 커널 (커널 모드)                  │
│   - 완전한 권한                     │
│   - 자원 접근을 중재·검증            │
└────────────────────────────────────┘
→ 한 프로그램의 오류가 시스템 전체에 영향을 주지 않음

Java에서 체감하는 Dual Mode의 효과

// 1. 메모리 보호 — 다른 프로세스 메모리 접근 불가
// Java에서는 포인터 자체가 없지만, C에서 임의 주소 접근 시도 시
// MMU가 차단 → Segmentation Fault

// 2. 안전한 파일 접근 — 커널이 권한 검사
try {
    // 커널이 파일 권한을 확인한 후 접근 허용/거부
    new FileInputStream("/etc/shadow");
} catch (IOException e) {
    // 권한 없음 → 커널이 -EACCES 반환 → IOException
    System.out.println("접근 거부: " + e.getMessage());
}

// 3. CPU 독점 방지 — 무한루프도 다른 프로세스에 영향 없음
new Thread(() -> {
    while (true) {} // 이 스레드가 CPU를 독점해도
}).start();
// 타이머 인터럽트 → 커널이 선점 → 다른 스레드 정상 실행
System.out.println("정상 출력됨");

핵심 정리

유저모드와 커널모드를 구분하는 이유

= 신뢰할 수 없는 프로그램으로부터 시스템을 보호하기 위해

  ┌────────────────────────────────────────────┐
  │ 1. I/O 보호    → 하드웨어 직접 접근 차단      │
  │ 2. 메모리 보호  → 프로세스 간 격리             │
  │ 3. CPU 보호    → 독점 방지 (타이머 인터럽트)   │
  │ 4. 커널 보호   → 커널 코드·데이터 변조 방지     │
  └────────────────────────────────────────────┘

  → 한 프로그램의 오류나 악의가 시스템 전체에 영향을 주지 않음

CSLOG에서 보기