1940을 수행 (940에 있는 데이터를 AC에 load), PC 1증가 (execute)
301번지에 저장된 명령어 5941을 IR에 저장 (fetch)
5941을 수행 (941에 있는 데이터를 AC에 있는 데이터와 ADD), PC 1증가 (execute)
302번지에 저장된 명령어 2941을 IR에 저장 (fetch)
2941을 수행 (941에 AC의 값 저장), PC 1증가 (execute)
5. Interrupt
processor의 fetch, execute은 매우 빠른 속도로 수행된다. 반대로 I/O모듈의 명령어 처리 속도는 상대적으로 매우 느리다.
예를들어 화면에 "hello"를 출력해라! 라는 명령을 CPU가 I/O모듈에게 내렸다고 할때, I/O모듈이 화면에 내용을 출력하고 일을 다 했다고 CPU에게 알릴 때까지 시간이 많이 소요된다. 즉 I/O모듈이 일을 하는동안 CPU는 쉬게 된다. 이런 idle상태는 자원의 낭비이다.
따라서 CPU가 I/O모듈에게 "화면에 출력해~"라고 명령을 하고나서 다음 해야할 일을 하고 있다가 I/O모듈이 일을 다 했다는 신호를 줄때 CPU가 현재 하던 일을 잠깐 멈추고 이전 일을 마무리하면 CPU는 항상 일하는 상태를 유지하게 된다.
이런식으로 normal sequence를 건너뛰면서 cpu활용을 최대로 할 수 있게 하는 방법을 interrupt라고 한다.
인터럽트 종류
프로그램 동작중에 오류가 발생했다면 interrupt가 발생되어 프로그램을 종료할 수 있다. (ex. 0으로 나누기등의 오류)
I/O처럼 느린 동작이 완료되었을 때 interrupt발생
timer를 설정해서 시간이 만료되었으면 interrupt가 발생돼서 다음 동작으로 넘어가도록 할 수 있다.
따라서 각 계층의 메모리를 섞어서 사용하게 되는데 내가 지금 필요한 데이터가 cache 혹은 main memory에 있다면 비교적 빠른 접근 속도로 데이터 접근이 가능할것이고 반대로 disk에 있다면 읽어오는데 많은 시간이 걸릴 것이다.
메모리에 대한 평균 접근 시간을 줄이기위해 locality(지역성)의 원리를 활용한다. 대게 앞으로 필요할 데이터는 지금 보고있는 데이터 근처에 있을 확률이 높다는 원리이다. 예를들면 우리가 int arr[10]의 index 1번 데이터를 참조하고 있다면 2번부터 9번을 그 뒤에 사용할 가능성이 매우 크다는 것이다.
지역성의 원리를 활용하여 cpu의 메모리 접근 시간을 줄이는 대표적인 방법으로 cache memory가 있다.
메모리에서 데이터를 일부 복사해서 cache에 올려둔다. 이때 올려두는 데이터 단위를 block이라고 한다. cache에 올려둘 데이터는 지역성을 활용하여 판단한다. 이전 예시 처럼 int arr[10]에서 현재 0번을 참조하고 있다면 0부터 10까지를 전부 cache에 올려두는 것이다. 왜냐하면 0번에 이어서 1부터 9번을 사용할 확률이 매우 높기 때문이다.
cpu가 cache에서 명령어를 읽어오는 단위를 word라고 한다.
cache를 여러 계층으로 구성하여 더 효율적 접근 시간을 구현할 수도 있다.
processor는 cache에 내가 찾는 데이터가 있는지 확인한다. cache에 존재한다면(hit) 바로 가져가서 사용한다. 반면 찾으려는 데이터가 cache에 없다면(miss) 메인메모리에서 그 데이터를 cache로 가져오고나서 processor는 접근할 수 있게 된다.
이런 방식으로 접근속도를 높이면서 더 큰 메모리를 사용할 수 있게 한다.
cache를 design하는데 고려해야하는 여러 요소가 있다.
메인메모리에서 cache로 복사해올 데이터 unit의 크기(block)
cache의 크기, cache의 수(L1, L2, L3)
cache에 새로운 block이 들어올때 누구와 교체할 것인가? 혹은 어느 slot에 저장할 것인가?
변경된 내용을 그때그때 저장(write)할 것인가? 아니면 block이 replace될 때 변경내용을 저장할 것인가?
cpu(processor)와 cache까지가 하나의 chip이다.
7. Programmed I/O
I/O로부터 제어권을 CPU가 가져와서 작업을 진행
예를들어 ABCD를 출력한다고 하자. A를 출력하는 동안 cpu는 B를 받을 준비가 되었는지 매번 status를 확인해야한다. 이런식으로 ABCD가 전부 출력될때까지 i/o에게 cpu가 계속 점유되어있게 된다.
정리하면 I/O module들이 cpu로부터 요청받은 동작을 수행하고 I/O status register에 완료, 미완료 상태를 저장해 둔다. processor는 주기적으로 그 상태들을 확인하고 instruction이 마무리 되었는지 결정하게 된다.
cpu가 입출력 명령을 요청
입출력 모듈이 명령을 수행
입출력 모듈의 상태 비트 저장
cpu가 주기적으로 상태비트 확인
performance가 낮음
8. Interrupt-Driven I/O
CPU의 대기를 극복하기위해 나온 방식이다.
I/O 모듈은 준비가 되면 인터럽트를 보내기 때문에 CPU가 반복적으로 장치를 확인할 필요가 없다.
CPU 입장
읽기 명령을 보낸다.
다음 일을 하나씩 처리한다. 일을 처리할때마다 인터럽트가 왔는지 확인한다.
만약 인터럽트가 있으면 context를 저장하고 인터럽트를 수행합니다.
I/O모듈 입장
읽기 명령을 CPU로 부터 받았음.
데이터를 장치로부터 읽어온다.
데이터를 다 읽어와서 준비가 되었을 때, 프로세서에게 인터럽트 신호를 보낸다.
프로세서로부터 데이터 요청 명령이 들어올 때까지 기다린다.
9. Direct Memory Access(DMA)
CPU가 읽을것인지 쓸것인지, 장치 주소, 메모리의 주소 정보, 얼마의 데이터를 보낼 것인지의 내용을 DMA에게 전달해준다.
CPU는 다음 작업을 진행한다.
DMA 제어기는 cpu로부터 받은 정보를 바탕으로 데이터를 i/o모듈, 메모리 사이에서 전달해준다.