[운영체제] 2. 컴퓨터시스템의 구조(4)

jyleever·2023년 1월 30일
0

운영체제

목록 보기
4/9
post-thumbnail

http://www.kocw.net/home/cview.do?lid=6de74734c21ccab4

CPU가 I/O를 요청하는 명령은 특권 명령으로 묶여있다. 사용자 프로그램이 직접 CPU를 가지고 있으면서 그 기계어를 실행할 수는 없다. 모든 I/O는 특권 명령이기 때문에 사용자 프로그램이 사용할 수 없다. 따라서 운영체제에게 요청해야 한다. -> 시스템 콜

시스템 콜 (System Call)

사용자 프로그램이 운영체제의 서비스를 받기 위해 커널 함수를 호출하는 것

사용자 프로그램이 실행되다가 디스크에서 뭘 읽어와야 한다면, 내가 CPU를 가지고 있을 때에는 특권 명령을 수행할 수 없기 때문에, 스스로 운영체제를 불러서 요청해야 한다.
시스템 콜을 하게 되면 사용자 프로그램의 위치에서 기계어가 실행되다가, 운영체제의 위치에 기계어가 실행되는 점프가 필요하다.
그런데 이 점프는 개별 프로그램에서 발생하는 점프와 다르게 프로그램의 가상 메모리를 가로질러서 점프를 하는 것. 그냥 점프하겠다고 해서 점프하는 게 아니라, 방법이 필요하다.
내가 기계어를 실행하다가, CPU를 운영체제에 넘기고 싶을 때에는 인터럽트 라인에 인터럽트가 들어와서, CPU가 다음 기계어를 실행하기에 앞서 인터럽트를 체크하여 인터럽트가 존재하면 자동으로 운영체제에게 넘어가는 방식이 있는데, 현재 이 방식에서는 IO를 하고 싶은데 운영체제만 할 수 있다면, 해당 실행 중인 사용자 프로그램이 스스토 인터럽트를 건다. 한 마디로 본인이 권한이 없는 기계어를 실행해야 할 때 발생하는 인터럽트를 이를 시스템 콜 이라고 한다.
내가 cpu를 운영체제에게 넘겨주기 위해 직접 program counter를 운영체제로 넘길 수 없기 때문에, 이 프로그램이 자신의 기계어를 통해 스스로 인터럽트 라인을 세팅한다. 그러면 CPU가 다음 기계어를 실행하기 전에 인터럽트가 들어왔으니까, 운영체제에게 CPU 제어권을 넘긴다.

여기서의 인터럽트는 프로그램, 즉 소프트웨어가 본인이 직접 할 수 없는 일을 운영체제에게 부탁하기 위해서 자신의 코드를 통해 인터럽트를 거는 방식으로 동작한다.
즉, 운영체제에게 부탁하기 위해 거는 인터럽트를 시스템 콜 이라고 한다.
이렇게 전반적으로 소프트웨어들이 인터럽트 라인을 세팅해서 인터럽트를 거는 것을 소프트웨어 인터럽트라고 한다.
하드웨어들이 인터럽트 라인을 세팅해 인터럽트를 거는 것을 하드웨어 인터럽트 라고 한다.

인터럽트

인터럽트

  • 인터럽트 당한 시점의 레지스터와 program counter를 save한 후 CPU의 제어를 인터럽트 처리 루틴에 넘긴다.

interrupt (넓은 의미)

  • interrupt (하드웨어 인터럽트) : 하드웨어가 발생시킨 인터럽트. 일반적인 의미의 인터럽트
  • Trap (소프트웨어 인터럽트) : 소프트웨어가 발생시킨 인터럽트, 아주 좁은 의미의 인터럽트. 스스로가 스스로에게 거는 것이기 때문.
    • Exception : 프로그램이 오류를 범한 경우
    • System Call : 프로그램이 커널 함수를 호출하는 경우

인터럽트 관련 용어

디스크 컨트롤러에 의한 인터럽트인지 타이머에 의한 인터럽트인지에 따라 처리해야 하는 인터럽트 처리 루틴이 다르다.

  • 인터럽트 벡터
    해당 인터럽트의 처리 루틴 주소를 가지고 있음
    일종의 주소에 대한 포인터 느낌
  • 인터럽트 처리 루틴(=interrupt service routine, 인터럽트 핸들러)
    해당 인터럽트를 처리하는 커널 함수
    해당 인터럽트에서 무슨 작업을 해야 하는지 적혀 있음


CPU와 DISK CONTROLLER
프로그램이 실행되다가, 디스크에서 어떤 파일을 읽어오는 작업이 필요하다면, 이 I/O 작업은 특권 명령이므로 본인의 기계어로 실행이 불가능해서 운영체제에게 시스템 콜
운영체제는 CPU에서 disk에서 file을 읽어오는 I/O작업을 하라고 disk controller에 부탁하면, disk controller는 이 disk의 head를 이동시켜 해당 file을 마그네틱에서 읽어서 본인 buffer에 들여놓는 작업을 시작.
이 I/O 작업은 오래 걸리기 때문에, 운영체제는 program counter을 다른 프로그램에 넘겨줘서, 다른 프로그램이 자신의 기계어를 실행할 수 있도록 함.
그렇다면, I/O작업을 요청한 프로그램은 요청한 FILE을 읽어오기까지 대기하다가, 모든 작업이 완료되었을 때 CPU에 아까 요청한 작업이 완료되었다고 인터럽트를 걸면, CPU 제어권이 운영체제에게 넘어가게 되고 운영체제는 자신의 기계어를 통해 읽어온 FILE을 메모리 위치에 프로그램이 사용할 수 있게 COPY해두고,
프로그램은 CPU를 얻어서 본인의 기계어를 실행할 수 있게 된다.

CPU와 키보드 controller
키보드에서 입력을 받아서 그 입력 결과를 가지고 프로그램을 실행하도록 프로그램을 만든다면,
프로그램이 실행되다가 키보드 입력이 들어오는 코드를 만나면 이는 i/o작업이기 때문에 운영체제에게 시스템 콜을 실행하고, 운영체제는 이 프로그램이 키보드 입력을 기다린다는 것을 큐에 줄 세운 후 다른 프로그램에게 CPU제어권을 넘김
그러다 키보드에서 원하는 input이 들어오면 키보드 컨트롤러가 CPU에 인터럽트를 걸고, CPU는 운영체제에게 넘어가서, 키보드 입력 드러온 내용을 키보드 입력을 요청한 프로그램에게 넘겨주고, 다음 부분을 처리할 수 있게 된다

Device Controller

I/O Device Controller

  • 해당 I/O 장치 유형을 관리하는 일종의 작은 CPU
  • 제어 정보를 위해 controll register, status register을 가짐
  • local buffer을 가짐 (일종의 data register)

I/O는 실제 device와 local buffer 사이에서 발생함
device controller는 I/O가 끝났을 경우 interrupt로 cpu에 그 사실을 알림
모든 I/O 장치에서 I/O를 전담하는 작은 CPU(하드웨어)
실제 I/O작업은 CPU가 직접하는 것이 아니라 DEVICE CONTROLLER에게 부탁해서 진행되고, 해당 작업이 끝나면 CPU에 인터럽트를 걸어 알려주는 역할

I/O Device Controller와 Device Driver

  • I/O Device는 I/O장치 내부에 미리 코딩된 프로그램이 들어있는데 이를 펌웨어라고 하고 이를 통해 동작하고 있다.

  • I/O Device Controller는 작은 CPU로서 하드웨어지만, Device Driver는 소프트웨어. 즉 CPU가 I/O Device Controller에게 작업을 부탁하는 방법이 적혀있는 것이 I/O Device Driver. 따라서 컴퓨터 내부에서 CPU가 실행하는 코드

  • Device Drviver에서 수행되는 코드는 펌웨어 라고 부른다.

인터럽트 정리

운영체제가 사용자 프로그램에 CPU를 넘겼을 때, 운영체제로 CPU가 다시 넘어오는 경우
몇 가지 경우가 있는데, 모든 경우가 공통적으로 인터럽트 라인을 세팅하는 경우에 한해서 CPU가 운영체제로 넘어온다.
또한, 인터럽트 라인을 누가 세팅하느냐에 따라 2가지(하드웨어, 소프트웨어)로 나누어진다.
운영체제는 인터럽트가 왜 걸렸는지, 디스크 컨트롤러(디스크 컨트롤러에게 시킨 작업이 종료돼서 알려주는 것)가 걸었는지 타이머가 걸어준 인터럽트인지에 따라 해야 할 일, 루틴이 다르므로 구분한다.
이 때 등장하는 것이 인터럽트 벡터. 해당 인터럽트의 처리 루틴 주소, 일종의 주소에 대한 포인터 느낌. 그리고 해당 인터럽트테서 무슨 작업을 해야 하는지 적혀있는 것이 인터럽트 처리 루틴, 인터럽트 핸들러 이다.

운영체제에게 CPU가 넘어가는 경우는 인터럽트가 걸렸을 때 넘어간다.
또한 사용자 프로그램이 CPU 제어권을 다른 프로그램 또는 운영체제에게 넘어가는 경우는 다음과 같이 2가지가 존재한다

    1. CPU 독점권을 막기 위해 존재하는 규정은 타이머 인터럽트, CPU를 어느 정도 사용했으면 타이머 인터럽트가 걸려서 해당 프로그램에서 CPU 제어권을 빼앗아 다른 프로그램에 넘겨주는 경우
    1. I/O 작업과 같이 오래 걸리는 작업을 위해 존재하는 인터럽트, 더 이상 CPU를 사용할 의지가 없는 상황에서는 어차피 내가 CPU를 가지고 있어도 다음 기계어를 사용할 수 없으므로 CPU 제어권을 내어놓는 경우도 존재

현재 운영체제는 인터럽트에 의해 구동된다.

운영체제도 하나의 프로그램이기 때문에 마음만 먹으면 CPU를 사용하는 것이 아니라, 인터럽트가 들어오는 경우에 한해서만 CPU를 사용한다.
CPU의 독점을 막기 위해서는 타이머 또는 I/O장치를 통해 인터럽트가 발생된다.

동기식 입출력과 비동기식 입출력

동기식 입출력 (Synchronous I/O)

  • I/O 요청 후 입출력 작업이 완료된 후에야 제어가 사용자 프로그램에 넘어감
  • 구현 방법1
    • I/O가 종료될 때까지 CPU를 낭비시킴
    • 매시점 하나의 I/O만 발생할 수 있음
  • 구현 방법2 (보통)
    • I/O가 완료될 때까지 해당 프로그램에게서 CPU를 빼앗음 -> 비동기식
    • I/O 처리를 기다리는 줄에 그 프로그램을 줄 세움 -> 동기식
    • 다른 프로그램에게 CPU를 줌
    • CPU가 또 다시 I/O 작업이 필요하다면 다시 다른 I/O 작업이 발생할 수 있음! I/O에게도 도움되고, CPU도 놀지 않는 방법

비동기식 입출력 (Asynchronous I/O)

  • I/O가 시작된 후 입출력 작업이 끝나기를 기다리지 않고, (I/O 작업의 결과를 보지 않고) 제어가 사용자 프로그램에 즉시 넘어감

결론적으로 두 경우 모두 I/O의 완료는 인터럽트로 알려줌

DMA (Direct Memory Access)

빠른 입출력 장치를 메모리에 가까운 속도로 처리하기 위해 사용
CPU의 중재 없이 Device Controller가 Device의 buffer storage의 내용을 메모리에 block 단위로 직접 전송
바이트 단위가 아니라 block 단위로 인터럽트를 발생시킴

  • 인터럽트 처리도 일종의 overhead, CPU 입장에서는 번거롭게 자주 발생하는 일은 아니지만 고속 I/O 장치는 인터럽트가 자주 발생하므로 CPU 입장에서 비효율적
  • 따라서 DMA Controller 을 걸어놓음 -> 인터럽트가 너무 자주 걸리는 것을 막기 위함!
    아주 작은 크기의 데이터가 local buffer에 들어와있다고 해서 그 때마다 controller가 직접 cpu에 인터럽트를 거는 것이 아니라, 어느 정도의 분량이 찼을 때 DMA가 직접 메모리에 copy하는 작업까지 하고, 그 작업이 끝나면 인터럽트를 하나 걸어서 필요로 하는 작업이 끝났음을 알려줌
    -> 인터럽트가 덜 빈번하게 발생함

  • 매번 cpu에 인터럽트를 걸어서 작업하는 것이 너무 비효율적이기 때문에, 메모리에 직접 접근할 수 있도록 하는 것

서로 다른 입출력 기계어

I/O를 수행하는 기계어는 두 가지가 있다.
I/O를 수행하는 special instruction에 의해 (I/O를 전담하는 기계어)
Memory Mapped I/O에 의해 (메모리 접근하는 기계어로 I/O 수행, 다만 메모리 주소가 I/O까지 연장된 것)

저장 장치 계층 구조


이러한 계층 구조에서, 실제 모든 데이터의 원본은 아래에 저장되어있고 필요할 때 위에서 가져다 사용

  • 위로 갈수록 용량은 작지만 빠르고 비쌈
    CPU가 접근 가능하며 Executable (직접 실행 가능함)
    휘발성, 컴퓨터의 전원이 종료되면 내용이 사라짐
  • 아래로 갈수록 용량은 크지만 느리고 저렴함
    I/O 컨트롤러에 요청해서 읽어들여야 함. Secondary
    비휘발성, 컴퓨터의 전원이 종료되어도 내용이 보존됨. 전원이 켜지면 메모리로 올라가서 실행될 수 있도록 구성되어있다.

캐싱은 재사용성이 있음. 하지만 용량의 제한으로 이미 사용되었다고 다 가지고 있진 않기 때문에 재사용성이 높은 것을 보관하고 있고 사용성이 낮은 것을 아래로 내려가게 하는 방법이 필요함.

0개의 댓글