[운영체제] 시스템 구조 & 프로그램 실행
01. 컴퓨터 시스템 구조
- CPU
- 중앙 처리 장치(Central processing unit)
- 컴퓨터 시스템을 통제하고, 프로그램의 연산을 실행하고 처리하는 컴퓨터 시스템의 핵심 장치
- 산술 논리 장치(ALU) : 연산 수행
- 컨트롤 장치(CU) : 제어 명령 전달
- Register : 결과 값을 일시적으로 기억하는 장치
- Memory
- 주 기억 장치
- 용량이 매우 작은 CPU의 Register을 대신해, 정보를 저장해 두었다가 필요할 때 읽어 들여 이용할 수 있는 장치
- 컴퓨터가 켜지면 운영체제, 사용자 프로그램들이 해당 Memory에 올라가게 되고 → CPU는 Memory에서 프로그램들의 명령어를 읽어와 작업 수행
- ROM, RAM 등
- I/O Device
- 입 출력 장치
- 사용자가 원하는 문자나 그림의 데이터를 컴퓨터로 전달하거나 출력하는 장치
- 입력장치 : 키보드, 마우스 등
- 출력장치 : 모니터, 프린터 등
01-1. 컴퓨터 시스템 흐름
- 컴퓨터의 전원이 들어오면, 메인 메모리에 운영체제가 올라간다. (부트로더)
→ 시스템이 돌아가기 위한 핵심적인 부분 먼저 올라감 (커널)
→ 모든 코드가 올라가게 되면 자원 낭비가 심하다. - CPU는 운영체제의 프로그램들을 읽어 운영체제를 실행
- 다른 프로그램 실행
→ 마찬가지로 메인 메모리에 코드가 올라가게 된다.
→ 이때, CPU는 메인 메모리의 명령어 주소를 레지스터(PC 레지스터)에 저장 - 각 프로그램들이 I/O 디바이스 사용이 필요할 경우
→ 운영체제에게 요청 (시스템 콜)
→ 프로그램들이 직접 I/O 디바이스를 제어하지 않는 이유는 보안 때문의 이유가 가장 크다. - 프로그램들의 요청을 받은 운영체제는 I/O 디바이스의 컨트롤러에게 데이터 입출력 처리 요청
- 해당 컨트롤러들은 입출력을 받게 되면 Interrupt를 발생시켜 CPU에게 작업이 완료되었다고 알림.
- CPU는 I/O 디바이스의 버퍼에 가서 데이터를 읽어와 메인 메모리에 올림
01-2. CPU와 I/O 연산
- 컴퓨터에 대한 연산은? CPU 가 처리
- I/O 디바이스들에 대한 연산은? 각각의 디바이스 컨트롤러들이 처리 → CPU 에게 인터럽트를 발생시켜 보고하는 형식으로 처리
- 각각의 컨트롤러로부터 입,출력되는 데이터들은? 로컬 버퍼에서 관리
01-2-1. Device Controller
- 각각의 디바이스들을 I/O 연산, 제어관리를 하는 역할
- 각각의 디바이스들의 CPU 역할
- Device Driver : 운영체제가 각각의 디바이스를 접근하게 하기 위한 인터페이스 역할을 하는 소프트웨어
- 펌웨어 : 디바이스가 동작하기 위한 소프트웨어
01-2-2. Buffer
- 각각의 디바이스 컨트롤러들이 명령을 내려 디바이스의 데이터를 읽어오거나 출력할 때 데이터를 저장하는 공간
- 각각의 디바이스들의 램(메인 메모리) 역할
02. Interrupt
- I/O 디바이스들이 데이터를 입력할때까지 CPU가 기다리는 것이 아닌, 자신의 일을 계속 처리하고 있게 된다.
이때 I/O 디바이스들에게 입,출력이 이루어지면 각각의 디바이스 컨트롤러가 인터럽트(일련의 신호)를 발생시켜 CPU에게 알려준다.
인터럽트 왜 할까요? >
입출력 연산이 CPU 명령 수행속도보다 현저히 느리기 때문.
→ CPU는 입출력 처리를 기다리며 다른 일을 한다.
→ 따라서 I/O 컨트롤러가 작업을 마칠 경우 CPU에게 직접 알려줘 처리가 필요함을 알리게 된다.
- 기본적으로 운영체제에는 인터럽트가 발생했을 때 각각의 인터럽트에 대한 처리가 운영체제 안에 코드로 작성되어 저장되어 있음.
- 인터럽트 처리 루틴 : 다양한 인터럽트에 대한 각각의 처리해야 할 업무들을 정의해놓은 것
02-1. 용어 정리
- 인터럽트 백터
→ 인터럽트 종류마다 번호를 정해서, 번호에 따라 처리해야 할 코드가 위치한 부분을 포인터로 가리키고 있는 자료 구조 - 시스템 콜
→ 응용 프로그램이 운영체제의 서비스를 받기 위해 커널함수를 호출하는 것. - 영역
- 스택 영역 : 실행중인 함수에서 다른 함수를 호출한 경우, 호출된 함수의 종료 후 원래 실행 함수로 돌아오기 위해 복귀 주소 저장하는 위치
- 데이터 영역 : 전역변수 등 프로그램이 사용하는 각종 데이터가 저장되는 공간
- 코드 영역 : 프로그래머가 작성한 코드가 기계어 명령 형태로 저장되는 영역
- PCB
→ 프로세스 제어 블록 (Process Control Block)
→ 현재 시스템 내에서 수행되는 프로그램들을 관리하기 위한 자료구조
→ 인터럽트가 발생했을 때, 어느부분이 수행되던 중이었는지 저장하는 자료구조로 사용하기도 한다.
03. 입출력 구조
03-1. 동기식 입출력 (Synchronous I/O)
I/O 요청 후 입출력 작업이 완료 된 후에야 CPU의 제어권이 사용자 프로그램에게 다시 넘어갈 수 있는 방식
- 입출력 연산이 끝날 때 까지 CPU는 아무 일도 수행할 수 없다.
- 일반적으로 프로그램이 입출력을 수행중인 경우, CPU를 다른 프로그램에게 이양해 쉬지 않고 일할 수 있도록 관리한다.
→ 그 입출력을 요청했던 사용자 프로그램은“봉쇄 상태(Blocked State)”
로 전환한다.
→ 봉쇄 상태의 프로그램은 CPU를 할당하더라도 명령 수행을 못한다.
문제 발생 가능
입출력이 수행중일 때, 다른 프로그램에게 CPU를 양도하게 되므로 다수의 입출력 연산이 동시에 요청되거나 처리될 수 있다.
A, B 프로그램이 동시에 하나의 파일에 접근하려 한다.
→ 개발자는 A라는 프로그램이 먼저 파일을 수정할 것을 예상하고 개발했지만 컨트롤러는 이것의 순서를 보장하지 않는다.
이를 해결하기 위해서는 I/O 장치 별도로 큐(FIFO)를 두어 요청한 순서대로 처리할 수 있도록 한다.
구현 방법 1
- I/O가 끝날 때까지 CPU를 낭비시킨다.
- 매 시점 하나의 I/O만 일어날 수 있도록 한다.
구현 방법 2
- I/O가 완료될 때 까지 해당 프로그램에게서 CPU를 빼앗는다.
- I/O 처리를 기다리는 줄에 그 프로그램을 줄세운다
- 다른 프로그램에게 CPU를 준다.
03-2. 비동기식 입출력 (Asynchronous I/O)
I/O 요청 후 연산이 끝나기를 기다리는 동기식 입출력과 달리, CPU의 제어권을 입출력 연산을 호출한 사용자 프로그램에게 곧바로 다시 부여하는 방식.
- 입출력 결과에 상관없이 수행할 수 있는 일들을 먼저 처리하고, 입출력의 결과가 필요한 프로그램들은 입출력이 완료된 후에 작업 수행
03-3. 동기식 입출력과 비동기식 입출력
- 동기식 입출력은 응답이 돌아올 때 까지 입출력을 요청한 프로그램은 봉쇄 상태가 되고,
인터럽트
가 발생 해야 봉쇄 상태가 풀리고 CPU를 할당받을 수 있는 상태가 된다. - 비동기식 입출력은 입출력을 요청한 프로세스에게 바로 주어지며, 입출력 연산이 완료되는 것과 무관하게 처리 가능한 작업부터 처리한다.
처리가 완료되었음은 동기식과 동일하게
인터럽트
로 CPU에게 알려준다.
예시
프로그램 A
가 실행중에 디스크에서 데이터를 읽어오는 명령을 만나게 된다 → 시스템 콜 발생- CPU는 지금까지
프로그램 A
의 작업을 멈추고 현재 수행상태 저장 후, 인터럽트에 의해 처리 되어야 할 커널 루틴으로 이동 - 처리 루틴으로 이동하게 되면 CPU는 디바이스 컨트롤러에게 입출력 연산 요청
- 디바이스 컨트롤러는
A
가 요청한 데이터를 디스크로부터 읽어와 로컬 버퍼에 저장 - 읽어오는 동안
A
는 CPU를B 프로그램
에 넘겨 줌 (A 프로그램
은 봉쇄 상태가 되며, CPU 명령을 수행하려 해도 못함.) - 디바이스 컨트롤러가 작업이 끝나면 하드웨어 인터럽트 발생
- 인터럽트가 발생되면
B 프로그램
작업을 미뤄두고 인터럽트 처리 루틴에 가서 인터럽트 처리 - 인터럽트 처리 루틴은 컨트롤러에서 데이터를 읽어와
A 프로그램
에 올리게 되고,A 프로그램
은 다시 CPU 대기 줄을 서서 기다린다. - CPU는 다시
B 프로그램
에 돌아가 작업을 수행하게 된다.
일반적으로는 동기식 입출력을 사용하며, 운영체제는 장치별로 입출력 처리를 기다리는 프로세스를 줄세워 관리한다.
03-4. DMA(Direct Memory Access)
일반적으로 I/O 디바이스들은 메인 메모리에 직접 접근할 수 없고, 인터럽트를 발생시켜 CPU가 I/O 디바이스들의 데이터를 읽어 메인 메모리 프로그램에 올린다.
→ 하지만 CPU는 명령어를 처리하는 것 외에도 항상 각각의 I/O 디바이스들 인터럽트 처리도 해야 한다.
→ 기존의 CPU 작업들을 방해하게 된다.
이러한 비 효율성을 극복하기 위해 CPU 대신 I/O 디바이스들의 인터럽트를 처리할 컨트롤러를 하나 더 둔다
→ DMA
- 빠른 입출력 장치를 메모리에 가까운 속도로 처리하기 위해 사용
- CPU의 중재 없이 디바이스 컨트롤러가 디바이스의 버퍼 저장 공간의 내용을 메모리에 block 단위로 직접 전송
- 바이트 단위가 아니라 block 단위로 인터럽트를 발생시킴.
- 마지막에 CPU에게 인터럽트 한번 발생
04. 저장 장치 구조
04-1. 주기억장치 = 메모리
- 휘발성(Volatile)
- 전원이 나가면 저장되었던 내용이 모두 사라진다
- 속도가 빠르다.
- 크기가 한정되어있고 가격이 비싸다.
04-2. 보조기억장치
- 비휘발성(Nonvolatile)
- 전원이 나가도 저장된 내용을 모두 기억할 수 있다.
- 마그네틱 디스크를 흔히 사용한다.
- 속도와 크기는 주기억장치보다 느리고 작지만, 가격은 비교적 싸다.
- 파일 시스템
- 전원이 나가도 유지해야 할 정보가 있으면, 파일 형태로 보조기억장치에 저장
- 스왑 영역 (디스크에서 지정 가능)
- 다수의 프로그램이 메인 메모리에 올라가 동시에 수행될경우, 메모리 공간이 부족한 경우가 발생
- 한번에 메인 메모리에 올려놓는 것이 아닌 프로그램이 돌아가기 위한 핵심적인 부분만 메인 메모리에 올려 놓고, 나머지는 ‘스왑 영역’에 두고 필요할때마다 메인 메모리로 불러온다.
- 캐시 메모리 (레지스터와 메인 메모리 사이에 존재)
- 캐싱 기법을 사용해 적은 용량의 캐시 메모리를 사용해서도 메인 메모리와 같이 큰 용량을 가진 것처럼 효율적으로 관리 가능
캐싱 기법(Caching) >
상대적으로 느린 저장장치에 있는 내용 중 당장 사용되거나 빈번히 사용될 정보를 빠른 저장장치에 선별적으로 저장하여 두 저장장치의 속도를 완충시키는 기법
→ Copying information into faster storage system
04-3. 메모리 보안
여러 프로그램이 메모리에 동시에 올라가서 실행되기 때문에 하나의 사용자 프로그램이 다른 사용자 프로그램이나 운영체제가 위치한 메모리 영역 침범 가능
→ 두개의 레지스터를 이용해 현재 접근하려는 메모리가 합법적인지 체크함으로써 메모리 보호
- 기준 레지스터 (base register)
- 실행되고 있는 프로그램이 합법적으로 접근이 시작되는 메모리 주소를 보관
- 한계 레지스터 (limit register)
- 해당 프로그램이 기준 레지스터로부터 접근할 수 있는 범위 지정
사용자 프로그램은 이 두개의 값의 범위만 접근할 수 있으며 이 범위를 벗어난 접근을 하게 되면 예외 인터럽트가 발생한다
→ Exception interrupt
05. 하드웨어의 보안
일반적으로 사용하는 운영체제는 여러 프로그램이 동시에 실행될 수 있는 다중 프로그래밍 환경에서 실행
→ 각 프로그램들이 다른 프로그램의 실행을 방해하거나, 프로그램 간 충돌 발생 가능하므로 문제 해결을 위한 각종 보안 기법 필요
하드웨어의 보안을 유지하기 위해 운영체제는 두가지 모두의 운영을 지원함
- 커널 모드
- 운영체제가 CPU의 제어권을 가지고 운영체제 코드를 실행하는 모드
- 모든 종류의 명령을 다 실행할 수 있음
- Mode bit 0
- 사용자 모드
- 일반 사용자 프로그램이 실행
- 제한적인 명령 수행 가능 → 보안과 관련된 명령, 특권 명령어는 사용 불가
- Mode bit 1
여기서 잠깐 Mode bit >
사용자(user)와 OS 는 시스템 자원을 공유합니다. 때문에 사용자가 메모리 내의 OS 영역을 침투해서 고의적으로 시스템을 망가트릴 수 있습니다. → OS 의 안전과 적절한 동작을 위해서 보호 장치가 필요 : Mode bit → CPU에서 지금 실행되는 프로그램이 프로그램인지 운영체제인지 구분해주는 역할
- 사용자 모드 (user mode): 제어권이 사용자에게 있고, 사용자 수준의 코드가 수행
- 커널 모드(kernel mode): 제어권이 OS에게 있고, OS 코드가 수행
→ 하드웨어에 Mode bit을 추가해서 각 모드를 표시합니다. → **사용자 모드는 1, 커널 모드는 0 - 특징
- UserMode에서는 특권 명령어(kernel에 악영향을 끼칠 수 있는 명령어)가 수행될 수 없음
- Interrupt나 Exception 발생 시 커널 모드
→ 이중 연산 모드(하드웨어에서 Mode bit로 제공)로 OS 동작의 안정성을 보장할 수 있다.
CPU는 보안과 관련된 명령을 수행하기 전에 Mode bit를 조사해 0으로 세팅된 경우에만 명령 수행
보통 Mode bit가 0이 되는 경우에는 운영체제에게 권한이 넘어가거나 인터럽트가 발생해 인터럽트 루틴을 처리해야 할 경우이다.
06. CPU의 보안
일반적으로 CPU는 컴퓨터 시스템 내에 하나씩 존재
따라서 특정 프로그램이 CPU를 독점해 무한 반복문을 수행하게 되면 다른 프로그램들 및 운영체제가 CPU를 획득하지 못한다
→ 타이머 사용
- 타이머
→ 특정 프로그램이 무한 루프에 빠져 CPU를 독정하는 것을 막기 위해 존재
→ 특정 프로그램이 CPU 할당 시간을 초과할 시 timer는 인터럽트를 발생시켜 CPU의 권한을 다시 OS에 이양시킨다.
→ 타이머 값이 0이 되면 인터럽트 발생
07. 시스템 콜을 이용한 입출력 수행
사용자 프로그램이 I/O 디바이스 등을 통해 데이터 입출력 불가
→ 운영체제를 통해서 해야 한다.
운영체제에는 I/O 디바이스들의 데이터 입출력 명령이 코드로 구현되어 있다.
따라서 보통의 사용자 프로그램들은 인터럽트를 발생시켜 I/O 디바이스 등의 입출력을 하는데 이를 가리켜 시스템 콜이라 한다.
- 소프트웨어적인 인터럽트로서 사용자 프로그램이 시스템 콜을 할 경우, 트랩이 발생해 CPU에 대한 제어권이 운영체제로 넘어간다. (kernel mode, 0)
- 운영체제는 해당하는 시스템 콜을 처리하기 위해 인터럽트 처리 루틴으로 넘어가 시스템 콜에 맞는 루틴을 처리한다.
- 프로세스에서 시스템콜로 커널의 코드를 실행하더라도 이를 ‘프로세스의 실행 상태’라고 한다
- 첫 시작은 프로세스에서 시작되었기 때문
- ‘프로세스가 커널 모드에서 실행 중’ 으로 출력
08. 사용자 프로그램이 사용하는 함수
- 사용자 정의 함수
- 사용자가 만든 함수
- 라이브러리 함수
- 자신의 프로그램에서 정의한 것이 아닌, 누군가가 정의해놓은 함수
- 커널 함수
- 운영체제 커널 코드에 정의된 함수 (운영체제 프로그램의 함수)
- 이를 호출하는 것이 시스템 콜이다.
- 커널 함수 = 시스템 콜 함수 + 인터럽트 처리 함수
사용자 정의함수와 라이브러리 함수는 해당 프로그램의 코드 영역에 기계어 명령 상태로 저장한다.
- 해당 프로세서의 주소 공간에 포함된다
- 함수 호출 시에도 자신의 주소 공간에 있는 스택을 사용
08-1. 프로그램의 실행
timer, I/O 작업은 배재한 그림이다. 출처 : 운영체제 반효경 교수님
참조
https://wan-blog.tistory.com/32
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=4717010&logNo=60210905703
댓글남기기