-
[운영체제] 2. 컴퓨터 시스템의 동작 원리OS 2020. 3. 18. 01:29
1. 컴퓨터 시스템의 구조
- 컴퓨터 내부 장치와 외부 장치로 구성
- 내부 장치 : CPU, 메모리 등...
- 외부 장치 : 디스크, 키보드, 마우스, 모니터, 네트워크 장치 등...
- 컴퓨터 내부로 데이터가 들어오는 것은 입력(Input),
컴퓨터 외부 장치로 데이터가 나가는 것은 출력(Output) 이라고 한다.
- 키보드와 같은 외부 장치를 입출력(I/O) 장치라고도 부른다.
- 각 하드웨어 장치마다 컨트롤러가 존재한다.
- 대표적으로, 메모리를 제어하는 메모리 컨트롤러와 디스크를 제어하는 디스크 컨트롤러가 있다.
2. CPU와 I/O 연산
- 컴퓨터내에서 수행되는 연산은 메인 CPU가 담당하고, 입출력 장치들의 연산은 I/O 컨트롤러가 담당한다.
- 이때, I/O 컨트롤러와 메인 CPU는 다른 곳에서 발생하므로 동시 수행이 가능하다.
- 장치 컨트롤러에는 I/O과정에서의 데이터를 임시로 저장하기 위한 임시 저장소인 로컬 버퍼를 가지고 있다.
- 우선 로컬 버퍼에 데이터가 임시로 저장된 후 메모리에 전달하게 된다.
- 이 때, 장치에서 로컬 버퍼로 읽어오는 일은 컨트롤러가 담당한다.
- 데이터를 다 읽어오면 컨트롤러가 인터럽트를 발생시켜 CPU에 보고한다.
- 인터럽트란 컨트롤러들이 CPU의 서비스가 필요할 때 이를 통보하는 방법을 말한다.
- CPU 옆에 인터럽트 라인이 있어, CPU가 명령 하나를 수행할 때마다 인터럽트 라인 체크를 하고
인터럽트가 발생하였다면 다음 명령 수행 전에 인터럽트 처리를 한다.
3. 인터럽트의 일반적 기능
- OS 커널은 인터럽트가 들어왔을 때 해야 할 일을 미리 다 프로그래밍해서 커널 내에 보관하고 있다.
- 그 중 한 가지가 인터럽트 처리 루틴이다. 인터럽트 처리 루틴은 다양한 인터럽트에 대해 처리해야 할 업무들을 정의한다.
- 먼저 로컬 버퍼에 있는 내용을 프로그램 B가 사용할 수 있도록 메모리에 전달하고,
이제 B가 CPU를 할당받을 경우 다음 명령을 수행할 수 있음을 표시한다. - 한편, 인터럽트에는 하드웨어 인터럽트와 소프트웨어 인터럽트가 있다.
통상적으로 인터럽트라 하면 HW 인터럽트를 가리키고, SW 인터럽트는 트랩(Trap) 이라고 부른다. - SW 인터럽트의 예로는 예외 상황(Exception), 시스템 콜(System Call) 등이 있다.
- SW 인터럽트는 HW 인터럽트처럼 컨트롤러가 발생시키는 인터럽트가 아니라
프로그램 수행 도중 직접 CPU에 인터럽트 라인을 세팅하여 발생시킨다. - CPU 옆에 있는 인터럽트 라인에 신호를 보내어 인터럽트가 발생했음을 알려 주는 방식은 동일하다.
- 다만, 하드웨어 인터럽트는 컨트롤러 등 하드웨어 장치가 CPU의 인터럽트 라인을 세팅하는 반면
소프트웨어 인터럽트는 소프트웨어가 그 일을 수행한다는 점이 다르다. - 인터럽트가 발생하면 CPU는 하던 일을 멈추고 인터럽트를 처리하기 위한 루틴(OS 커널 내부 코드)에 들어가서 정의된 일을 찾게 된다.
- OS는 할 일을 쉽게 찾아가기 위해 인터럽트 벡터를 갖고 있다.
- 인터럽트 벡터란 인터럽트 종류마다 번호를 정해서, 번호에 따라 처리해야 할 코드가 위치한 부분을 포인터로 가리키고 있는 자료 구조이다.
- 실제 처리해야 할 내용은 인터럽트 서비스 루틴이라는 다른 곳에 정의된다.
4. 인터럽트 핸들링
- 인터럽트 핸들링이란 인터럽트가 발생한 경우에 처리해야 할 일의 절차를 의미한다.
- CPU 에서 명령이 수행될 때에는 CPU 내부에 있는 임시 기억 장치인 레지스터에 데이터를 읽어오거나 쓰는 작업을 수행하게 되는데, 인터럽트가 발생해 새로운 명령을 수행하면 기존의 레지스터 값들이 지워지게 되므로 레지스터 값 등 CPU 내의 하드웨어 상태를 저장해 두어야 한다.
- OS 커널 영역에는 현재 시스템 내에서 수행되는 프로그램들을 관리하기 위한 자료 구조인프로세스 제어 블록(PCB)을 두고 있다.
- PCB 중 일부분은 인터럽트 발생 시 프로그램의 어느 부분이 수행되던 중이었는지를 저장하기 위해 사용된다.
- 저장되는 내용으로는 현재 수행중이던 메모리 주소와 레지스터 값, HW 상태 등이 있다.
- 인터럽트 수행이 끝나면 저장된 값을 CPU 상에 다시 복원해 직전의 명령을 계속 수행할 수 있다.
- 프로그램 내부의 함수 호출 시 그 복귀 주소에 대한 정보는 각 프로그램의 주소 공간 중 스택 부분에 저장된다.
- 현재 수행중인 프로그램의 수가 n개라고 할 때, 커널 스택은 n만큼 독립적인 공간을 둔다.
- 즉, 인터럽트 처리 루틴으로 넘어와서 함수 호출이 이루어질 경우에는 각 프로세스별로 독자적인 커널 스택을 사용하게 된다.
- 프로그램 A가 수행중에 인터럽트가 발생하면 현재까지 수행된 지점을 프로세스 제어 블록(PCB) 에 저장하고,
인터럽트 처리 루틴으로 와서 커널 코드를 수행하게 되며, 이 때 이루어지는 함수 호출은 프로세스 A의 커널 스택을 사용하게 된다.
5. 입출력 구조
- 동기식 입출력
- 입출력 요청 후 입출력 작업이 완료된 후에야 CPU의 제어권이 그 프로그램에게 다시 넘어갈 수 있는 방식이다.
- 예를 들어, 프로그램이 디스크에서 어떠한 정보를 읽어오라는 요청을 했다고 할 때 디스크 입출력이 완료될 때까지 어느 정도의 시간이 걸린다. 이때, 동기식 입출력은 입출력이 진행되는 동안 다음 명령을 수행하지 않고 기다리게 된다.
- 그러다가 입출력이 완료되어 인터럽트를 통해 그 사실이 전달된 후에야 CPU의 제어권이 그 프로그램에게 넘어가 다음 명령을 수행할 수 있게 된다.
- 따라서, 동기식 입출력에서는 입출력 연산이 끝날 때까지 CPU는 아무일을 수행할 수 없다.
- 한편, CPU의 명령 수행 속도는 빠른 반면 입출력 연산은 상대적으로 속도가 느리다.
그럼에도 불구하고 입출력이 완료될 때까지 기다렸다가 CPU의 제어권을 넘기는 방식은 입출력이 완료될 때까지 CPU가 아무 일도 하지 못하기 때문에 자원을 낭비를 초래하게 된다.
< 예시 >
(1) 프로그램 A가 CPU를 할당받고 명령을 수행하다가 입출력 요청을 하게 되면 입출력 작업이 완료될 때까지 CPU의 낭비가 초래되므로 CPU를 프로그램 A에게서 선점해 다른 프로그램 B에게 할당하게 된다. (2) 그러면 프로그램 B가 CPU를 할당받아 명령을 수행하고, 프로그램 A의 입출력이 완료될 때까지 A에게는 CPU를 다시 할당하지 않는다. (3) 이는 입출력이 완료될 때까지 그 프로그램에 CPU를 할당하더라도 명령을 수행하지 못하기 때문이다. 이것을 "프로그램을 봉쇄 상태로 전환시킨다"고 말한다.
- 봉쇄 상태의 프로그램에게는 CPU를 할당하지 않고, CPU를 할당하면 곧바로 작업을 수행할 수 있는 프로그램들에게만 CPU를 할당한다.
- 선점하여 다른 프로그램에게 CPU를 양도하게 되므로 다수의 입출력 연산이 동시에 요청되거나 처리될 수 있다.
< 예시 >
(1) A라는 프로그램이 디스크에 원래 1이던 파일의 내용을 3으로 바꾸는 입출력 연산을 요청했다. (2) 그리고 입출력 연산을 수행중일 때 A에게서 CPU를 선점해 B에게 할당했다. (3) 한편, 프로그램 B가 CPU를 할당받고 수행중 일 때, 이 프로그램 역시 입출력 요청을 할 수 있다. (4) 공교롭게도 B가 요청한 입출력 연산이 A가 접근하려는 곳과 동일한 파일 내용을 1 증가시키는 내용이었다. (5) 이 경우 매 시점 두 개 이상의 입출력 연산을 수행할 수 있다면, 컨트롤러는 A와 B의 순서를 바꾸어 수행할 가능성이 있다. (6) 즉, A가 입출력을 요청한 다음 B가 요청했는데, 컨트롤러는 작업을 바꿔서 B의 요청을 먼저 처리할 수 있다. (7) 그렇게 되면 "1 -> 3 -> 4" 가 아닌, "1 -> 2 -> 3" 이 되어의도치 않은 결과를 초래한다.
- 따라서, 동기식 입출력에서는 입출력 요청의 동기화를 위해 장치별로 큐(queue)를 두어 요청한 순서대로 처리할 수 있도록 한다.
- 프로그램 A가 먼저 요청했으면 이를 먼저 큐에 넣고, 그 후에 발생한 B의 요청을 A의 요청 뒤에 삽입하여 동기화 문제를 해결한다.
- 연산 완료의 통보는 인터럽트를 통해서 수행하며, OS 커널은 인터럽트 처리 루틴으로 가서 입출력 연산을 끝낸 프로그램이 CPU를 할당 받을 수 있도록 그 프로그램을 봉쇄 상태로부터 해제시킨다.
동기식 입출력 요약
- 동기식 입출력을 요청한 프로그램은 입출력이 완료될 때까지 다음 명령을 수행할 수 없기에 CPU가 낭비된다.
- CPU의 효율적인 사용을 위해 입출력이 수행되는 동안 다른 프로그램에게 CPU를 양도하여동시에 다수의 입출력 연산이 가능해 진다.
- 다수의 프로그램이 동시에 입출력 연산을 요청하는 경우 동기성을 보장하기 위해 장치마다 큐를 두어 해결한다(동기성 보장).
< 동기식 입출력 과정 예 >
// 일반적으로 OS는 동기식 입출력 방식을 사용한다. (1) 프로그램 A가 실행중에 디스크에서 어떤 데이터를 읽어오는 명령을 만나면 프로그램 A는 시스템 콜을 통해 CPU에게 S/W 인터럽트를 발생시킨다. (2) 그러면 CPU는 지금까지 프로그램 A의 작업을 멈추고 현재 상태를 저장 후에, 인터럽트에 의해 처리해야 할 커널의 루틴으로 이동한다. (3) 처리 루틴으로 이동하면 CPU는 컨트롤러에게 입출력 연산을 요청한다. 그러면 컨트롤러는 A가 요청한 데이터를 디스크로부터 자신의 로컬 버퍼로 읽어온다. (4) 읽어오는 동안 "프로그램 A는 봉쇄 상태"가 되고 CPU를 선점당하게 되며, CPU는 다른 프로세스에게 할당해 계속 CPU가 일을 할 수 있도록 한다. (5) 원하는 정보가 로컬 버퍼로 다 들어오면 컨트롤러는 CPU에게 인터럽트를 발생시킨다. 이 때 발생하는 인터럽트는 H/W 인터럽트에 해당한다. (6) 프로그램 B를 수행중이던 CPU는 작업을 멈추고 현재 상태를 저장 후 인터럽트를 처리하게 된다. (7) 인터럽트 처리 루틴은 로컬 버퍼에 있는 A가 요청한 데이터를 A의 메모리 영역으로 읽어오고, A의 "봉쇄 상태를 해제"시킨다. 그러면 A는 다시 CPU를 기다리는 줄에 대기하게 된다. (8) 그 후 CPU는 원래 수행하던 프로그램 B의 지점으로 돌아가서 하던 업무를 계속 수행한다. (9) 프로그램 A는 CPU를 기다리는 줄에서 기다리다가 자신의 차례가 되면 CPU를 할당받고 입출력연산 이후의 작업을 수행하게 된다.
- 비동기식 입출력
- 비동기식 입출력은 입출력 연산을 요청한 후에 연산이 끝나기를 기다리는 것이 아니라 CPU의 제어권을 입출력 연산을 호출한 그 프로그램에게 곧바로 다시 부여하는 방식을 말한다.
- 데이터와 관련없이 수행할 수 있는 일을 먼저 수행하고, 읽어오는 데이터가 반드시 있어야 수행할 수 있는 일들은 입출력이 완료된 후에 수행하게 된다.
- 입출력 연산이 완료되면 동기식과 마찬가지로 인터럽트를 통해 이를 CPU에게 알려준다.
- 또한, 입출력 요청이 디스크를 읽는 것이 아닌 쓰는 요청이라면 쓰기 작업이 완료되기 전에도 다음 명령을 수행할 수 있으므로 비동기식 입출력이 사용될 수 있다.
6. DMA(Direct Memory Access)
- 모든 메모리 접근 연산이 CPU에 의해서만 이루어질 경우 주변 장치가 메모리 접근을 원할 때마다 인터럽트를 통해 CPU의 업무가 방해를 받게 되어 CPU 사용 효율성이 떨어지는 문제점이 발생하게 된다.
- 이러한 비효율성을 극복하기 위해 CPU 이외에 메모리 접근이 가능한 장치를 하나 더 두는 경우가 많은데,
이와 같은 장치를 DMA(Direct Memory Access)라고 부른다.
- DMA는 로컬 버퍼에서 메모리로 읽어오는 작업을 진행 후 CPU에게 인터럽트를 발생시켜 해당 작업의 완료를 알려준다.
- DMA는 바이트 단위가 아니라 블록이라는 큰 단위로 정보를 메모리로 읽어 온다.
- 로컬 버퍼에서 메모리로 읽어오는 작업을 CPU가 담당하는 것이 아니라, DMA가 대행하게 되어 CPU는 인터럽트 처리할 필요가 없어진다.
7. 저장 장치의 구조
- 주 기억 장치와 보조 기억 장치 2가지로 나뉜다.
- 주 기억 장치
- 휘발성/ 빠름/ 용량이 적음/ 비쌈
- ex) RAM
- 보조 기억 장치
- 비휘발성/ 느림/ 용량이 많음/ 저렴
- ex) 플래시메모리, CD, 디스크
- 용도 : (1) 비휘발성 파일 저장 (2) 메모리의 연장(swap)
- 파일 시스템용
- 전원 Off 시 유지해야할 정보가 있으면 그것을 파일 형태로 보조 기억 장치에 저장한다.
- 메모리는 휘발성이므로 비휘발성 매체인 디스크를 파일 시스템용으로 흔히 사용한다.
- 전원 Off 시 유지해야할 정보가 있으면 그것을 파일 형태로 보조 기억 장치에 저장한다.
- 메모리의 연장공간인 스왑 영역용
- OS는 프로그램 수행에 당장 필요한 부분만 메모리에 올려 놓고 나머지는 디스크의 스왑 영역에 내려놓게 된다.
- 디스크에 내려놓는 일을 스왑 아웃이라고 말한다.
- 스왑 아웃된 부분이 필요 시 다시 메모리 영역에 올린다.
- 스왑 영역은 프로그램이 실행 시 내용을 저장했다가 프로그램이 종료될 때 삭제하는 메모리의 연장 공간으로서의 역할을 담당한다.
- 파일 시스템처럼 비휘발성 용도로 사용되는 것과는 역할이 구분된다.
- OS는 프로그램 수행에 당장 필요한 부분만 메모리에 올려 놓고 나머지는 디스크의 스왑 영역에 내려놓게 된다.
8. 하드웨어의 보안
- 보통 OS는 다중 프로그래밍 환경에서 동작한다. 그러므로 각 프로그램이 다른 프로그램의 실행을 방해하거나 서로 충돌을 일으키는 문제를 막기 위해 HW의 각종 보안 기법이 필요하다.
- HW 보안을 유지하기 위해 OS는 기본적으로 두 가지 모드의 오퍼레이션을 지원한다.
- 커널 모드
- CPU 내부의 모드 비트가 0인 상태이다.
- OS가 CPU의 제어권을 갖고 OS 코드를 실행하는 모드로서, 모든 종류의 명령을 다 실행할 수 있다.
- 중요한 정보에 접근해 위험한 상황을 초래할 수 있는 연산은 커널 모드에서만 실행되도록 하여 보안성을 확보한다.
- 시스템의 보안과 관련된 명령들을 특권 명령이라하며, 모드 비트가 0일 때에만 수행가능하다.
즉, 특권 명령은 커널 모드에서 OS에 의해서만 수행이 가능하다.
- 사용자 모드
- CPU 내부의 모드 비트가 1인 상태이다.
- 일반 사용자 프로그램이 실행되며 제한적인 명령만을 수행할 수 있다.
- OS가 CPU를 점유해 자신의 코드를 수행하다 사용자 프로그램에게 CPU의 제어권을 넘길 때 모드 비트를 1로 세팅해 넘긴다.
- 사용자 프로그램이 수행되다 HW 접근 등 보안이 필요한 중요한 명령을 수행해야 할 경우에는 시스템 콜을 통해 OS에게 서비스를 대신해 줄 것을 요청하게 된다.
- 인터럽트가 발생할 때에는 모드 비트가 0으로 세팅되어 OS는 서비스에 필요한 모든 종류의 명령을 수행할 수 있다.
9. 메모리 보안
- 여러 프로그램이 메모리에 동시에 올라가서 실행되기 때문에 하나의 사용자 프로그램이 다른 사용자 프로그램이나 운영 체제가 위치한 메모리 영역을 침범할 수 있기 때문에 메모리 보안이 필요하다.
- 두 개의 레지스터를 사용해서 프로그램이 접근하려는 메모리 부분이 합법적인지를 체크함으로써 메모리 보호가 이루어진다.
- 이 때 사용되는 2가지의 레지스터는 기준 레지스터(base register)와 한계 레지스터(limit register)이다.
- 기준 레지스터는 어떤 프로그램이 수행되는 동안 합법적으로 접근할 수 있는 메모리 상의 가장 작은 주소를 보관한다.
- 한계 레지스터는 그 프로그램이 기준 레지스터 값부터 접근할 수 있는 메모리의 범위를 보관한다.
- 즉, 어떤 프로그램이 실제 메모리에 올라가 있는 부분의 시작 주소와 그 프로그램의 길이를 보관해 메모리 접근 연산이 있을 때마다 하드웨어적으로 현재 접근하려는 위치가 합법적인 범위인지를 체크한다.
- 사용자 프로그램은 기준 레지스터 부터 ~ (기준 레지스터 + 한계 레지스터 값) 사이의 주소 영역만 접근이 가능하며, 접근하려는 주소가 이 범위 안에 없으면 불법적인 메모리 접근이므로 예외 상황이라는 SW 인터럽트가 발생하게 된다.
예외 상황은 OS에게 SW 인터럽트를 발생시켜 CPU의 제어권을 이양시키고 OS는 그 프로그램을 강제 종료시킨다. - 단, 여기에서 기준 레지스터와 한계 레지스터를 통한 메모리 보호 기법은 하나의 프로그램이 메모리의 한 영역에 연속적으로 위치하는 경우에 대한 설명이다.
이 외에 하나의 프로그램이 메모리 여러 영역에 나뉘어 위치하는 페이징기법도 존재한다. - 메모리 접근 연산은 사용자 프로그램이 CPU를 가지고 있는 동안에 수행할 수 있는 연산이므로 특권 명령은 아니다.
다만, 사용자 프로그램이 메모리를 접근하기 전에 하드웨어적으로 그 접근이 합법적인지를 체크하여 메모리를 보호한다.
이것이 OS만 수행할 수 있는 입출력 연산과 메모리 접근 연산과의 차이점이라 할 수 있다. - 사용자 모드인 경우에는 기준 레지스터와 한계 레지스터를 사용해 메모리를 보호하게 되고,
커널 모드에서는 메모리에 무제한으로 접근이 가능하다. - 메모리 접근 명령은 특권 명령이 아니지만, 올바르지 않은 접근 시도로부터 메모리를 보호하기 위해서는 기준 레지스터와 한계 레지스터의 값을 세팅하는 연산은 특권 명령으로 규정해야 한다.
만약 프로그램이 자신의 기준 레지스터와 한계 레지스터 값을 직접 변경할 수 있다면 메모리에 무제한 접근이 가능하기 때문이다.
10. CPU 보호
- 일반적으로 CPU는 컴퓨터 내에 하나밖에 존재하지 않기 때문에 특정 프로그램이 CPU를 독점해 무한 반복문을 수행하는 등 부적절한 방법으로 독점한다면 다른 프로그램 및 OS가 CPU의 제어권을 획득할 수 있는 방법이 없게 된다.
- OS는 CPU가 하나의 프로그램에 의해 독점되는 것을 막기 위해 타이머(timer) 라는 HW를 사용한다.
- 타이머는 정해진 시간이 지나면 인터럽트를 발생시켜 지금 CPU를 할당받고 수행하는 프로그램으로부터 CPU를 선점하여,
OS나 다른 프로그램에게로 CPU의 제어권을 이양시키는 역할을 수행한다. - 타이머는 일정한 시간 단위로 세팅될 수 있으며, 타이머 값을 세팅하는 명령을 로드 타이머(load timer)라고 한다.
이는 특권 명령에 해당된다. - 타이머는 시분할 시스템에서 현재 시간을 계산하기 위해서도 널리 사용된다.
시분할 시스템이란 여러 프로그램이 CPU의 시간을 조금씩 나누어 사용하는 시스템을 의미한다.
11. 시스템 콜을 이용한 입출력 수행
- 입출력 명령은 특권 명령에 해당하므로 사용자 프로그램이 직접 수행할 수 없다.
- 사용자 프로그램은 직접 입출력을 수행하는 대신 OS에게 시스템 콜이라는 서비스 대행 요청을 하여 입출력을 수행하게 된다.
- 시스템 콜은 일종이 SW 인터럽트로서 사용자 프로그램이 시스템 콜을 할 경우 트랩(trap)이 발생해 CPU에 대한 제어권이 OS로 넘어가게 된다.
- 그러면 OS는 해당 시스템 콜을 처리하기 위한 루틴으로 가서 정의된 명령을 수행하게 된다.
'OS' 카테고리의 다른 글
[운영체제] 1.운영 체제 개요 (0) 2020.02.20 댓글