하드웨어적 동작에 대해 알아보자
CPU와 메모리 -> 컴퓨터
Disk, 키보드, 프린터 등 -> I/O device
Memory -> CPU의 작업 공간이다. CPU는 매 순간 (매 클럭 사이클 마다) 메모리에서 기계어를 하나씩 읽어 실행
I/O device들은 별개의 device들이다.
각각의 I/O device들은 device를 전담하는 작은 CPU같은 것들이 붙어 있고, 이는 Disk의 내부를 통제한다. 이를 disk controller라고 한다.
main CPU의 작업공간인 main memory가 있듯이 I/O device의 controller도 메모리가 필요하다. 이를 local buffer라고 한다.
CPU에 비해 Disk는 100만배정도 느리다. CPU는 매 클럭마다 메모리에서 instruction을 읽어 실행한다. CPU내에는 메모리보다 더 빠르면서 정보를 저장할 수 있는 작은 공간이 있으며 이를 register라 부르며 mode bit이라는 것이 있다. 이 mode bit은 CPU에서 실행되는 것이 운영체제 인지 사용자 프로그램인지 구분해준다.
interrupt line
CPU는 항상 메모리에 있는 instruction만 실행한다. instruction 하나가 실행되고 나면 다음 기계어의 주소값이 증가 하고 다음 사이클에서 실행하고.. 하는 것만 실행한다. 따라서 disk에서 무언갈 읽어와야 된다거나 요청을 했는데 일이 다 끝났다던지를 CPU가 알기 위해 intterupt line 이 있다.
프로그램 실행되다가 파일 읽어오기등의 작업이 있을 수 있다. 입력을 받거나, 출력, 읽어오는 등의 작업은 I/O device에 접근하는 작업이다. 하지만 CPU는 memory에서만 읽어오는 instruction을 실행하므로 I/O device에 접근하는 작업은 다른 누군가에게 시킨다. 그럼 컨트롤러의 지시를 받아 disk에서 받고 local buffer에 저장한다. 이는 되게 오래 걸리며 CPU가 그동안 놀 수 없으므로 disk에서 받아오는 동안 memory에서 다음 instruction을 받아와 실행한다. 하지만 읽은 값이 무엇인가에 따라 다음 작업이 결정되는 작업을 만나게 된다면 keyboard controller에 말해서 결과값을 알려달라하고 본인이 할 수 있는 일을 계속 실행한다. CPU는 빠른 속도를 이용해서 계속 일을 해야하므로 기다려야하는 상황이 온다면 다른 프로그램을 실행하고 있는다. 따라서 사용자 입장에서 보면 interactive하다.
한가지 문제점은 만약 이 프로그램이 무한루프를 돌아 계속 CPU를 쓰면 (종료 되지도 않고 I/O device를 쓰지도 않음) time sharing을 구현할 수가 없다. 따라서 timer라는 하드웨어를 둬서 특정 프로그램이 CPU를 독점하는 것을 막는다. timer에 시간을 할당해 넘기고 할당된 시간을 넘기면 timer가 CPU에 interrupt를 걸어 시간이 지남을 알리고 CPU는 하던 일을 멈추고 CPU의 제어권이 사용자 프로그램에서 운영체제로 넘어가게 된다.
I/O 작업을 할 때는 스스로 운영체제에게 CPU를 넘겨주고 해당하는 작업을 I/O controller에게 시킨다. 하지만 이 작업이 오래 걸리므로 그동안 다른 프로그램에게 CPU를 넘겨준다. I/O 작업이 끝나고 데이터가 local buffer에 저장하고 controller가 CPU에 interrupt를 건다. 그럼 CPU 제어권이 자동으로 운영체제로 넘어간다. 운영체제는 interrupt를 확인하고 local buffer의 데이터를 필요한 프로그램에 복사해주고 실행되다가 interrupt 당안 프로그램에게 CPU를 주고 시간이 끝나면 I/O 작업이 끝난 프로그램에게 CPU를 준다.
CPU의 제어권이 바뀔 때 마다 바뀐다.
사용자 프로그램의 잘못된 수행으로 다른 프로그램 및 운영체제에 피해가 가지 않도록 하기 위한 보호 장치이다.
CPU는 memory와 local buffer에 접근 가능, device controller는 local buffer에만 접근 가능 => 문제점은 너무 많은 interrupt가 발생해 빠른 장치가 효율적으로 작동하지 못한다. 따라서 DMA(direct memory access) controller가 있음 이는 직접 메모리에 접근할 수 있는 장치이다. 메모리를 CPU도 접근할 수 있고 DMA도 접근할 수 있다. 특정 메모리 영역을 동시에 접근할 때는 문제(일관성)가 생길 수 있기 때문에 이를 memory controller가 중재한다. I/O 장치가 너무 많이 interrup를 걸어서 CPU가 계속 local buffer의 데이터를 복사해오는것은 오버헤드가 크다. 따라서 local buffer의 데이터가 모두 적재되면 DMA가 memory로 복사해주고 CPU에 데이터가 다 올라왔다고 interrupt를 건다.
device driver : OS 코드 중 각 장치별 처리루틴 -> software (디스크의 데이터를 읽고 하는게 아님)
device controller : 각 장치를 통제하는 일종의 작은 CPU -> hardware
모든 입출력 명령은 즉, I/O 장치에 대한 접근은 운영체제를 통해서만 할 수 있다.
따라서 사용자 프로그램은 운영체제에게 I/O 요청을 해야하는데 이를 system call 이라고 한다.
사용자 프로그램을 실행하다보면 함수를 호출해야할 때가 있다. 프로그램이 main함수를 실행하면 main에 대한 instruction을 실행하고 그 안에서 다른 함수를 실행하면 순차적으로 실행하다가 instruction을 jump하게 된다. 즉, 내 프로그램 안에서 함수를 호출하는 것은 memory안에서 주소를 바꾸는 것인데, I/O요청을 하기 위해 운영체제의 함수를 호출하는 것은 주소를 바꾸는 것만으로는 안된다. system call을 해야한다. 왜냐하면 나는 아직 사용자 프로그램이기 때문이다. 따라서 프로그램 내에서 CPU에 interrupt를 걸어 CPU의 제어권이 운영체제로 넘어간다. 이를 소프트웨어 interrupt라고 하며 trap이라고 한다.
사용자 프로그램이 I/O를 하는 방법
사용자 프로그램 내에서 I/O 요청이 있는 경우엔 운영체제에게 trap을 사용해 CPU의 제어권을 운영체제로 넘긴다. 운영체제는 올바른 I/O 요청인지 확인하고 이를 수행한다. 그럼 I/O controller가 일을 수행하고 이게 오래걸리기 때문에 CPU는 다른 일을 하고 있는다. I/O controller가 일이 끝나면 CPU에게 interrupt를 거는데 이때 interrupt는 하드웨어적 interrupt이므로 trap이 아니다. I/O 완료시 제어권을 system call 다음 명령으로 옮긴다.
따라서 I/O를 하기 위해서 두가지 interrupt가 사용된다. 일을 요청할 땐 software interrupt, I/O가 끝났을 땐 hardware interrupt가 필요하다.
일반적인 의미는 하드웨어가 거는 interrupt이다.
interrupt 당한 시점의 레지스터와 program counter를 save한 후 CPU의 제어를 인터럽트 처리 루틴에 넘긴다.
Trap
인터럽트 벡터 : 해당 인터럽트의 처리 루틴 주소를 가지고 있음(인터럽트가 왔을 때 어떤 코드로 가야하는지 표시)
인터럽트 처리 루틴 : 해당 인터럽트를 처리하는 커널 함수(인터럽트 마다 처리해야할 실제 코드)
현대의 운영체제는 인터럽트에 의해 구동된다.
사용자 프로그램이 운영체제의 서비스를 받기 위해 커널함수를 호출하는 것이다.
Operating System Concepts 10th
KOCW 강의 - [운영체제] 이화여자대학교 반효경 교수