운영체제가 하는 일

hongo·2024년 1월 9일
0

운영체제

목록 보기
1/10

운영체제

사용자와 하드웨어 사이를 중재하는 소프트웨어이다.

응용 프로그램은 워드프로세서, 크롬 등 사용자를 위한 프로그램이다. 응용 프로그램들은 하드웨어로부터 CPU, 메모리 공간 등 리소스를 얻어와야 하는데, 운영체제가 각 프로그램들이 얻는 리소스들을 관리한다.

커널

커널은 운영체제의 핵심 요소로, 컴퓨터가 켜지면 항상 메모리에서 상주하는 부분이다. (운영체제는 보통 커널과 같은 의미로 쓰인다고 한다. 넓은 의미의 운영체제는 사용자 인터페이스 기능까지 포함한 형태)

커널은 CPU, 메모리, 디스크, 입출력 장치의 자원을 관리한다. 하드웨어 자원들을 쉽게 관리하기 위해 추상화해서 제공한다.

물리적 자원  ->   추상화
* CPU     ->  Task
* Memory  ->  Page, Segment
* Disk    ->  File
* Network ->  Socket

이중모드(사용자 모드와 커널 모드)

CPU가 명령을 실행하는 모드는 두 가지가 있다.

  • 사용자 모드

    • 운영체제 서비스를 제공받을 수 없는 실행모드
    • = 커널 영역의 코드 실행 불가능
    • = 하드웨어 자원에 접근 불가능
    • 응용 프로그램이 기본적으로 사용자 모드에서 실행됨
  • 커널 모드

    • 운영체제 서비스를 제공받을 수 있는 실행모드
    • = 커널 영역의 코드 실행 가능
    • = 하드웨어 자원에 접근 가능
  • 왜 두 가지 모드로 나누었을까?

    • 두 가지 모드로 나눈 이유는, 사용자가 중요한 리소스에 접근하는 것을 막기 위해서라고 한다.

응용 프로그램은 사용자 모드에서 커널 모드로 전환하기 위해 시스템 콜(시스템 호출)을 사용한다. 시스템 콜은 운영체제 서비스를 제공받기 위한 요청으로, 소프트웨어 인터럽트라고 볼 수 있다. (인터럽트는 아래에서 서술)

인터럽트

인터럽트에 대해 알기 전, 입출력 장치같은 하드웨어가 어떻게 소프트웨어와 통신하는지 간략하게 알아보자.

각 하드웨어 장치는 장치 컨트롤러와 연결되어 있다. 장치 컨트롤러는 하드웨어의 규격을 맞추고, CPU와 하드웨어(입출력장치)간 전송률이 차이나는 것을 극복하기 위해 버퍼링등의 기능을 제공한다. 하드웨어로 접근하기 위한 인터페이스라고 보면 될 것 같다.

장치 컨트롤러가 하드웨어로 접근하기 위한 인터페이스용이라면, 장치 드라이버는 소프트웨어에 접근하기 위한 인터페이스이다. 장치 드라이버는 장치 컨트롤러가 컴퓨터 내부와 정보를 주고받을 수 있게하는 프로그램이다. (장치 컨트롤러는 하드웨어, 장치 드라이버는 소프트웨어)

각 장치 컨트롤러마다 장치 드라이버가 있으며, 장치 드라이버가 작업을 위한 값을 장치 컨트롤러의 레지스터에 넘겨준다. 장치 컨트롤러는 하드웨어에 접근해 해당 작업을 수행한 후 결과를 장치 드라이버에게 넘겨준다.

입출력 작업을 예시로 들면,

1. 장치 드라이버는 장치 컨트롤러의 적절한 레지스터에 값을 적재한다.
2. 장치 컨트롤러는 레지스터 내용을 검사하여 수행할 작업을 결정한다.(ex. 키보드에서 문자 읽기)
3. 장치 컨트롤러는 장치에서 로컬 버퍼로 데이터 전송을 시작한다.
4. 데이터 전송이 완료되면 장치 컨트롤러는 장치 드라이버에게 작업이 완료되었음을 알린다.
5. 장치 드라이버는 데이터 또는 데이터에 대한 포인터를 반환하여 운영체제의 다른 부분에 제어를 넘긴다.

장치 컨트롤러는 어떻게 장치 드라이버에게 작업이 완료되었음을 알리는 걸까? 바로 인터럽트라는 것을 사용한다.

인터럽트를 통해 운영체제와 하드웨어의 상호 작용을 할 수 있다.

각 인터럽트는 적절한 ISR(인터럽트 서비스 루틴)을 가지고 있고, ISR은 인터럽트를 처리하기 위한 코드 모음이라고 된다. (ISR은 메모리에 존재하며, 커널의 일부라고 볼 수 있다.)

인터럽트가 자주 발생하기에, 인터럽트들은 ISR을 가리키는 포인터에 빠르게 접근할 수 있는 테이블을 메모리에 저장하고 있다. 이 테이블을 인터럽트 벡터 테이블이라고 한다.

CPU와 장치 컨트롤러는 같은 버스를 사용해서 메모리에 접근한다. 때문에 CPU에서 수행되는 작업과 장치 컨트롤러가 수행한 작업은 병렬로 실행되며 메모리 사이클을 놓고 경쟁한다.

버스란?
컴퓨터 시스템 구성요소들을 상호 연결하는 중심 통로

그렇기에, 장치 컨트롤러가 처리한 결과를 장치 드라이버가 처리하기 위해선 기존에 CPU가 처리하고 있던 작업을 잠시 멈추고 끼어들 필요가 있다.

그림을 보며 인터럽트 과정을 알아보자.
장치 컨트롤러는 인터럽트 작업을 요청할 때 인터럽트 리퀘스트 라인이라는 것에 기록한다. CPU는 명령어를 하나 실행할 때마다 이 라인을 확인하며 인터럽트 요청이 왔는지를 체크한다.

인터럽트 요청이 왔다면, 인터럽트 벡터 테이블을 통해 적절한 ISR을 찾는다. ISR은 기존에 처리하고 있던 작업의 정보를 ProgramCounter에 저장하고, 인터럽트 작업을 수행한다. 작업을 완료하면 ISR은 이전에 처리하고 있던 작업으로 상태를 복구한다.

ISR(인터럽트 서비스 루틴) vs 인터럽트 핸들러
두 용어가 자주 나오는데, 수행하는 기능이 같은 것 같아 혼란스러웠다. 검색해보니 ISR은 주로 하드웨어와 관련된 용어로서 저수준에서 동작하는 코드를 나타내는 반면, 인터럽트 핸들러는 소프트웨어 및 운영체제의 관점에서 인터럽트를 처리하는 데 사용되는 더 포괄적인 용어라고 한다.
같은 의미로 사용해도 무방할 것 같다.

더욱 정교한 인터럽트 처리

똑똑한 개발자들은 더 정교한 인터럽트 처리를 위해 아래 세 가지 고민을 했다.

  1. CPU가 중요한 작업을 처리 중일 때, 인터럽트 처리를 미룰 수 있어야한다.
  2. 더 효율적으로 인터럽트 핸들러로 디스패치 할 수 없을까?
  3. 인터럽트에 우선순위를 부여할 수 없을까?

인터럽트 처리를 미루기 위해, 인터럽트는 미룰 수 있는 것미룰 수 없는 것 두 분류로 나눠졌다. 미룰 수 있는 인터럽트를 마스킹 가능(maskable) 이라고 하고, 미룰 수 없는 인터럽트를 마스크 불가능 인터럽트(nonmaskable interrupt)라고 부른다. 당연한 얘기지만, 마스크 불가능 인터럽트에는 메모리 오류와 같이 복구할 수 없는 크리티컬한 인터럽트가 속한다.

또한, 인터럽트 벡터의 주소 개수보다 많은 양의 장치가 존재하기에, 인터럽트 체인을 사용한다고 한다... 인터럽트 벡터의 각 원소는 인터럽트 핸들러 리스트의 헤드를 가리키고, 인터럽트가 발생하면 요청을 처리할 수 있는 핸들러가 발견될 때까지 하나씩 검사한다는데... 트리처럼 인터럽트 범위를 나누고 연결리스트형식으로 검사한다는 건가?

인터럽트 우선순위 레벨을 구현해 우선순위에 따라 인터럽트 처리 속도를 조정하게 했다. (자세한 알고리즘이나 구현방식은 아직 설명안해줌. 뒤에 챕터에서 더 말해줄듯)

인터럽트 리퀘스트 라인안에는 마스킹 가능 여부를 저장하는 레지스터와 우선순위 값이 쓰여져있다고 한다.

인터럽트 처리를 미루기 위해, 인터럽트는 미룰 수 있는 것미룰 수 없는 것 두 분류로 나눠졌다. 미룰 수 있는 인터럽트를 마스킹 가능 이라고 하고, 미룰 수 없는 인터럽트를 마스크 불가능 인터럽트라고 부른다.

당연한 얘기지만, 마스크 불가능 인터럽트에는 메모리 오류와 같이 복구할 수 없는 크리티컬한 인터럽트가 속한다.
그리고 CPU에 마스킹 가능한 인터럽트를 감지하는 핀과, 마스킹 불가능한 인터럽트를 감지하는 핀을 별도로 두어 구분해서 처리한다고 한다.

운영체제 3
각 인터럽트는 위 사진처럼 번호가 붙여져있는데, 번호가 작을수록 우선순위가 높은 인터럽트임을 의미한다고 한다.
(위 사진은 Intel 처리기 이벤트의 벡터 테이블인데 CPU 내부에서 발생하는 인터럽트들이고, CPU 외부에서 발생하는 PC 시점의 인터럽트들에 대한 테이블은 또 별도로 있음. CPU 내부 인터럽트들은 instruction과 동기화되어서 발생하기에 ynchronous interrupt라고 부르고, CPU 외부 인터럽트들은 asynchronous interrrupt라고 부른다고 함.)

또한, 인터럽트 벡터의 주소 개수보다 많은 양의 장치가 존재하기에, 인터럽트 체인을 사용한다고 한다... (인터럽트 벡터의 각 원소는 인터럽트 핸들러 리스트의 헤드를 가리키고, 인터럽트가 발생하면 요청을 처리할 수 있는 핸들러가 발견될 때까지 하나씩 검사한다는데... 트리처럼 인터럽트 범위를 나누고 연결리스트형식으로 검사한다는 건가?)

인터럽트 리퀘스트 라인(참고용)

운영체제 번역본에 다음과 같이 쓰여있다.
"""
CPU에는 2개의 인터럽트 요청 라인이 있다. 하나는 복구할 수 없는 메모리 오류와 같은 이벤트를 위해 예약된 마스크 불가능 인터럽트(nonmaskable interrupt)이다. 두 번째 인터럽트 라인은 마스킹 가능(maskable)이다.
"""

여기서 봤을 때는, CPU내부에 두 개의 인터럽트 요청 라인이 존재하고, 마스킹 여부에 따라 나뉜다는 의미인 것 같은데, 보편적으로 쓰이는 인터럽트 요청 라인은 CPU외부에 있는 하드웨어를 나타내는 것 같다. (CPU는 그냥 라인을 감지하는 PIN이 있는거고...)

PIC(Programmable Interuppt Controller)는 입출력 장치와 같은 하드웨어에서 발생한 인터럽트 신호들을 관리하고, CPU에게 요청하는 장치이다. 내부에 인터럽트 리퀘스트 라인(IRQ)을 여러개 가지고 있고, 각 IRQ에는 번호가 있다. 해당 번호는 특정 하드웨어와 연결된다. (ex. IRQ0-타이머, IRQ1-키보드)

커널은 프로세스인가?

참고

0개의 댓글