06-1 확인문제 3번 | ①SRAM ②DRAM ③DRAM ④SRAM
06-3 확인문제 1번 | ①레지스터 ②캐시 메모리 ③메모리 ④보조기억장치
07-1 RAID의 정의와 종류를 간단히 정리하기 | 완료
RAM은 우리가 흔히 말하는 '메모리'로 실행할 프로그램의 명령어와 데이터가 저장된다. 여기서 중요한 점은 RAM은 전원을 끄면 저장된 내용이 사라지는 휘발성 저장 장치이다.
반면 비휘발성 저장 장치인 보조기억장치는 전원을 꺼도 내용이 유지되지만, CPU가 직접 접근하지 못한다는 단점이 있다.
그래서 일반적으로 보조기억장치에는 '보관할 대상'을 저장하고, RAM에는 '실행할 대상'을 저장한다. 만약 CPU가 실행하고 싶은 프로그램이 보조기억장치에 있다면 이를 RAM으로 복사하여 저장한 뒤 실행하게 된다.
여기서 만약 RAM용량이 크다면 비교적 작은 용량에 RAM보다 많은 프로그램들을 동시에 빠르게 실행하는 데 유리하다.
DRAM은 Dynamic RAM의 준말로, 저장된 데이터가 동적으로 사라지는 RAM을 의미한다.
즉, DRAM은 시간이 지나면 저장된 데이터가 점차 사라지는 RAM이다. 그렇기에 DRAM은 데이터의 소멸을 막기 위해 일정 주기로 데이터를 재활성화(다시 저장)해야 한다.
그럼에도 DRAM은 일반적으로 가장 많이 쓰이는데, 그 이유는 소비 전력이 비교적 낮고, 저렴하고, 집적도가 높기 때문에 대용량으로 설계하기가 용이하기 때문이다.
SRAM은 Static RAM의 준말로, 저장된 데이터가 변하지 않는 RAM을 의미한다. DRAM과 달리 SRAM은 시간이 지나도 저장된 데이터가 사라지지 않는다. 당연하게 주기적으로 데이터를 재활성화할 필요도 없다. 그리고 일반적으로 SRAM은 DRAM보다 속도도 더 빠르다.
하지만 이러한 장점에도 SRAM을 메모리로 잘 사용하지 않는 이유는 SRAM이 DRAM보다 집적도가 낮고, 소비 전력도 크며, 가격도 비싸기 때문이다. 그래서 SRAM은 메모리가 아닌 '대용량으로 만들어질 필요는 없지만 속도가 빨라야 하는 저장 장치', 캐시 메모리에서 사용된다.
SDRAM(Synchronous Dynamic RAM)은 클럭 신호와 동기화된, 발전된 형태의 DRAM이다. '클럭 신호와 동기화되었다'는 말은 클럭 타이밍에 맞춰 CPU와 정보를 주고받을 수 있음을 의미한다.
즉, SDRAM은 클럭에 맞춰 동작하며 클럭마다 CPU와 정보를 주고받을 수 있는 DRAM이다.
DDR SDRAM은 최근 가장 흔히 사용되는 RAM으로, 대역폭을 넓혀 속도를 빠르게 만든 SDRAM이다.
대역폭은 흔히 자동차 도로에 비유되곤 하는데, 한 클럭에 하나씩 정보를 주고받을 수 있는 SDRAM과 비교했을 때 DDR SDRAM은 너비가 두 배인 도로와 같다. 즉, 한 클럭에 한 번씩 CPU와 데이터를 주고받을 수 있는 SDRAM에 비해 DDR SDRAM은 두 배의 대역폭으로 한 클럭당 두 번씩 CPU와 데이터를 주고받을 수 있다. 당연하게도 DDR SDRAM의 전송 속도가 두 배가량 빠르다.
주소에는 메모리가 사용하는 물리 주소가 있고, CPU와 실행 중인 프로그램이 사용하는 논리주소가 있다.
메모리가 사용하는 물리 주소는 말 그대로 정보가 실제로 저장된 하드웨어상의 주소를 의미한다. 반면 CPU와 실행 중인 프로그램이 사용하는 논리 주소는 실행 중인 프로그램 각각에게 부여된 0번지부터 시작되는 주소를 의미한다.
즉, 실행 중인 모든 프로그램은 모두 물리 주소가 아닌 0번지부터 시작하는 자신만을 위한 주소인 논리 주소를 가지고 있다. 예를 들어, '10번지'라는 주소는 메모장에도, 게임에도, 인터넷 브라우저에도 논리 주소로써 존재할 수 있다.
그런데 CPU와 메모리가 상호작용하려면 논리 주소와 물리 주소 간의 변환이 이루어져야 하는데, 이것을 수행하는 것이 바로 CPU와 주소 버스 사이에 위치한 메모리 관리 장치(MMU)이다.
메모리 관리 장치(MMU)는 CPU가 발생시킨 논리 주소에 베이스 레지스터 값을 더하여 논리 주소를 물리 주소로 변환시킨다. 예를 들어 현재 베이스 레지스터에 15000이 저장되어 있고 CPU가 발생시킨 논리 주소가 100번지라면 이 논리 주소는 15100번지로 변환된다.
게임 프로그램의 물리 주소가 1000번지부터 1999번지, 인터넷 브라우저 프로그램의 물리 주소가 2000번지부터 2999번지라고 할 때, 게임 프로그램 명령어 중 '(논리 주소) 1500번지에 숫자 100을 저장하라'와 같은 명령어가 있다면 어떻게 될까?
위와 같은 명령어는 프로그램의 논리 주소 영역을 벗어났기 때문에 실행되어서는 안된다. 이렇게 다른 프로그램의 영역을 침범할 수 있는 명령어는 위험하기 때문에 논리 주소 범위를 벗어나는 명령어 실행을 방지하고 실행 중인 프로그램이 다른 프로그램에 영향을 받지 않도록 보호할 방법이 필요한데, 그것을 한계 레지스터가 담당한다.
베이스 레지스터가 실행 중인 프로그램의 가장 작은 물리 주소를 저장한다면, 한계 레지스터는 논리 주소의 최대 크기를 저장한다.
CPU는 메모리에 접근하기 전에 접근하고자 하는 논리 주소가 한계 레지스터보다 작은지를 항상 검사한다. 만약 CPU가 한계 레지스터보다 높은 논리 주소에 접근하려고 하면 인터럽트(트랩)를 발생시켜 실행을 중단한다.
이러한 방식으로 실행 중인 프로그램의 독립적인 실행 공간을 확보하고 하나의 프로그램이 다른 프로그램을 침범하지 못하게 보호할 수 있다.
모든 사용자들은 빠르면서 용량이 큰 저장 장치를 원한다. 하지만 그 둘은 양립하기 어렵다.
저장 장치는 CPU와 가까울수록 빠르고, 멀수록 느리다. 또한 속도가 빠른 저장 장치는 저장 용량이 작고, 비싸다. 즉, 낮은 가격대의 대용량 저장 장치를 원한다면 느린 속도는 감수해야 하고, 빠른 메모리를 원한다면 작은 용량과 비싼 가격을 감수해야 한다.
그래서 일반적으로 컴퓨터는 다양한 저장 장치를 모두 사용한다.
CPU 연산 속도가 아무리 빨라도 메모리에 접근하는 속도가 그에 따라가지 못한다면 CPU의 발전은 아무 소용이 없게 된다. 그래서 등장한 저장 장치가 캐시 메모리인데, 캐시 메모리는 CPU와 메모리 사이에 위치하고, 레지스터보다 용량이 크고 메모리보다 빠른 SRAM 기반의 저장 장치이다.
CPU가 매번 메모리에 왔다 갔다 하는 건 시간이 오래 걸리니, 메모리에서 CPU가 사용할 일부 데이터를 미리 캐시 메모리로 가지고 와서 활용하는 것이다.
컴퓨터 내부에는 여러 개의 캐시 메모리가 있는데, 이것들은 CPU(코어)와 가까운 순서대로 계층을 구성한다. 코어와 가장 가까운 캐시 메모리를 L1 캐시, 그다음 가까운 캐시 메모리를 L2 캐시, 그 다음 가까운 캐시 메모리를 L3 캐시라고 부른다. 일반적으로 L1 캐시와 L2 캐시는 코어 내부에, L3 캐시는 코어 외부에 위치해 있다.
CPU가 메모리 내에 데이터가 필요하다고 판단하면 우선 L1 캐시에 해당 데이터가 있는지를 알아보고, 없다면 L2, L3 캐시 순으로 데이터를 검색한다.
멀티 코어 프로세서에서 L1 - L2 - L3 캐시는 일반적으로 다음과 같이 구현되는데, L1 캐시와 L2 캐시는 코어마다 고유한 캐시 메모리로 할당되고, L3 캐시는 여러 코어가 공유하는 형태로 사용된다.
코어와 가장 가까운 L1 캐시는 조금이라도 접근 속도를 빠르게 만들기 위해 명령어만을 저장하는 L1 캐시인 L1I 캐시와 데이터만을 저장하는 L1 캐시인 L1D 캐시로 분리하는 경우도 있는데, 이를 분리형 캐시라고 한다.
보조기억장치는 전원이 꺼져도 기억할 대상을 저장하고, 메모리는 실행 중인 대상을 저장한다면 캐시 메모리는 CPU가 사용할 법한 대상을 예측하여 저장한다.
이때 자주 사용될 것으로 예측한 데이터가 실제로 들어맞아 캐시 메모리 내 데이터가 CPU에서 활용될 경우를 캐시 히트라고 한다. 반대로 자주 사용될 것으로 예측하여 캐시 메모리에 저장했지만, 예측이 틀려 메모리에서 필요한 데이터를 직접 가져와야 하는 경우를 캐시 미스라고 한다.
캐시가 히트되는 비율을 캐시 적중률이라 하는데, 일반적으로 컴퓨터의 캐시 적중률은 약 85~95% 이상이다. 이 캐시 메모리의 이점을 제대로 활용하려면 CPU가 사용할 법한 데이터를 제대로 예측해서 캐시 적중률을 높여야 한다.
캐시 메모리는 한 가지 원칙에 따라 메모리로부터 가져올 데이터를 결정하는데, 그것이 바로 참조 지역성의 원리이다. 참조 지역성의 원리는 CPU가 메모리에 접근할 때의 주된 경향인 'CPU가 최근에 접근했던 메모리 공간에 다시 접근하려는 경향', 시간 지역성과 '접근한 메모리 공간 근처를 접근하려는 경향'인 공간 지역성을 바탕으로 만들어진 원리이다.
보조기억장치에는 다양한 종류가 있다. 그중 가장 대중적인 보조기억장치는 하드 디스크와 플래시 메모리다. 플래시 메모리는 우리가 흔히 사용하는 USB 메모리, SD 카드, SSD와 같은 저장 장치를 말한다.
하드 디스크는 자기적인 방식으로 데이터를 저장하는 보조기억장치로, 자기 디스크(magnetic disk)의 일종으로 지칭되기도 한다.
하드 디스크에 내부를 살펴보겠다.
하드 디스크에서 실질적으로 데이터가 저장되는 곳은 동그란 원판으로, 이를 플래터라고 한다. 플래터는 자기 물질로 덮여 있어 수많은 N극과 S극을 저장한다. N극과 S극은 0과 1의 역할을 수행한다.
또, 구성 요소 중 플래터를 회전시키는 것을 스핀들이라고 하는데, 스핀들이 플래터를 돌리는 속도는 분당 회전수를 나타내는 RPM이라는 단위로 표현한다.
플래터를 대상으로 데이터를 읽고 쓰는 구성 요소는 헤드이다. 헤드는 플래터 위에서 미세하게 떠 있는 채로 데이터를 읽고 쓰는, 마치 바늘같이 생긴 부품이다. 그리고 헤드는 디스크 암에 부착되어 있는데, 디스크 암은 헤드를 원하는 위치로 이동시키는 역할을 한다.
하드 디스크는 많은 양의 데이터를 저장해야 하기 때문에 일반적으로 여러 겹의 플래터로 이루어져 있고 플래터 양면을 모두 사용할 수 있다. 양면 플래터를 사용하면 위아래로 플래터당 두 개의 헤드가 사용된다. 이때 일반적으로 모든 헤드는 디스크 암에 부착되어 다같이 이동한다.
플래터에 데이터를 저장하는 방법은 다음과 같다. 플래터는 트랙과 섹터라는 단위로 데이터를 저장하는데, 플래터를 여러 동심원으로 나누었을 때 그중 하나의 원을 트랙이라고 부른다. 그리고 트랙은 피자처럼 여러 조각으로 나뉘는데, 그 한 조각을 섹터라고 부른다. 섹터는 하드 디스크의 가장 작은 전송 단위로, 하나의 섹터는 일반적으로 512바이트 정도의 크기를 가지고 있지만, 정확한 크기는 하드 디스크에 따라 차이가 있다. 하나 이상의 섹터를 묶어 블록이라고 표현하기도 한다.
이 때 여러 겹의 플래터 상에서 같은 트랙이 위치한 곳을 모아 연결한 논리적 단위를 실린더라고 한다. 연속된 정보는 보통 한 실린더에 기록되는데, 가령 두 개의 플래터를 사용하는 하드 디스크에서 네 개 섹터에 걸쳐 데이터를 저장할 때는 첫 번째 플래터 윗면, 뒷면과 두 번째 플래터 윗면, 뒷면에 데이터를 저장한다. 연속된 정보를 하나의 실린더에 기록하는 이유는 디스크 암을 움직이지 않고도 바로 데이터에 접근할 수 있기 때문이다.
하드 디스크가 저장된 데이터에 접근하는 시간은 크게 탐색 시간, 회전 지연, 전송 시간으로 나뉜다.
위 시간들은 별것 아닌 것 같아도 성능에 큰 영향을 끼치는 시간이다.
탐색 시간과 회전 지연을 단축시키기 위해서는 플래터를 빨리 돌려 RPM을 높이는 것도 중요하지만, 접근하려는 데이터가 플래터 혹은 헤드를 조금만 옮겨도 접근할 수 있는 곳에 위치해 있는 것도 중요하다.
우리가 흔히 사용하는 USB 메모리, SD 카드, SSD가 모두 플래시 메모리 기반의 보조기억장치이다.
플래시 메모리는 전기적으로 데이터를 읽고 쓸 수 있는 반도체 기반의 저장 장치이다.
사실 플래시 메모리는 보조기억장치 뿐만아니라 주기억장치 중 하나인 ROM과 우리가 일상적으로 접하는 거의 모든 전자 제품 안에 플래시 메모리가 내장되어 있다고 봐도 무방하다.
플래시 메모리에는 셀이라는 단위가 있는데, 플래시 메모리에서 데이터를 저장하는 가장 작은 단위이다. 이 셀이 모여 MB, GB, TB 용량을 갖는 저장 장치가 되는 것이다.
이 때 하나의 셀에 몇 비트를 저장할 수 있느냐에 따라 플래시 메모리 종류가 나뉘는데,
한 셀에 1비트를 저장할 수 있는 플래시 메모리를 SLC 타입, 한 셀에 2비트를 저장할 수 있는 플래시 메모리를 MLC 타입, 한 셀에 3비트를 저장할 수 있는 플래시 메모리를 TLC 타입이라고 한다.
이는 플래시 메모리의 수명, 속도, 가격에 큰 영향을 끼친다.
사람 한 명을 비트, 셀을 집에 비유하자면, SLC 타입은 한 집에 한 명 사는 구조로 한 셀의 두 개의 정보를 표현할 수 있다. ( 0과 1 )
홀로 거주하는 집에 제약없이 출입이 가능하듯 SLC 타입은 MLC나 TLC 타입에 비해 비트의 빠른 입출력이 가능하다. 또한, 수명도 MLC나 TLC 타입보다 길어서 수만에서 수십만 번 가까이 데이터를 쓰고 지우고를 반복할 수 있다.
하지만 SLC 타입은 용량 대비 가격이 높다. 그렇기에 보통 기업에서 데이터를 읽고 쓰기가 매우 많이 반복되며 고성능의 빠른 저장 장치가 필요한 경우에 SLC 타입을 사용한다.
MLC 타입은 한 집에 두명이 사는 구조로 한 셀의 네 개의 정보를 표현할 수 있는데( 00, 01, 10, 11 ),
일반적으로 SLC 타입보다 속도와 수명은 떨어지지만, 한 셀에 두 비트씩 저장할 수 있다는 점에서 MLC 타입은 SLC 타입보다 대용화하기 유리하다. 또한 SLC 타입보다 용량 대비 가격이 저렴하여, 시중에서 사용되는 많은 플래시 메모리 저장 장치들이 MLC 타입으로 만들어진다.
TLC 타입은 한 집에 세명이 살아 한 셀로 여덟 개의 정보를 표현할 수 있다. ( 000, 001, 010, 100, 110, 101, 011, 111 ) 그렇기에 대용화하기 유리하고, SLC나 MLC 타입보다 수명과 속도가 떨어지지만 용량 대비 가격도 저렴하다.
이제 셀보다 더 큰 단위를 알아보면, 셀들이 모여 만들어진 단위를 페이지, 그리고 페이지가 모여 만들어진 단위를 블록, 블록이 모여 플레인, 플레인이 모여 다이가 된다.
플래시 메모리의 가장 큰 특징 중 하나가 읽기/쓰기 단위와 삭제 단위가 다르다는 것인데, 읽기와 쓰기는 페이지 단위로 이루어지고 삭제는 그보다 큰 블록 단위로 이루어진다.
이때 페이지는 세 개의 상태를 가질 수 있다. Free 상태는 어떠한 데이터도 저장하고 있지 않아 새로운 데이터를 저장할 수 있는 상태를 의미하고, Valid 상태는 이미 유효한 데이터를 저장하고 있는 상태를 의미한다. 그리고 Invalid 상태는 쓰레기 값이라 부르는 유효하지 않은 데이터를 저장하고 있는 상태를 의미한다.
여기서 플래시 메모리가 작동하는 것을 본다면 플래시 메모리는 하드 디스크와 달리 덮어쓰기가 불가능하여 Valid 상태인 페이지에는 새 데이터를 저장할 수 없다. 그렇기 때문에 기존에 저장된 A라는 데이터를 수정하고 싶다면, 저장되어 있던 A라는 데이터를 유효하지 않은 쓰레기값, Invalid 상태로 만들고, Free 상태의 공간에 새로운 데이터를 저장한다.
그런데 이렇게 된다면 쓰레기값을 저장하고 있는 공간은 사용하지 않을 공간인데도 불구하고 용량을 차지하고 있다. 하지만 앞서 말했듯 플래시 메모리에서 삭제는 블록 단위로 수행되기 때문에 쓰레기값인 A만 지울 수도 없다.
그래서 최근 SSD를 비롯한 플래시 메모리는 이런 쓰레기값을 정리하기 위해 가비지 컬렉션 기능을 제공한다. 가비지 컬렉션은 유효한 페이지들만을 새로운 블록으로 복사한 뒤, 기존의 블록을 삭제하는 기능이다.
RAID는 주로 하드 디스크와 SSD를 사용하는 기술로, 데이터의 안전성 혹은 높은 성능을 위해
여러 개의 물리적 보조기억장치를 마치 하나의 논리적 보조기억장치처럼 사용하는 기술을 의미한다.
RAID를 구성하는 방법은 여러 가지가 있는데, RAID 레벨이라 표현한다. RAID 레벨에는 대표적으로 RAID 0, RAID 1, RAID 4, RAID 5, RAID 6이 있고, 그로부터 파생된 RAID 10, RAID 50이 있다.
우선 RAID 0은 여러 개의 보조기억장치에 데이터를 단순히 나누어 저장하는 구성 방식이다.
즉, 저장되는 데이터가 하드 디스크 개수만큼 나뉘어 저장되는 것인데, 이때 마치 줄무늬처럼 분산되어 저장된 데이터를 스트라입이라 하고, 분산하여 저장하는 것을 스트라이핑이라 한다.
다시 말해 데이터가 분산되어 저장, 스트라이핑되면 저장된 데이터를 읽고 쓰는 속도가 빨라진다. 하나의 대용량 저장 장치를 이용했더라면 여러 번에 걸쳐 읽고 썼을 데이터를 동시에 읽고 쓸 수 있기 때문이다. 그렇기에 4TB 저장 장치 한 개를 읽고 쓰는 속도보다 RAID 0으로 구성된 1TB 저장 장치 네 개의 속도가 이론상 네 배가량 빠르다.
하지만 RAID 0에 단점은 저장된 정보가 안전하지 않다는 것이다. RAID 0으로 구성된 하드 디스크 중 하나에 문제가 생긴다면 다른 모든 하드 디스크의 정보를 읽는 데 문제가 발생하게 된다.
RAID 1은 RAID 0에 단점을 해결하기 위해 나온 방식으로 복사본을 만드는 방식이다. 그래서 미러링이라고도 불린다.
RAID 1은 RAID 0처럼 데이터 스트라이핑이 사용되긴 하지만, 원본을 백업해놓은 복사본이 저장되어있어서, 쓰기 속도는 RAID 0보다 느리다. 반면 하나에 문제가 발생해도 잃어버린 정보를 금방 되찾을 수 있기 때문에 복구가 매우 간단하다는 장점이 있다.
하지만 RAID 1은 복사본이 만들어지는 용량만큼 사용자가 용량을 사용하지 못하기 때문에 하드 디스크 개수가 한정되었을 때 사용 가능한 용량이 적어지는 단점이 있다. 결국 많은 양의 하드 디스크가 필요하게 되고, 비용이 증가한다는 단점으로도 이어진다.
RAID 4는 RAID 1처럼 완전한 복사본을 만드는 대신 오류를 검출하고 복구하기 위한 정보를 저장한 장치를 둔다. 이때 '오류를 검출하고 복구하기 위한 정보'를 패리티 비트라고 한다. 패리티 비트는 본래 오류 검출용 정보지만, RAID에서는 오류 복구도 가능하다.
RAID 4는 패리티를 저장한 장치를 이용해 다른 장치들의 오류를 검출하고, 오류가 있다면 복구하는데, 이로써 RAID 4는 RAID 1보다 적은 하드 디스크로도 데이터를 안전하게 보관할 수 있다.
RAID 4에서는 어떤 새로운 데이터가 저장될 때마다 패리티를 저장하는 디스크에도 데이터를 쓰게 되므로 패리티를 저장하는 장치에 병목 현상이 발생한다는 문제가 있었다.
따라서 RAID 5는 패리티 정보를 분산하여 저장하는 방식으로 병목 현상을 해소한다.
RAID 6의 구성은 RAID 5와 같으나, 오류를 검출하고 복구할 수 있는 수단인 패리티를 두 개로 늘리는 방식으로 RAID 4나 RAID 5보다 안전한 구성이라 볼 수 있다.
다만 새로운 정보를 저장할 때마다 함께 저장할 패리티가 두 개이므로, 쓰기 속도는 RAID 5보다 느리다. 따라서 RAID 6은 데이터 저장 속도를 조금 희생하더라도 데이터를 안전하게 보관하고 싶을 때 사용하는 방식이다.
우선 입출력 장치는 앞서 학습한 CPU, 메모리보다 다루기가 더 까다롭다. 그 이유는 두 가지가 있다,
첫째, 입출력 장치는 종류가 너무나 많기 때문이다.
장치가 다양하면 자연스럽게 장치마다 속도, 데이터 정송 형식 등도 다양하다. 따라서 다양한 입출력장치와 정보를 주고받는 방식을 규격화하기가 어렵다.
둘째, 일반적으로 CPU와 메모리의 데이터 전송률은 높지만 입출력장치의 데이터 전송률은 낮다
여기서 전송률이란 데이터를 얼마나 빨리 교환할 수 있는지를 나타내는 지표인데, CPU와 메모리처럼 전송률이 높은 장치는 1초에도 수많은 데이터를 주고받을 수 있지만, 키보드나 마우스 같이 상대적으로 전송률이 낮은 장치는 같은 시간 동안 데이터를 조금씩만 주고받을 수 있다.
이렇듯 전송률의 차이는 CPU와 메모리, 입출력장치 간의 통신을 어렵게 한다.
이와 같은 이유들로 입출력장치는 컴퓨터에 직접 연결되지 않고 장치 컨트롤러라는 하드웨어를 통해 연결된다. 장치 컨트롤러는 입출력 제어기, 입출력 모듈 등으로 다양하게 불리기도 한다.
여기서 장치 컨트롤러의 역할을 더 알아보자면
'CPU와 입출력장치 간의 통신 중개', '오류 검출', '데이터 버퍼링'등이 있다.
입출력장치 종류가 많아 정보 규격화가 어려웠던 문제를 장치 컨트롤러가 일종의 번역가 역할을 함으로써 문제를 해결하고, 그 과정에서 입출력장치에 문제는 없는지 오류도 검출한다.
또한 버퍼링이란 전송률이 높은 장치와 낮은 장치 사이에 주고받는 데이터를 버퍼라는 임시 저장 공간에 저장하여 전송률을 비슷하게 맞추는 방법인데, 장치 컨트롤러는 일반적으로 전송률이 높은 CPU와 낮은 입출력장치와의 전송률 차이를 데이터 버퍼링으로 완화하는 역할을 한다.
이번에는 장치 컨트롤러의 내부 구조를 알아보겠다.
장치 컨트롤러 내부는 간단하게 보면 데이터 레지스터, 상태 레지스터, 제어 레지스터가 있다.
데이터 레지스터는 CPU와 입출력장치 사이에 주고받을 데이터가 담기는 레지스터로, 데이터 버퍼링을 할 때에 버퍼의 역할을 한다. 최근 주고받는 데이터가 많은 입출력장치에서는 레지스터 대신 RAM을 사용하기도 한다.
상태 레지스터는 입출력장치가 입출력 작업을 할 준비가 되었는지, 작업이 완료되었는지, 오류는 없는지 등의 상태 정보가 저장된다. 또한 제어 레지스터는 상태 레지스터와 하나의 레지스터로 사용되기도 하는데, 입출력장치가 수행할 내용에 대한 제어 정보와 명령을 저장한다.
장치 드라이버란 장치 컨트롤러의 동작을 감지하고 제어함으로써 장치 컨트롤러가 컴퓨터 내부와 정보를 주고받을 수 있게 하는 프로그램이다. 프로그램이기에 당연히 실행 과정에서 메모리에 저장된다.
장치 컨트롤러가 입출력장치를 연결하기 위한 하드웨어적인 통로라면, 장치 드라이버는 입출력장치를 연결하기 위한 소프트웨어적인 통로이다.
장치 드라이버는 운영체제가 기본으로 제공하는 것도 있지만, 장치 제작자가 따로 제공하기도 한다. 물론 장치 제작자가 장치 드라이버를 따로 제공하는 경우 입출력장치는 해당 드라이버를 직접 설치해야만 사용이 가능하다.
입출력 작업을 수행하려면 CPU와 장치 컨트롤러가 정보를 주고받아야 한다. 여기에는 크게 세 가지 방법이 있는데, 프로그램 입출력, 인터럽트 기반 입출력, DMA 입출력이다.
프로그램 입출력은 기본적으로 프로그램 속 명령어로 입출력장치를 제어하는 방법이다.
CPU가 프로그램 속 명령어를 실행하는 과정에서 입출력 명령어를 만나면 CPU는 입출력장치에 연결된 장치 컨트롤러와 상호작용하며 입출력 작업을 수행한다.
하드 디스크에 백업 상황으로 입출력 과정을 간단하게 알아보자면
우선 CPU는 하드 디스크 컨트롤러의 제어 레지스터에 쓰기 명령을 보낸다. 하드 디스크 컨트롤러는 하드 디스크 상태를 확인하여, 하드 디스크가 준비된 상태라면 상태 레지스터에 준비되었다고 표시한다. 그러면 CPU는 상태 레지스터를 주기적으로 읽어보며 하드 디스크의 준비 여부를 확인한 후, 준비됐음을 CPU가 알게 되면 백업할 메모리의 정보를 데이터 레지스터에 쓴다.
위와 같이 진행된다. 이렇듯 프로그램 입출력 방식에서의 입출력 작업은 CPU가 장치 컨트롤러의 레지스터 값을 읽고 씀으로써 이루어진다.
그런데 여기서 CPU는 장치 컨트롤러의 레지스터들을 어떻게 다 알고, 어떠한 명령어들을 사용할까? 여기에는 크게 두 가지 방식이 있다.
메모리 맵 입출력은 메모리에 접근하기 위한 주소 공간과 입출력장치에 접근하기 위한 주소 공간을 하나의 주소 공간으로 간주하는 방법이다.
여기서 중요한 점은 메모리 맵 입출력 방식을 사용하는 CPU는 메모리의 주소들이나 장치 컨트롤러의 레지스터들이나 모두 똑같이 메모리 주소를 대하듯 한다는 점이다. 그래서 메모리에 접근하는 명령어와 입출력장치에 접근하는 명령어는 굳이 다를 필요가 없다.
고립형 입출력은 메모리를 위한 주소 공간과 입출력장치를 위한 주소 공간을 분리하는 방법이다.
고립형 입출력은 1,024개의 주소 공간을 가진 컴퓨터가 있을 때, 메모리에도 1,024개의 주소 공간을 활용하고 입출력장치에도 1,024개의 주소 공간을 활용하는 방법으로 고립형 입출력 방식을 사용하는 CPU는 입출력장치에 접근하기 위해 메모리에 접근하는 명령어와는 다른 입출력 명령어를 사용한다.
입출력장치에 의한 하드웨어 인터럽트는 정확히 말하자면 입출력장치가 아닌 장치 컨트롤러에 의해 발생한다. CPU는 장치 컨트롤러에 입출력 작업을 명령하고, 장치 컨트롤러가 입출력장치를 제어하며 입출력을 수행하는 동안 CPU는 다른 일을 할 수 있다. 그러면 입출력 작업을 끝낸 장치 컨트롤러는 CPU에게 인터럽트 요청 신호를 보내고, CPU는 인터럽트 서비스 루틴을 실행한다.
이렇게 인터럽트를 기반으로 하는 입출력을 인터럽트 기반 입출력이라고 한다.
기본적으로 CPU는 인터럽트가 발생한 순서대로 인터럽트를 처리하는데, CPU가 플래그 레지스터 속 인터럽트 비트를 비활성화한 채 인터럽트를 처리하는 경우 다른 입출력 장치에 의한 하드웨어 인터럽트를 받아들이지 않기 때문에 CPU는 순차적으로 하드웨어 인터럽트를 처리하게 되는 것이다.
하지만 현실적으로 모든 인터럽트를 전부 순차적으로 해결할 순 없다. 인터럽트 중에서도 빨리 처리해야 하는 인터럽트가 있기 때문에, 인터럽트 간에 우선순위를 고려하여 우선순위가 높은 인터럽트 순으로 여러 인터럽트를 처리해야 한다.
플래그 레지스터 속 인터럽트 비트가 활성화되어 있는 경우, 혹은 인터럽트 비트를 비활성화해도 무시할 수 없는 인터럽트인 NMI가 발생한 경우 CPU는 이렇게 우선순위가 높은 인터럽트부터 처리한다.
우선순위를 반영하여 다중 인터럽트를 처리하는 방법에는 여러 가지가 있지만, 많은
컴퓨터에서는 프로그래머블 인터럽트 컨트롤러(PIC)라는 하드웨어를 사용한다.
PIC는 여러 장치 컨트롤러에 연결되어 장치 컨트롤러에서 보낸 하드웨어 인터럽트 요청들의 우선순위를 판별한 뒤 CPU에 지금 처리해야 할 하드웨어 인터럽트는 무엇인지 알려주는 장치이다.
PIC는 위 그림처럼 여러 핀이 있는데, 각 핀에는 CPU에 하드웨어 인터럽트 요청을 보낼 수 있는 약속된 하드웨어가 연결되어 있다.
PIC에 연결된 장치 컨트롤러들이 동시에 하드웨어 인터럽트 요청을 보내면 PIC는 이들의 우선순위를 판단하여 CPU에 가장 먼저 처리할 인터럽트를 알려준다.
일반적으로 더 많고 복잡한 장치들의 인터럽트를 관리하기 위해 PIC를 두 개 이상 계층적으로 구성하여 훨씬 더 많은 하드웨어 인터럽트를 관리한다.
앞서 설명한 프로그램 기반 입출력과 인터럽트 기반 입출력은 데이터가 반드시 CPU를 거쳐야 했다. 그런데 이러면 가뜩이나 바쁜 CPU는 입출력장치를 위한 연산 때문에 시간을 뺏기게 되고 부담도 더 커지게 된다. 그래서 입출력장치와 메모리가 CPU를 거치지 않고도 상호작용할 수 있는 입출력 방식인 DMA가 등장하였다.
DMA는 이름 그대로 직접 메모리에 접근할 수 있는 입출력 기능으로, DMA 입출력을 하기 위해서는 시스템 버스에 연결된 DMA 컨트롤러라는 하드웨어가 필요하다.
DMA 입출력은 다음과 같이 이루어지는데,
우선 CPU는 DMA 컨트롤러에 입출력장치의 주소, 수행할 연산과 같이 입출력 작업에 필요한 정보로 입출력 작업을 명령한다. 그러면 DMA는 CPU 대신 장치 컨트롤러와 상호작용하며 입출력 작업을 수행하고, 입출력 작업이 끝나면 CPU에 인터럽트를 걸어 작업이 끝났음을 알린다.
이렇게 CPU는 DMA 컨트롤러를 이용해 작업 부담을 훨씬 줄일 수 있다.
그런데 여기서 문제점이 있다. 시스템 버스는 공용 자원이기 때문에 CPU가 시스템 버스를 사용할 때는 DMA 컨트롤러는 시스템 버스를 사용할 수 없고, DMA 컨트롤러가 시스템 버스를 사용할 때는 CPU가 시스템 버스를 사용할 수 없다는 것이다.
그래서 나오게 된 것이 입출력 버스이다. DMA 컨트롤러와 장치 컨트롤러들을 입출력 버스라는 별도의 버스에 연결하는 것이다. 그러면 DMA 컨틀롤러가 데이터를 전송할 때 시스템 버스를 이요할 필요가 없으므로 시스템 버스의 사용 빈도를 줄일 수 있다.
현대 대부분 컴퓨터에는 입출력 버스가 있다. 이런 점에서 볼 때 입출력 버스는 입출력장치를 컴퓨터 내부와 연결 짓는 통로라고도 볼 수 있다.
공감하며 읽었습니다. 좋은 글 감사드립니다.