I/O operations
- I/O devices와 CPU는 concurrent하게 작동된다.
- I/O : device와 controller의 buffer 사이 data가 이동하는 것.(CPU까지 도달하는 과정 포함)
- Controller : I/O processor
- 각 controller는 local buffer와 special register가 있다.
- device driver : 모든 device controller의 sw이다.
Accessing I/O Devices
Memory Mapped I/O
- memory의 주소 공간을 배정하여 같은 주소 공간을 사용하는 것
- 일반적으로 사용하는 방법
- memory에서 읽고 쓰는 명령어를 사용한다.
- 개발자 입장에서 사용하기 조금 더 편하다.
Special(Isolated) I/O
- Channel I/O라고도 한다.
- CPU는 I/O를 위한 별도의 Hardware bus를 가지고 있다.
- inport, outport..등 특별한 명령어를 사용한다.
- 메모리와 I/O를 분리했기 때문에 성능 면에서 조금 더 낫다.
Polling I/O(Programmed I/O)
- CPU가 status register를 이용해서 지속적으로 check를 하는 것
- Data-in register : buffer와 유사하다.
- Data-out : buffer와 유사하다.
- Status register : 현재 device의 상태를 나타내는 register(CPU가 무언가를 하고 있는지 등 확인하는 register)
- Control register(Command register) : CPU가 하고싶은 명령을 저장하는 register
data를 device에 write하는 과정(Polling I/O)
- CPU가 status register의 busy bit를 확인하고 device가 정보를 받을 수 있는지 확인
- write bit를 set 또는 write 명령어를 실행 후 data out
- control register에 command-ready bit를 set한다.
- device controller가 ready bit를 확인하고 busy bit를 set한다.
- device controller가 command register를 읽고 write bit를 설정하고 I/O 장치로 보낸다
- command ready bit, error bit, busy bit를 clear한다.
polling I/O의 문제점
- 한 개의 word를 보낼때도 CPU가 개입을 하게 된다. 즉, polling하는데 시간을 많이 소비하게 된다.
- CPU는 속도가 매우 빠르지만 I/O device는 속도가 느리기 때문에 불필요한 작업 때문에 낭비가 심하게 된다.
- I/O controller의 buffer의 속도가 느려서 data가 빨리 들어오면 data가 넘쳐 data의 손실이 일어날 수 있다.
해결법

- 현대 운영체제에서는 interrupt를 활용한다.(HW가 지원한다.)
Interrupts

- CPU hardware는 interrupt-request line(wire)를 가지고 있고, 각 명령어를 처리한 다음 check를 한다.
- interrupt가 들어왔을 때 context를 kernel memory에 저장을 하고 interrupt를 처리하는 routine(device driver 내부에 들어있다.)으로 jump를 하여 interrupt를 처리한다. 처리한 다음에는 원래의 위치로 돌아온다.
- 장치가 hw 신호로 interrupt를 raise했다고 알려주고, CPU가 interrupt를 catch한 다음 지정된 interrupt handler가 실행이 되고, 해소가 되면 clear
- 대부분의 os는 interrupt-driven 형태로 작동한다.
Interrupt Handling

- Interrupt controller는 여러 개의 interrupt가 들어오면 우선순위에 따라 처리를 한다.
- 누가 interrupt를 걸었는지 알려주는 interrupt number와 interrupt를 함께 CPU에 알려준다.
- interrupt number : 각 device or event에 부여된 고유 number
- interrupt vector table : memory 내부의 특수한 영역에 위치하고 있고, interrupt number가 오면 해당 number에 대응하는 interrupt가 저장되어 있는 table. 즉, interrupt handler가 위치하고 있는 address가 저장되어 있다.
- context : CPU 내부의 register의 상태를 저장하는 것
- CPU의 상태는 각 process(PCB), device마다 지정된 공간 또는 system stack에 저장을 한다. 일반적으로 각 process의 지정된 공간(PCB)에 저장을 많이 한다.
- vectored interrupt system을 이용하여 interrupt를 확인한다.
Interrupt Timeline

Direct Memory Access(DMA)

- 너무 빈번하게 interrupts를 발생시켜서 CPU가 원래 작업을 하지 못하는 상황이 발생
- 대량의 bulk data 전송 / 고속의 data 전송 때 interrupt가 발생해서 overhead가 큰 문제
- bulk data를 CPU interrupt 없이 알아서 memory로 전달하는 방식
- device는 대량의 data를 읽고 쓰고 하고, 이러한 작업이 전부 완료 되었을 때 한번에 CPU에 알려준다.
- DMA controller의 count만큼 처리가 되면 CPU에게 data 작업 처리가 완료되었다고 CPU에게 알려준다.
Modern Interrupt Handling
- 현대 OS는 더욱 부가된 기능을 가지고 있다.
- interrupt를 더욱 지연(disable)할 수 있는 기능 → 더 중요한 기능을 할 때(interrupt에 방해를 받지 않고싶을 때)
- interrupt handler를 실행시키는 기능이 여러 가지 있다.
- interrupt vector : 장치의 번호를 부여하고 interrupt에 활용하는 방법
- priority를 부여하여 우선순위를 매긴다. 높은 priority를 가진 interrupt를 우선적으로 처리하는 방식
- preempt processing : low priority를 가진 interrupt를 처리하다가 high priority interrupt가 온다면 하던 것을 멈추고 높은 우선순위의 interrupt를 먼저 처리하는 것.
- CPU는 interrupt request line이 두가지가 있다.
- Maskable interrupt : interrupt를 disable하는 것
- Non-maskable interrupts : 절대 끌 수 없는 interrupt
Traps and Exceptions
Trap
- user program이 의도적으로 실행시키는 명령
- 목적은 대부분 OS service(system calls)를 받기 위해서이다.
- software의 interrupt(명령어)
Exception
- 대부분 비정상적인 상황(div by 0, memory access violation..)에서 일어난다.
- CPU에서 나타내는 일종의 오류 신호
Handling
- hardware의 interrupt와 유사하게 처리한다.
- 실행 중인 process를 정지한다.
- handler routine으로 분기하고 처리한 뒤 저장한 state로 돌아온다.
Protection
- application program이 memory에 접근하여 내용을 바꿀 수도 있고, 무한 loop를 돌아서 빠져나오지 못하는 경우가 있다.
- user는 CPU를 독점하거나, 의도적으로 다른 program에 무언가를 심으려고 하거나 자원을 독점하려고 하는 상황이 생길 수도 있다.
- 이러한 상황을 제어하기 위해서 OS는 protection mechanism을 제공한다.
Protecting Memory
- program이 할당 된 영역 내에서만 접근할 수 있도록 한다.
- 다른 program에서 write를 하는 행위 등을 막는다.
- Virtual Memory, Base register와 Limit register를 두어 사이의 address에 속해있는지 확인하는 방식이 있다.
CPU control
- Non-cooperative approach
- 의도치 않게 무한 loop에 빠진 경우..
Timer Hardware
- 일정시간마다 timer를 작동시키게 하고, interrupt / interrupt handling을 한다.
- Non-cooperative approach
- 주어진 시간(quantum)으로 timer를 설정한다.
- OS가 timer에게 interrupt time을 load를 한다.
- program이 작동하다가 timer가 작동을 하고, counter variable이 0이 되면 프로그램을 교체와 같은 방식을 사용한다.
- timer를 이용하여 program이 interrupt를 당하고 OS가 CPU control을 가져간다.
- CPU의 독점, 무한 루프 등의 문제를 해결할 수 있다.
- Privileged(특권 명령) : 일반 user는 timer 설정이 불가하고 OS만 timer value 설정이 가능하다.
Privileged Instructions
- 일반 user는 접근/명령하지 못하고 OS만 설정할 수 있는 것들
- 특권 명령을 이용하면 protection을 효과적으로 지원하고, OS와 user의 사용영역을 분리하기 쉬워진다.
- hardware resource에 접근하는 장치(I/O devices, disks, printer)
- memory management와 관련된 명령(page table pointer...)
- system register에 접근하는 것(control registers, system table locations...)
- CPU mode bits를 설정하는 것
- Halt instructions
- Timer value를 설정하는 명령
CPU Modes of Operation
- CPU 내에는 mode를 지원하는 bit가 있다. → User mode / Kernel(supervisor) mode
- OS는 kernel mode에서만 동작하고 user는 user mode에서만 동작할 수 있다.
- OS는 모든 resource에 접근이 가능하고, privileged instructions는 kernel mode에서만 사용이 가능하다.
- CPU는 hardware 내의 mode bit를 확인하고 동작한다.
- system call(trap)이 호출되면 kernel로 들어가면서 mode bit를 바꾼다.
- RTI(interrupt를 끝내고 돌아올 때)가 실행되면 mode bit가 바뀐다.
- User program은 privileged를 원칙적으로 사용이 불가능하지만 OS에게 요청을 해서 사용이 가능하다.(system call)
Crossing Protection Boundary

- 왜 OS에 system call을 호출할 때는 꼭 trap으로 interrupt 형태로 요청해야 하는가?
- protection이 불가능하기 때문, OS를 보호할 수가 없어진다.
- 분리된 객체로 관리해야하기 때문에 함수 호출과 같은 형태로 호출할 수 없다.
- System Call : User가 privileged 사용을 OS에게 실행시켜달라고 요청을 하는 것.
- system call을 할 때 trap이 실행되고 user mode(1)에서 kernel mode(0)로 bit가 바뀐 뒤 system call이 실행되고 다시 user mode(bit = 1)로 돌아간다.
System Call

- OS가 제공하는 service, 이를 호출하는 interface
- 대부분 C/C++로 구성되어 있다.
- 실제로 system call의 내용(open, read, write...)과 코드는 kernel에 있다.
- Wrapper Library : user mode에서 system call을 하기 위해 제공하는 준비단계 모음 및 trap 모음
- OS는 illegal한 request를 받지 않는다.
- OS는 각 자원마다 적절한 할당량을 지원한다.
- 자원을 공유할 때 공평하게 분배되도록 system call에 의해 고려된다.
- System call은 protected procedure call이다.
- routine은 OS code, 즉 kernel 모드에 존재한다.
- user모드에서 요청되어 kernel 모드에서 실행된 뒤 user mode로 복귀하는 형식이다.
- system call은 OS마다 다르다. 그리고 POSIX, Java 등에 의해서도 달라진다.
- user가 사용하는 library의 함수들도 OS의 도움을 받아 system call을 최종적으로 호출한다.
Reducing System call Overhead
- user-kernel mode로 구분된 곳에는 performance barrier가 존재한다.
- hardware barrier를 지나갈 때 costly
Solution
- system call의 횟수를 줄이는 것
- Library
- DLL(Dynamic Linking Library)
- caching result
- buffering ops
System call을 하는 것이 부담스러움에도 불구하고 사용하는 이유는 OS kernel을 응용프로그램으로부터 보호하기 위해, 즉 구조적 안정성을 위해서이다.
OS Structure
- 하나의 독립된 software이고, 하나의 process로 볼 수 있다.
- main process는 OS가 booting이 될 때 한 번 실행 된다.
- kernel에서 사용할 수 있는 resource가 많다.
- OS에도 bug가 있어 crash가 생기는 경우가 있다.
- 외부의 사건에 반응하는 event driven software/Interrupt driven software이다.
- OS 내에서는 어떤 instruction이든 실행할 수 있다.(privileged instruction 포함)
- concurrently, simultaneously
OS를 시작하는 방법
- main board에 위치한 BIOS의 Master Boot Record(MBR)에 small OS(bootloader)를 기동시킨다.
- Hard disk에 있는 windows kernel이 설치한 위치(Big OS kernel)를 기억해서 memory로 loading
OS가 하는 일
- OS도 program이기 때문에 loop을 돌며 대기하는 형태
- system management & profiling(application이 자원을 사용한 것 기록)
- power mode가 낮은 경우 process를 잠시 suspend(halt), 대기 모드로 전환
- 새로운 계산 시도
When OS wake up?
- hardware interrupt, user’s trap이 발생했을 때
- user program에서 exception이 발생했을 때