컴퓨터 시스템 구조
-
CPU
- 매 clock cycle마다 메모리에서 instruction 하나를 읽고 수행한다.
- instruction 수행 후 매번 interrupt line을 확인한다
-
IO device
- 입출력 장치
- 메모리는 IO device에 접근할 수 없음. 오직 OS만 접근 가능하다
-
register
- 메모리보다 더 빠르면서도 데이터를 저장할 수 있음
-
interrupt line
- CPU는 메모리 관련 작업을 계속 하다가, interrupt가 interrupt line에 들어오면 CPU는 하던 작업을 잠시 멈추고 CPU 제어권을 OS에게 넘겨준다.
Mode Bit
- CPU에 실행되고 있는 작업이 운영체제의 것인지, 프로그램 것인지를 구분하는 bit
- 기능 및 목적
- 프로그램의 잘못된 수행으로 다른 프로그램 및 운여체제에 피해가 가지 않도록 하기 위한 보호 장치로서 역할을 한다.
- mode bit을 통해 CPU는 두 가지 모드로 작동하게 된다
- 1 (사용자 모드)
- 사용자 프로그램 모드
- 사용자 프로그램에게 CPU를 넘기기 전에 하드웨어는 mode bit을 1로 셋팅한다
- 0 (모니터/커널/시스템 모드):
- OS 코드 수행
- Interrupt나 Exception 발생 시 하드웨어가 mode bitd을 0로 설정
- 모드별 설정
- 모드에 따라 CPU가 수행할 수 있는 작업이 제한될 수 있다. 보안을 해칠 수 있는 중요한 명령어는 '특권 명령'으로 규정하며, 모니터 모드에서만 수행 가능하다 (ex. IO device 접근 X).
- 즉, 모든 Instruction을 수행할 수 있는 모드는 모니터 모드, 특권 명령이 아닌 일반 명령어만 실행할 수 있는 모드는 사용자 모드이다.
timer
- 목적: 특정 프로그램이 CPU를 독점하는 것을 방지하는 하드웨어이다
- 작동 방식
- 프로그램에게 CPU가 할당되기 전 timer에 특정 값을 할당한다.
- 타이머는 매 clock cycle 때마다 1씩 감소
- timer가 0이 되면 interrupt를 CPU에게 보낸다.
- CPU는 하던 일을 멈추고 제어권이 운영체제에게 넘어간다.
- 타이머는 time sharing을 구현하기 위해 널리 이용됨
- 타이머는 현재 시간을 계산하기 위해서도 사용
Device controller
- 이는 IO device를 전담하는 작은 CPU로, IO device에 붙어있다.
- 어떤 데이터를 읽을지, 헤드를 어디로 이동시킬지, CPU에게 입출력이 끝났음을 알리는 interrupt를 보낼지 등 IO device 내부를 통제하는 것은 CPU가 아닌 device controller이다.
- register
- 제어 정보를 위해 control register, status register를 가진다.
- 제어 정보란 IO device에게 명령을 시키기 위해 필요한 정보를 의미한다
- local buffer
- main CPU의 작업공간인 메모리가 있듯이 device controller의 작업공간인 local buffer가 있다.
- 일종의 data register이다.
- IO는 실제 device와 local buffer 사이에서 일어남
- device controller는 IO가 끝났을 경우 Interrupt로 그 사실을 알림
- 그러면 CPU는 Local buffer에 저장된 데이터를 읽고 Memory에 복사한 후, 작업을 이어나간다.
- 이때, IO device는 memory에 접근할 수 없다. 오직 Local buffer에만 접근 가능
- 그러나 이런 방식은 CPU에 interrupt를 너무 자주 발생시키기 때문에 DMA controller가 중간에 개입해 interrupt 발생 횟수를 줄인다.
DMA (Direct Memory Access)
- 빠른 입출력 장치를 메모리에 가까운 속도로 처리하기 위해 사용
- 원래 메모리를 접근할 수 있는 유일한 장치는 CPU였지만, CPU가 워낙 많은 인터럽트를 받아 효율적으로 사용할 수 없음
- 그래서 CPU의 중재 없이 device controller가 device의 buffer storage의 내용을 메모리에 block 단위로 직접 전송. 전송 이후 CPU한테는 IO 입출력 및 데이터 전송이 완료되었음을 알림
- 바이트 단위가 아니라 block 단위로 인터럽트를 발생시킴
Interrupt
- 인터럽트 당한 시점의 레지스터와 program counter를 save한 후 CPU의 제어를 언터럽트 처리 루틴, 즉 OS에 넘긴다.
- 운영체제는 인터럽트 발생할 때만 CPU를 사용. 대부분은 사용자 프로그램이 사용함
- 종류
- Interrupt (하드웨어 인터럽트)
- 하드웨어가 발생시킨 인터럽트
- Ex) IO device, timer가 발생한 인터럽트
- Trap (소프트웨어 언터럽트)
- 소프트웨어가 발생시킨 인터럽트로 두 가지 종류가 있다.
- exception: 프로그램이 오류를 범한 경우
- system call: 프로그램이 운영체제의 서비스를 받기 위해 커널 함수를 호출하는 경우 (ex. 프로그램이 IO를 요청하는 경우)
- 인터럽트 관련 용어
- 인터럽트 벡터
- 인터럽트 처리 루틴
- = Interrupt service routine, 인터럽트 핸들러
- 해당 인터럽트를 처리하는 커널 함수
입출력의 수행
* 모든 입출력 명령은 특권 명령
1. 시스템 콜 (사용자 프로그램은 OS에게 IO 요청)
2. trap을 사용하여 인터럽트 벡터의 특정 위치로 이동
3. 제어권이 인터럽트 벡터가 가리키는 인터럽트 서비스 루틴으로 이동
4. OS는 올바른 IO 요청인지 확인 후 IO controller에게 IO 명령을 부탁함
5. 이후 CPU는 다음 명령으로 넘어감. 즉 제어권을 시스템 콜 다음 명령으로 옮김
6. 실제 IO 완료 시 device controller는 하드웨어 인터럽트가 발생시킴.
동기식 입출력과 비동기식 입출력
![](https://velog.velcdn.com/images/spig0126/post/336cbe25-4548-489f-bf65-68df23a09488/image.png)
동기식 입출력 (Synchronous I/O)
I/O 요청 후 입출력 작업이 완료된 후에야 제어가 사용자 프로그램에게 넘어가는 입출력 방식
구현 방법
방법 1)
- I/O가 끝날 때까지 CPU를 낭비시킴
- 매시점 하나의 I/O만 일어날 수 있음
방법 2)
- I/O가 완료될 때까지 해당 프로그램에게서 CPU를 빼앗음
- I/O 처리를 기다리는 줄에 그 프로그램을 줄 세움
- 다른 프로그램에게 CPU를 줌
*두 경우 모두 I/O의 완료는 인터럽트로 알려줌
비동기식 입출력 (Asynchronous I/O)
I/O 시작된 후 입출력 작업이 끝나기를 기다리지 않고 제어가 사용자 프로그램에 즉시 넘어감 입출력 방식
서로 다른 입출력 명령어
![](https://velog.velcdn.com/images/spig0126/post/965f1c2b-da4a-49b5-873b-d90e26a8a574/image.png)
- 왼쪽: IO를 수행하는 special instruction에 의해
- IO 장치들은 메인 메모리와 아예 별개의 주소를 가지고 있어, IO를 수행할 때 special instruction을 이용해 특정 IO 장치를 접근
- 오른쪽: Memorm Mapped IO에 의해
- IO 장치들도 메인 메모리와 같은 방식의 주소를 갖게 하는 방식
- 메인 메모리 주소를 연장하는 방식
저장장치 계층 구조
![](https://velog.velcdn.com/images/spig0126/post/83ed32d9-8709-41a2-bd95-7553854fb64b/image.png)
- 계층이 올라갈수록 속도가 빠르지만, 동시에 가격이 비싸고 용량도 적음
- 그리고 primary 메모리는 휘발성(volatility) 매체, 즉 전원 끄면 데이터가 날아가는 매체이다
커널 주소 공간의 내용
- code
- 시스템콜, 인터럽트 처리 코드
- 자원 관리를 위한 코드
- 편리한 서비스 제공을 위한 코드
- data
- 운영체제가 사용하는 여러 자료구조들이 존재
- 각 하드웨어/소프트웨어 관리하기 위한 자료구조를 가지고 있음
- stack
- 사용자 프로그램이 커널 함수를 호출할 때마다 해당 프로세스가 커널 스택에 올라감
사용자 프로그램이 사용하는 함수
- 사용자 정의 함수
- 라이브러리 함수
- 자신의 프로그램에서 정의하지 않고 갖다 쓴 함수
- 자신의 프로르갬의 실행 파일에 포함되어 있음
- 커널 함수
- 운영체제 프로그램의 함수
- 커널 함수의 호출 = 시스템 콜
사용자 정의 함수와 라이브러리 함수는 프로세스 내에서 특정 virtual memory 주소로 jump해서 실행하는 반면, 커널 함수를 호출할 경우 jump가 불가능함. 그래서 사용자 정의 함수와 라이브러리 함수는 인터럽트를 발생시킬 필요가 없지만 커널 함수를 호출할 때는 인터럽트를 발생시켜 CPU가 제어권을 가지고 커널 함수를 실행시키도록 해야 함.