디스크 등 내부를 컨트롤하는 것은 device controller들이다. 이 또한 작은 CPU이다. 그것들만의 작은 메모리 공간이 필요한데, 그것이 local buffer이다.
지금 CPU에서 실행되는 것이 사용자 프로그램인지, 운영체제인지 구분해주는 것이 mode bit이다.
CPU는, 입력 출력을 해야할 때 device controller에게 시킨다. 그것을 하는 동안에는 본인이 할 수 있는 일(Memory에 접근하여 할 수 있는 일 등)을 하게 된다. CPU는 빠르면서 쉬지 않고 일한다. 다른 오래 걸리는 일들은 device controller에게 시킨다.
timer(타임 쉐어링 구현), for loop 등으로 오래 도는 등, 특정 프로그램이 CPU를 오랫동안 점유하는 것을 방지한다. timer에 일정 값을 셋팅한 후 프로그램에 CPU를 넘겨주게 된다. 보통 수십ms 정도 세팅해서 CPU를 넘겨준다. 그러면 CPU는 프로그램의 인스트럭션을 실행한다. 하나의 인스트럭션이 끝나고 나면 Interrupt line을 확인한다. 즉 하나의 인스트럭션이 끝날 때 마다 인터럽트 라인을 확인하여 인터럽트가 발생했는지 확인한다.
timer가 인터럽트를 걸어왔으면 CPU는 하던 일을 멈추고, CPU의 제어권을 사용자 프로그램(A)으로부터 운영체제에게 넘어가게 된다. 그러면 또 다음 프로그램(B)에게, timer 세팅 후 CPU의 제어권을 넘겨주게 된다.
사용자 프로그램(A)은, 본인이 직접 I/O 장치에 접근할 수 없고, 보안 등의 이유로 운영체제를 거쳐할 수 있게 구현되어 있다. 사용자 프로그램이 화면에 무언가 출력하거나 입력하는 작업이 필요하다면 스스로 본인의 CPU 제어권을 OS에게 넘겨주고, OS가 해당되는 작업(출력, 입력 등)을 device controller에게 시킨다. 이 작업이 오래 걸리니 A에게 넘겨주는 것이 아니라 다른 프로그램(B)에게 넘겨준다. device controller에게 시킨 작업이 끝나 local buffer에 들어왔다면, device controller가 CPU에게 인터럽트를 걸게 된다. 이렇게 인터럽트가 걸리면, 어떤 프로그램(B)이 CPU에서 실행되고 있었겠지만 인터럽트가 들어오니 CPU 제어권이 OS에게 넘어가게 된다. 그렇게 OS가 왜 인터럽트가 들어왔는지 확인하여, A가 요청한 작업의 결과를 확인하게 된다. 그러면 local buffer의 값을 A의 메모리 공간에 복사해주고 다시 B에게 CPU 제어권을 준다.(그 B에게 할당된 시간이 남아있었으면, by timer) B의 할당된 시간이 끝나면 A가 다시 CPU 제어권을 얻게 된다.
Mode bit :
보안을 목적으로 인스트럭션 집합을 나누어 놓았다.
유저(사용자) 모드 : 사용자 프로그램을 실행 중이면 mode bit이 1
제한된 인스트럭션만 CPU에서 실행할 수 있다. 보안 상의 목적이 있다.
B가 A 혹은 OS의 메모리 공간을 접근하려면 막을 수 있다.
커널 모드 : OS 코드를 수행 중이면 mode bit이 0
- 무슨 일이든 다 할 수 있게 정의되어 있다. 메모리 접근 뿐만 아니라 I/O 디바이스 접근하는 등.
각각의 디바이스, 메모리까지도 전담하는 컨트롤러가 붙어 있다.
DMA, Direct Memory Access : 키보드 입력할 때를 생각해보면, 1바이트 1바이트 씩 입력할 때마다 인터럽트가 일어나게 되는데, 이렇게 작고 반복적으로 CPU가 local buffer의 내용을 메모리로 복사해오는 동작은 오버헤드가 너무 크다. 이러한 동작을 DMA controller가 대신 해준다. DMA controller가 local buffer의 내용을 메모리로 직접 복사해주고, 완료되면 CPU에게 보고한다. 그러면 CPU는 계속해서 본인의 일(주로 메모리에 접근하는 일)을 할 수 있게 된다. 즉, CPU가 인터럽트 당하는 일이 줄어든다.
이렇듯 CPU의 중재 없이 device controller(DMA)가 device의 buffer storage의 내용을 메모리에 block 단위로 직접 전송한다.
이렇듯 device controller(장치 제어기)는 작 장치를 통제하는 일종의 작은 CPU이며 하드웨어이다.
device driver(장치 구동기) : 각 디바이스 별 인터페이스가 있는데 그러한 것을 구현해주는 소프트웨어이다. OS 코드 중, 각 장치별 처리 루틴이다.
2-2강, System Structure & Program Execution 2
컴퓨터는 다른 말로, host라고 하기도 한다.
PC라는 program counter 레지스터가 메모리에서 한 주소를 가르키고 있다. 4바이트의 인스트럭션을 실행하고 나면 주소가 4 증가하여 다음 위치의 인스트럭션을 실행한다. jump를 만나면 멀리 있는 인스트럭션을 실행하기도 한다.
입출력 요청을 해놓고, 결과를 받고 다음 인스트럭션을 실행하면 동기식 입출력(프로세스 입장)
시간적으로 서로를 맞추는 것이 sync이다.
I/O 장치에 요청을 하고 결과가 나올 때까지 기다리다가 직접 결과를 가지고 오는 것이다.
즉, I/O 요청 후, 입출력 작업이 완료된 후에야, 제어권이 사용자 프로그램에게 넘어간다.
구현 방법 1
요청한 I/O 작업이 끝날 때까지 기다리고 있으면, 즉 해당 프로세스가 CPU를 계속 가지고 있는 것.
I/O 작업이 끝날 때까지 CPU를 낭비(끝났는지 계속 체크함)시킨다.
매 시점, 하나의 I/O만 일어날 수 있다.
구현 방법 2(운영체제 강의에서 주로 얘기되는 입출력 구현 방법)
당장 일을 할 수 있는 프로세스한테 CPU를 넘겨주는 것
좀 더 효율적이다.
비동기식 입출력(asynchronous I/O)
입출력 요청을 해놓고, 바로 인스트럭션을 실행하면 비동기식 입출력(프로세스 입장)
I/O 장치에 요청을 하고 결과가 나올 때까지 기다리는 것이 아니라 다른 일을 하다가 결과가 나오면 그 때 결과를 가지고 온다.
즉, I/O가 시작된 후 입출력 작업이 끝나기를 기다리지 않고, 제어권이 사용자 프로그램에게 즉시 넘어간다.
입출력 I/O 수행
시스템 콜 : 운영체제(커널)에게 부탁하는 것. 사용자 프로그램이 운영체제의 서비스를 받기 위해, 커널 함수를 호출하는 것이다.
인터럽트
인터럽트(하드웨어 인터럽트)
트랩(소프트웨어 인터럽트)
Exception : 프로그램이 오류를 범한 경우 ex. zerodivisionerror(0으로 나누려는 연산)
System call : 프로그램이 커널 함수를 호출하는 경우.
사용자 프로그램이 입출력 등의 함수를 사용하기 위해 운영체제에게 I/O를 요청한다.(트랩을 거는 경우)
사용자 프로그램이 필요에 의해 I/O를 요청하기 위해서는 트랩을, 그 작업이 완료되면 인터럽트를 CPU에게 발생시킨다.
인터럽트 벡터 : 해당 인터럽트의 처리 루틴 주소를 가지고 있다. 인터럽트의 종류가 다양하다. 키보드 컨트롤러, 타이머 등이 걸어주는 인터럽트가 있다. 키보드 인터럽트가 들어왔으면 키보드 로컬 버퍼의 내용을 메모리로 복사해야 하고, 프로세스한테는 CPU를 얻을 수 있음을 알려야 한다. 각 인터럽트마다 해야할 일들이 다르다. 각 인터럽트마다 무슨 일을 해야하는지 운영체제 코드에 다 정의가 되어 있다. 이를 인터럽트마다 처리해야 할 루틴들이 있다.
즉, 이러한 루틴들이 존재하는 코드의 주소를 표시해주고 있는데(인터럽트마다 어디 있는 루틴, 즉 함수를 실행해야 하는지) 그 주소를 정의해놓은 테이블들을 인터럽트 벡터라고 한다.
> ### 저장장치 계층 구조
위로 갈수록 빠르고 비싸다. Primary 영역은 바이트 단위라서 CPU가 바로 접근이 가능하다. 즉 바로 실행이 가능한 메모리 계층이다.
Secondary 영역은 섹터 단위라서 CPU 접근이 바로는 불가능하다.
프로그램의 실행 (메모리 load)
프로그램을 실행시키게 되면, 그 프로그램만의 독자적인 address space가 형성된다.(메모리 주소 공간)
stack : 함수를 호출하거나 리턴할 때와 같이 데이터를 쌓았다가 리턴할 때 stack에 담긴다.
data : 전역변수
code : 그 프로그램을 실행할 코드
이렇게 프로그램들은 독자적인 주소 공간을 가지고 있다. 이를 물리적인 메모리에 올려 실행시키게 된다.
커널은 처음 부팅하고 나면 물리적 메모리에 항상 상주해 있다.
하지만 사용자 프로그램은 실행시키면 주소 공간이 생겼다가, 종료 시 주소 공간이 사라진다.
이 사용자 프로그램을 실행시켰을 때 물리적 메모리에 모두 올려놓는 것이 아니라 당장 필요한 부분만 물리적 메모리에 올려놓게 된다. 물리적 메모리 안에서도 당장 필요가 없어지면 디스크 중 swap area에 내려 놓게 된다.
각 프로그램마다, 독자적으로 가지고 있는 주소 공간을 Virtual Memory라고 한다.
File system은 전원이 나가도 사라지면 안된다.(비휘발성)
Swap area는 전원이 나가면 프로그램이 종료되므로 의미가 없어지므로 사라진다.
커널 주소 공간의 내용
code
시스템 콜 및 인터럽트(각 인터럽트마다 무슨 일을 해야 할지)를 처리하는 코드
data
하드웨어를 직접 관리하기 위한 자료 구조들
프로세스 또한 관리하기 때문에, 각 프로세스가 CPU를 얼마나 쓰고 있는지, 누구한테 메모리를 다음에 얼마나 줘야 할지 등 프로그램들을 관리하기 위한 자료 구조들도 있다. 프로세스마다 PCB(process controll block)가 하나씩 만들어진다.
stack
운영체제도 함수 구조로 짜여져 있기 때문에 함수를 스택에 쌓고 리턴 받기 위해 stack 영역이 있다.
어떤 프로그램이 시스템 콜 등을 사용하고 있는지 알고 그 프로그램에 결과를 리턴하기 위해, stack에는 프로세스 마다 스택이 따로 따로 있다.