의도적으로 인터럽트를 발생 시켜서 CPU 제어권을 OS를 통해 사용자 프로그램으로 넘긴다. (Mode bit=1에서 Mode bit=0으로 변경)
사용자 프로그램은 CPU에 직접 접근이 불가능하다. 그래서 Mode bit을 1에서 0으로 바꿔 OS에게 필요한 서비스를 요청한다.
ex) 프로그램에서 필요한 데이터를 읽어와서 처리해야 되는 경우 => 동기식처리
하나의 작업이 끝날때까지 기다렸다가 작업이 끝나면 다음 작업을 시작하는 방법이다.
작업중에 오래걸리는 작업은 뒤로 미뤄두고 먼저 끝나는 작업부터 처리하는 방법이
다.
여기서 오래 걸리는 작업을 뒤로 미뤄둔다는 의미는 아무것도 안하면서 뒤로 미루는게 아니다. 예를들어 A버퍼에는 물이 꽉차있고, B버퍼는 물이 빈 상태에서 이제 차기 시작한다. 그럼 A버퍼를 먼저 처리하면서 B버퍼에는 물이 차고있을거다. 그러면 A버퍼를 처리 한 후에 B버퍼를 처리한다는 소리다.
ex) 프로그램에서 필요한 데이터 없이 글을 쓰는 과정 -> 비동기식 처리
(동기식, 비동기식) 입출력 모두 I/O의 완료는 인터럽트로 알려준다.
메모리와 I/O가 하나의 연속된 주소영역에 할당된다. 따라서 I/O가 차지하는 만큼 메모리 용량은 감소한다. CPU입장에서는 메모리와 I/O가 동일한 외부기기로 간주되므로 이들을 액세스 하기위하여 같은 신호를 사용한다. (read/write) 또한 소프트웨어적으로도 메모리에 대한 액세스나 I/O에 대한 데이터 입출력이 동일한 것으로 간주되므로 Load나 Store 명령에 의해 수행된다.
위 방식의 가장 큰 장점은 포트 입출력을 구현할 때 부수적인 복잡성이 없어지기 떄문에 CPU 내부적으로 로직이 덜 필요하고, 이는 더 저렴하고 빠르고 쉬운 CPU를 만들 수 있게 한다. 이 점이 RISC가 추구하는 바와 같다. 이러한 특징은 임베디드 시스템 구현시 장점으로 적용한다. 하지만 주소와 데이터 버스를 많이 사용하게 되어, 메인 메모리에 접근하는 것 보다 매핑된 장치에 접근하는 것이 더 느리다.
(대표적인 프로세서: ARM, MIPS, PowerPC, M68K)
- 사용시 I/O영역 변수는 volatile 타입으로 선언해야 한다. (컴파일러의 최적화 방지)
- I/O영역은 Non-cacheable로 설정해야 한다.(캐시메모리로 접근할 경우, 변경된 내용은 가져올 수 없을 수도 있다.)
메모리와 I/O가 별개의 주소영역에 할당된다. 따라서 I/O를 사용하더라도 메모리 용량은 감소하지 않는다. CPU의 입장에서는 메모리와 I/O를 구분하여 취급해야 하므로 이들을 액세스하기 위해서는 RD, WR 신호 이외에 추가적으로 I/O에 접근하기 위한 신호가 필요하다. 소프트웨어 적으로도 메모리에 대한 데이터의 액세스와 I/O에 대한 데이터의 입출력이 서로 다른 것으로 간주된 메모리에 대한 액세스는 Load/Store에 의해 수행되고 I/O의 입출력은 Input이나 Output 명령에 의해 수행된다.
이 방식의 가장 큰 장점은 어드레싱 능력이 제한된 CPU를 사용할 떄 이다. 입출력 접근을 메모리 접근과 분리하기 떄문에 메모리용으로 주소영역 전체를 사용할 수 있다. 또한 어셈블리어상에서 소스를 볼 때 입출력 수행 루틴을 알아보기 쉽다.
(주로 Interl 계열의 프로세서에서 사용한다. x86)
RISC는 Reduced Instruction Set Computer의 약자로, CPU 명령어의 갯수를 줄여 하드웨어 CISC보다 구조를 조금 더 간단하게 만드는 방식이다.
- 참고로 ARM Processor는 임베디드 시스템상의 프로세서로 RISC구조이며 Memory Mapped I/O(MMIO) 방식을 취하고 있다.
- ARM 어셈블러나 c로 작성할 때, 실제로 메모리 주소를 포인터로 잡아서 값에 접근하는 모습을 볼 수 있다
- 특히, 어셈블러상에서 in/out과 같은 I/O port 접근 명령어가 따로 존재하지 않고, 일반 메모리에 대한 접근인 id/st 명령어를 사용한다.
참고
위로 갈수록 빠르고, 비싸고, 용량이 적다.
CPU가 직접 접근한 부분은 Primary,
CPU가 직접 접근하지 못하는 부분은 Secondary