유저 모드, 커널 모드, 시스템 콜, 인터럽트

jhj603·2025년 9월 11일
0

CPU의 모드가 만들어진 이유

컴퓨터의 중앙 처리 장치(CPU)는 운영체제의 안정성과 자원 보호를 위해 두 가지 분리된 모드로 동작한다.

유저 모드와 커널 모드를 나누는 핵심적인 이유 2가지
1. 자원 관리를 통한 성능 향상
2. 시스템 보호(응용 프로그램 간, 운영체제와 응용 프로그램 간)

만약 어떤 프로그램이 다른 프로그램이나 하드디스크의 특정 파일을 직접 지워버리거나, 네트워크 카드를 점령해 다른 프로그램이 인터넷을 쓰지 못하게 만들면 컴퓨터 전체가 엉망이 된다.


커널 모드와 유저 모드

1. 커널 모드
CPU가 모든 하드웨어 자원에 직접 접근하고 모든 종류의 명령어를 실행할 수 있는 특권(privileged) 상태. 운영체제의 핵심 코드는 이 모드에서 동작하며, 시스템의 모든 자원을 관리하고 제어하는 역할을 수행. 메모리 관리, 프로세스 스케줄링 등 시스템의 핵심 기능은 커널 모드에서만 실행될 수 있음.

2. 유저 모드
사용자 애플리케이션(예: 웹 브라우저, 게임)이 실행되는 제한된(non-privileged) 상태. 이 모드에서 실행되는 프로그램은 하드웨어나 메모리에 직접 접근할 수 없으며, 운영체제가 허용한 기능만을 사용할 수 있음. 이는 하나의 프로그램이 오류를 일으켜도 다른 프로그램이나 시스템 전체에 영향을 주지 않도록 보호하는 중요한 매커니즘.


컨텍스트 스위칭

  • 정의 : 하나의 프로세스 실행을 멈추고, 그 프로세스의 현재 실행 상태(Context)를 저장한 뒤, 다른 프로세스의 저장된 상태를 복원하여 실행을 이어가는 과정
    컨텍스트란, CPU 레지스터 값, 프로그램 카운터(다음에 실행할 명령어 주소), 스택 포인터, 열린 파일 목록 등 해당 프로세스의 실행에 필요한 모든 정보를 의미

  • PintOS와의 연관성
    시스템 콜이나 인터럽트가 발생하면, CPU는 현재 실행 중인 유저 프로세스의 컨텍스트를 해당 프로세스의 커널 스택에 안전하게 저장. 그 뒤 커널 코드 실행. 커널 작업이 끝나면, 저장했던 컨텍스트를 다시 CPU 레지스터로 복원해 원래의 유저 프로세스 실행 재개


  • 질문 - 유저 모드에서 실행되는 프로그램이 파일 읽기나 네트워크 통신처럼 커널 모드의 기능이 반드시 필요한 작업을 수행하려면, 어떤 과정을 통해 운영체제에 서비스를 요청해야 하는가?
  • 대답 - 운영체제가 제공하는 특수 함수를 유저 모드에서 실행되는 프로그램이 사용해서 운영체제가 서비스를 수행하게끔 하고 다 처리된 데이터를 운영체제가 반환

시스템 콜

  • 시스템 콜 인터페이스
    운영체제가 제공하는 특수 함수들의 집합
    유저 프로그램은 직접 커널의 코드를 실행하는 것이 아니라, 운영체제가 미리 정해둔 이 인터페이스를 통해 서비스 요청

  • 시스템 콜 동작 과정

  1. 함수 호출 : 유저 프로그램이 일반적인 라이브러리 함수(예 : C언어의 printf, fopen)를 호출

  2. 내부 동작 : 라이브러리 함수 내에서, 실제 커널에 요청을 보내기 위한 준비를 함. 커널을 호출하기 위한 특별한 명령어(예 : syscall, int 0x80)를 실행

  3. 트랩(Trap) 발생 : 특별한 명령어가 실행되는 순간, CPU는 소프트웨어 인터럽트, 즉 트랩을 발생시킴

  4. 모드 전환 : 트랩이 발생하면, CPU는 즉시 실행 모드를 유저 모드에서 커널 모드로 전환하고, 운영체제가 미리 등록해 둔 시스템 콜 핸들러로 실행 흐름을 넘김

  5. 서비스 수행 : 시스템 콜 핸들러는 프로그램이 요청한 작업(예 : 파일 열기, 화면 출력)이 무엇인지 파악하고 해당 커널 코드를 실행해 요청 처리

  6. 복귀 : 작업이 완료되면, CPU는 다시 유저 모드로 전환하고, 시스템 콜을 호출했던 프로그램의 다음 코드로 실행 흐름을 되돌려 줌. 이 때, 처리 결과가 반환

시스템 콜은 유저 모드에서 실행되던 프로그램이 잠시 커널 모드로 전환해 운영체제의 기능을 빌려 쓰는 유일한 '공식적인 창구'


ABI(Application Binary Interface)

  • ABI : 컴파일된 프로그램이 운영체제 및 다른 라이브러리와 상호작용하는 방식에 대한 낮은 수준의 규칙
    운영체제와 애플리케이션 사이의 매우 엄격한 규약(Interface).
    시스템 콜이 대표적
    예를 들어, "시스템 콜 59번은 execve이고, 첫 번째 인자는 %rdi레지스터에, 두 번째 인자는 %rsi레지스터에 넣어 호출해야 한다"와 같은 구체적인 약속을 정의

  • PintOS와의 연관성
    ABI를 직접 설계하고 구현해야 함. 어떤 시스템 콜에 몇 번을 할당할지, 인자들은 사용자 스택의 어느 위치에서 어떻게 읽어올지를 직접 코드로 정의해야 함.


인터럽트

  • 1. 하드웨어 인터럽트
    하드웨어 장치가 CPU의 주의를 필요로 할 때 보내는 신호. 사용자가 키보드를 누르거나, 마우스가 움직이거나, 디스크가 파일 읽기를 완료했을 때 발생. CPU는 현재 하던 작업을 잠시 멈추고, 해당 하드웨어의 요청을 먼저 처리

  • 2. 소프트웨어 인터럽트
    프로그램이 스스로 발생시키는 인터럽트. 두 가지 주요 상황에서 사용
    1) 시스템 콜 : 유저 프로그램이 커널의 서비스를 요청하기 위해 의도적으로 발생시키는 경우.
    2) 예외 : 프로그램이 오류를 일으켰을 때(예 : 0으로 나누기, 허용되지 않은 메모리 접근) CPU에 의해 자동 발생. 운영체제는 이 인터럽트를 받아 프로그램 강제 종료 등의 처리 수행

이 두 종류의 인터럽트 모두 CPU가 현재 실행 흐름을 멈추고, 운영체제가 미리 정해둔 인터럽트 서비스 루틴 또는 인터럽트 핸들러를 실행하게 만듬.


  • 질문 : CPU는 수많은 종류의 인터럽트(키보드, 마우스, 시스템 콜 등) 중에서 어떤 인터럽트가 발생했는지 어떻게 구별하고, 각각에 맞는 올바른 핸들러를 찾아갈 수 있는가?
  • 대답 : 파일 식별자로 구별할 것 같다.

인터럽트 벡터 테이블 or 인터럽트 서술자 테이블

운영체제는 파일 식별자와 비슷한 방식으로 여러 대상을 구별하지만 인터럽트는 각 인터럽트에 할당된 고유한 번호(인터럽트 넘버, Interrupt Number)를 사용

  • 인터럽트 벡터 테이블 or 인터럽트 서술자 테이블
    인터럽트 넘버를 효율적으로 처리하기 위해 CPU와 운영체제가 사용하는 메모리에 저장된 하나의 큰 특별한 배열
    - 테이블 인덱스 : 인터럽트 번호가 배열의 인덱스로 사용
    - 테이블의 내용 : 각 인덱스 위치에 해당 인터럽트를 처리할 인터럽트 핸들러 함수의 메모리 주소 저장

  • 인터럽트 발생 처리 과정

  1. 발생한 인터럽트 고유 번호(인터럽트 넘버) 확인
  2. 그 번호를 인덱스로 사용해 인터럽트 벡터 테이블에서 해당 위치 탐색
  3. 그 위치에 저장된 메모리 주소로 즉시 이동해 해당 핸들러 함수 실행

  • 질문 : 테이블 구조를 생각했을 때, PintOS에서 시스템 콜을 처리하기 위한 코드는 이 테이블의 어느 부분과 연결되어야 하는가?
  • 대답 : 시스템 콜이 호출되면 해당 시스템 콜에 대한 정수 값을 인덱스로 해서 테이블에서 핸들러 함수 주소를 찾고 그 주소의 핸들러 함수를 수행

시스템 콜도 소프트웨어 인터럽트의 한 종류이기 때문에, PintOS에서는 인터럽트 벡터 테이블의 특정 위치에 시스템 콜을 처리하는 핸들러 함수의 주소를 등록해야 함.

과제 문서에서 유저 프로그램이 시스템 콜을 호출할 때 int 0x30 이라는 명령어를 사용하도록 약속되어 있음. 0x30이 인터럽트 번호

PintOS에서 인터럽트 처리 전체 흐름
1. PintOS가 부팅될 때, IDT의 0x30번 위치에 우리가 만든 시스템 콜 핸들러 함수의 주소 등록
2. 유저 프로그램이 시스템 콜 요청 시, int 0x30이 실행
3. CPU는 IDT의 0x30번을 보고 우리가 등록한 핸들러 함수로 점프

  1. 핸들러 함수는 프로그램이 요청한 구체적인 시스템 콜(예 : halt, exit, exec 등)이 무엇인지 파악하고, 그에 맞는 커널 코드 실행

인터럽트 마스킹

  • 인터럽트 마스킹 : 특정 인터럽트를 잠시 무시(Ignore)할 필요가 있음. CPU는 특정 인터럽트를 일시적으로 비활성화하는 기능을 제공. 이 기능으로 현재 처리 중인 작업의 중요도에 따라 다른 인터럽트의 수신 여부 제어.
    예를 들어, 매우 중요한 데이터를 처리하는 중에 덜 중요한 마우스 이동 인터럽트가 방해해서는 안되기 때문에 무시한다.

  • PintOS와의 연관성
    intr_disable()intr_enable() 함수를 보게 될 것. 이 함수들이 인터럽트를 비활성화하고 다시 활성화하는 역할. 스케줄러가 다음 실행할 프로세스를 고르기 위해 준비 큐(ready queue)를 조작하는 아주 짧은 순간동안 타이머 인터럽트에 의해 스케줄링이 또 다시 발생하는 것을 막기 위해 intr_disable()로 모든 인터럽트를 잠시 멈춤. 이런 동기화 기법은 운영체제 커널의 안전성을 위해 필수.


요약

  • 유저/커널 모드 : 시스템 보호를 위한 실행 환경 분리
  • 시스템 콜 : 유저 모드에서 커널 모드로 서비스를 요청하는 공식적인 방법
  • 인터럽트 : 시스템 콜을 포함한 모든 비동기 이벤트를 처리하고, 커널로 제어권을 넘기는 하드웨어/소프트웨어 메커니즘
profile
자라나라 실력 실력

0개의 댓글