728x90
- 현재 OS는 Time sharing, Multi Programming
I/O
I/O Operation
- I/O 디바이스와 CPU는 병행적으로 작동 가능
- 물리적 디바이스와 컨트롤러 버퍼 사이 데이터 전달
- 각 디바이스는 로컬 버퍼와 레지스터를 가지고 잇음
- 디바이스 컨트롤러를 위한 디바이스 드라이버가 필요 → 컨트롤러에게 필요한 명령어를 제공해주는 모듈
Accessing I/O Devices
- Memory Mapped I/O → 더 자주 쓰임
- 주소를 이용해 접근
- I/O 디바이스가 CPU 메모리와 똑같이 동작
- 일반적인 load, store 동작 → 사용하는 명령어 인터페이스가 같음
- Special(isolated) I/O
- Channel I/O라고도 부름 → 특수한 명령어가 필요하다
- CPU가 I/O 디바이스를 위한 별도의 버스를 가지고 있음
Polling I/O
- Programmed I/O라고도 불림
- CPU가 I/O 디바이스를 지속적으로 확인 → 시간 낭비 ⇒ 이를 해결하기 위해 interrupt가 등장
- 각 디바이스는
- Data-in, Data-out 레지스터
- Status 레지스터
- Control, Command 레지스터 존재
- 디바이스에 데이터 write 과정
- CPU가 Status 레지스터의 busy bit가 빌때까지 확인
- CPU는 Command 레지스터에 write하겠다는 bit를 쓰고 Data-out 레지스터에 output 값을 write
- CPU가 Control 레지스터에 command-ready bit를 씀
- 디바이스 컨트롤러는 이 bit를 보고 Status 레지스터에 busy bit를 씀
- 디바이스 컨트롤러가 command 레지스터를 읽고 write bit를 보고 Data-out 레지스터를 읽고 I/O 수행
- 디바이스 컨트롤러는 command-ready bit와 error bit, bust bit를 지움
- 문제점
- CPU가 polling에 너무 많은 시간을 할애 → 프로세스 대기 버퍼 메모리 오버플로우 위험
- 이를 해결하기 위해 interrupt를 사용
Interrupt
- CPU는 IRQ(Interrupt-request line)으로 interrupt 확인
- interrupt 시그널을 받으면 해당 프로세스 레지스터 내용(context)들을 메모리에 저장
- 디바이스 컨트롤러가 interrupt raise → CPU가 확인 → interrupt handler가 dispatch하여 처리
- OS는 interrupt-driven
- 하드웨어 : 버스로 트리거(interrupt)
- 소프트웨어 : system call(trap)
Interrupt Handling
- CPU에 현제 프로세스 context를 system stack에 저장
- 어떤 종류의 interrupt인지 확인하는 방법
- Polling : 모든 interrupt를 확인하여 어느 interrupt가 일으켰는지 확인
- Vectored interrupt system : interrupt를 보낼 때 vector 번호를 함께 보내 누가 보냈는지 알 수 있게 함
- 제어권을 ISR(Interrupt Service Routine)이나 Interrupt Handler에게 넘김
Direct Memory Access
- 특정 하드웨어 시스템이 CPU와 독립적으로 메인메모리에 접근할 수 있게 해주는 방식
- 디바이스들의 로컬버퍼에서 메모리로 데이터 이동이 완료되었다는 인터럽트만 발생시킨다.
- 많은 데이터를 디스크로 전달하기 위해서 programmed I/O(PIO)를 사용한다면 CPU가 다른 프로세스를 처리하기 위해 사용될 수 있는 시간들이 허비.
- byte단위로 인터럽트를 주지 않고 블럭단위(예를 들면 512Byte)로 전송이 완료될 때마다 인터럽트
- 프로그램 수행 도중 CPU가 입/출력 명령을 만남.
- CPU는 DMA에게 입/출력 명령(기억장치내의 데이터의 위치, 개수, I/O 명령의 종류 등이 전달).
- CPU와 독립적으로 DMA는 기억장치의 데이터를 직접 입/출력. CPU는 입/출력 명령을 내린 후 다른 프로그램을 수행.
- 주기억 장치와 주변장치 사이에 실제의 데이터 전송.
- DMA는 입/출력 완료 시 CPU에게 인터럽트로 완료 사실을 보고
Modern Interrupt Handling
- 다단계 interrupt 운선순위를 적용하여 선점형 처리
- Maskable interrupt
- Interrupt Mask가 가능한 인터럽트
- Interrupt Mask : 인터럽트가 발생하였을 때 요구를 받아들일지 말지 지정하는 것.
- NMI(non-maskable interrupt)
- Interrupt Mask 가 불가능한 인터럽트.
- 무시될 수 없는 interrupt == 매우 중요한 interrupt
- interrupt는 interrupt vector를 포함하여 전송 → 벡터 크기보다 더 많은 디바이스가 있을 경우 연결 리스트로 해결
Traps and Exceptions
- 소프트웨어가 발생시키는 인터럽트
- Exception
- 프로그래밍 에러 시 발생 ex) div by 0, memory access violation
- Trap
- 프로그램이 OS 서비스가 필요할 때 발생(system call)
- 소프트웨어 인터럽트라고도 함
- OS kernel로 들어가기 위함
Protection
- 프로그램 및 OS를 보호하기 위함.
Protecting Memory
- 다른 프로그램의 데이터 침범을 막음
- 유저 프로그램으로부터 OS 보호
- Base/Limit register : OS가 프로그램 주소를 관리 및 체크
- 가상 메모리 및 segmentation도 같은 맥락
CPU Control
- 협력적인 방안 → 프로그램들이 주기적 system call(
yield()
)로 CPU 제어권을 OS에게 넘김- OS가 프로그램들을 신뢰할 수 있을 경우에만 사용 가능
- Timer Hardware
- 무한 루프 혹은 독점을 막기 위한 방안 → 협력 X
- 시간 quantum timer를 정해 interrupt 발생
- OS가 CPU 제어권을 확실하게 가질 수 있음
- 시간 quantum을 정하는 것이 바로 protected(privileged) operation → OS만이 할 수 있음
Privileged Instructions
- User mode에서는 실행할 수 없는 명령
- 하드웨어 자원에 직접적인 접근
- 메모리 관리 상태 명령어
- 시스템 레지스터 접근
- 명령어 중지
- CPU mode bit 변경
- User mode : 유저 프로세스 영역
- Kernel Mode : OS 관리 영역
- system call 발생 시 kernel 모드로 전환
- 해당 작업 마치고 RTI(Return From Interrupt) 명령어로 User 모드로 전환
System Calls
- OS에 의해 제공되는 프로그래밍 인터페이스 서비스
- 부적절한 요청들을 막음으로써 OS 보호
- 특정한 자원 할당에 이용함으로써 자원 공유 공정성 확보
- Protected Procedure Call : 오직 kernel 모드에서만 실행됨
- 유저 모드에서
open()
으로 system call 호출 → Library function(API) - sys open → 실제 open에 해당하는 일은 kernel mode에서 실행
- 유저 모드에서
count = read(fd, buffer, nbytes));
실행 과정stack에 각 파라미터 저장 및 함수 호출
레지스터에 read함수 실행을 위한 코드(syscall) 저장
kernel에게 trap
interrupt handler가 dispath 및 해당 syscall handler에게 배분 후 처리
trap이 불려졌던 곳으로 복귀
스택 포인터 증가(스택에 있던 값 삭제)
빈번한 System call → Overhead
- User mode에서 system functionality 제공
- 결과 캐싱 및 buffering ops(fopen, fread, write) : 함수 안에 버퍼가 있어, 한번 읽은 데이터는 다시 syscall하지 않아도 됨
- 오버헤드를 감수하고도 나눈 이유 → OS-User 분리 ⇒ Protection 달성
- User mode에서 system functionality 제공
운영체제 구조
- 운영체제도 CPU에서 돌아가는 프로세스 중 하나이다.
- Event Driven
- 싱글 thread가 아닌 이벤트가 발생할 때마다 thread가 생성된다.
- 컴퓨터를 켜면, CPU는 BIOS에서 pre-loaded → small OS(Master Boot record) 읽어들인다. → 전체 OS를 실행
- OS로 바로 분기를 안하고 왜 small OS를 먼저 읽는가?
- OS마다 file system이 다르기에 그것을 먼저 이해하는게 필요하다.
- 즉, MBR이 file system을 이해하는 역할
- OS로 바로 분기를 안하고 왜 small OS를 먼저 읽는가?
OS가 하는 것
- 프로그램들을 실행, 없으면 idle loop → Event Driven이기 때문
Monolithic Structure
- 모든 기능들이 커널 모드에 들어이음
- 어느 한 부분이 문제 생기면 전체가 망가지는 위험성이 존재
Layered Structure
- 각 인접 계층끼리만 interface함
- 안정적으로 개발이 가능하며, 확장성이 좋다
- 하지만 계층간 오버헤드가 존재
Microkernel Structure
- 커널 모드에 있던 기능들 몇개를 유저 모드에 옮겨놓음
- 유저 모드에 있는 모듈들은 message passing으로 communication
- 확장성 및 이식성이 좋음
- 커널 모드에서 실행되는 모듈들이 적어 신뢰성이 더 높아짐
- 하지만 유저 모드에서 서로 간의 message passing은 커널 모드를 통해야함 → 오버헤드
유닉스 운영체제 구조
Virtual Machine
- Hypervisor가 만들어낸 가상 공간(객체)
- Hypervisor : visualization으로 논리적 공간을 지원해주는 소프트웨어
- 시스템 환경 구성 및 Protection에 유용
728x90