본 포스트는 공룡책이라 불리는 Abraham Silberschatz, Peter B. Galvin, Greg Gagne의 『Operating System Concept 10th』 을 바탕으로 작성하였습니다.
Ch 2. Operating System Structures
운영체제에 대해 살펴보기 위한 몇 가지 좋은 관점이 있다.
첫 번째, 운영체제가 제공하는 서비스에 초점을 맞추는 것
두 번째, 운영체제가 사용자와 프로그래머에게 제공하는 인터페이스에 초점을 맞추는 것
세 번째, 시스템의 구성요소와 그들의 상호 연결에 초점을 맞추는 것이다.
이번 장에서는 운영체제의 세 가지 측면을 모두 살펴본다. 운영체제가 제공하는 서비스는 무엇이며, 이 서비스는 어떤 방식으로 제공되는지, 이 서비스들이 어떻게 디버깅 되며, 이러한 시스템을 설계하기 위해서는 어떤 다양한 방법들이 사용되는지 공부한다.
2.1 운영체제 서비스 (Operating System Services)
운영체제는 프로그램 실행 환경을 제공한다.
더 정확히 말하면, 운영체제는 프로그램과 그 프로그램의 사용자에게 특정 서비스를 제공한다.
이러한 서비스들은 프로그래머가 프로그래밍 작업을 더 쉽게 수행할 수 있도록 한다.
서비스들을 구체적으로 살펴보자.
1) 사용자 인터페이스
거의 모든 운영체제는 사용자 인터페이스(UI)를 제공한다.
가장 일반적으로는 그래픽 사용자 인터페이스(GUI)가 사용되는데, 여기서 인터페이스는 윈도우 시스템으로 I/O를 지시하고, 화면을 선택하는 등 포인팅 장치인 마우스와 텍스트를 입력할 키보드를 가지고 있다.
또 다른 옵션은 명령어 라인 인터페이스(CLI)이다. 이 인터페이스는 명령을 사용하며 이를 입력할 방법이 사용된다.
2) 프로그램 수행
시스템은 프로그램을 메모리에 적재해 실행할 수 있어야 한다.
또, 프로그램은 정상적이든 비정상적이든 실행을 끝낼 수 있어야 한다.
3) 입출력 연산
수행 중인 프로그램은 입출력을 요구할 수 있다.
보통 이런 입출력 장치는 효율과 보안을 위해 사용자들이 제어할 수 없다. 따라서 운영체제가 입출력 수행의 수단을 제공해야 한다.
4) 파일 시스템 조작
파일 시스템은 특히 중요한 분야이다. 프로그램은 파일을 읽고 쓸 필요가 있을 뿐 아니라 생성, 삭제, 검색 등이 필요하다.
게다가 몇몇 프로그램은 특정 파일의 접근을 허용, 거부할 수 있어야 한다.
운영체제는 이런 특성을 제공하기 위하여 다양한 파일 시스템을 제공한다.
5) 통신
한 프로세스가 다른 프로세스와 정보를 교환해야 할 필요가 있는 여러 상황이 있다.
통신은 공유 메모리를 통해서 구현될 수 있고, 메시지 전달(message passing) 기법을 사용하여 구현될 수 있는데, 후자의 경우 정보의 패킷들이 운영체제에 의해 프로세스들 사이를 이동한다.
6) 오류 탐지
운영체제는 모든 가능한 오류를 항상 의식하고 있어야 한다.
오류는 CPU, 메모리 하드웨어, 입출력 장치(패리티 오류, 네트워크 접속 실패), 사용자 프로그램(연산 오버플로) 등에서 일어날 수 있다.
운영체제는 이러한 각 오류에 대한 적절한 조치를 취할 수 있어야 한다.
7) 자원 할당
다수의 프로세스나 작업이 동시에 실행될 때, 그들 각각에 자원을 할당해 주어야 한다.
운영체제는 여러 가지 다른 종류의 자원을 관리하는데, 예를 들어 CPU를 최대한 효율적으로 이용하기 위해 운영체제는 CPU 스케줄링 루틴이 CPU의 속도, 반드시 실행해야 할 프로세스들, CPU의 처리 코어의 개수 등의 요인들을 고려하도록 해야 한다.
8) 기록 작성(logging)
사용자는 어떤 프로그램이 어떤 종류의 컴퓨터 자원을 얼마나 많이 사용하는 지를 추적할 수 있길 원한다.
윈도우의 경우, (Ctrl + Alt + Del) 키를 누르면 작업 관리자 창이 나오는 데 여기에서 모든 프로그램들의 자원 사용 현황을 볼 수 있다.
2.2 사용자와 운영체제 인터페이스 (User and Operating System Interface)
여기서는 컴퓨터 사용자와 운영체제가 접촉하는 3가지 기본적인 방법에 대해 논의한다.
* 명령 인터프리터 (Command Interpreter)
대부분의 운영체제는 명령 인터프리터를 프로세스가 시작되거나 사용자가 처음 로그인 할 때 수행되는 특수 프로그램으로 취급한다.
이 인터프리터는 셸(shell)이라고 불린다.
명령어 인터프리터는 사용자 또는 명령어 파일로부터 명령어를 읽어 들인 후, 명령어를 하나 이상의 시스템 호출로 변환함으로써 그것을 실행한다. 그에 따라 명령어 인터프리터는 실행에 제약을 받기 때문에, 커널에 포함되지 않는다.
일반적으로 윈도우에는 cmd(command), 맥에는 terminal이 이에 해당한다.
* 그래픽 기반 사용자 인터페이스 (GUI)
이 방식에서는 데스트톱이라고 특징지어지는 마우스를 기반으로 하는 윈도 메뉴 시스템을 이용한다.
사용자는 마우스를 움직여 마우스 포인터를 프로그램, 파일, 시스템 기능 등을 나타내는 화면상의 이미지(아이콘)에 위치시킨다.
* 터치스크린 인터페이스
대부분의 모바일 시스템에서는 앞서 말한 명령 라인 인터페이스, 마우스, 키보드 시스템이 실용적이지 않기 때문에 스마트폰, 태블릿 컴퓨터는 일반적으로 터치스크린 인터페이스를 사용한다.
사용자는 터치스크린에서 손가락을 누르거나 스와이프 하는 등의 제스처를 취하여 상호 작용한다.
2.3 시스템 콜(System Calls)
시스템 콜은 운영체제에 의해 사용 가능하게 된 서비스에 대한 인터페이스를 제공한다.
간단한 작업을 하는 과정에서도 많은 시스템 콜을 수행하게 되는데, 예시는 아래와 같다.
위 사항 중 에러 메시지 출력, 특정 상황에서의 비정상적인 종료 등은 모두 시스템 콜이 사용된 사례를 보여준다.
* 응용 프로그래밍 인터페이스(API)
위에서 보았듯, 간단한 작업에서도 많은 시스템 콜을 사용하게 된다.
대부분의 사용자들은 모든 시스템 콜들을 알지는 못한다.
다만, 개발자들은 응용 프로그래밍 인터페이스(이하 API)에 따라 프로그램을 설계한다.
API는 각 함수에 전달되어야 할 매개변수들과 프로그래머가 기대할 수 있는 반환 값을 포함하여 응용 프로그래머가 사용 가능한 함수의 집합을 명시한다.
운영체제에 매개변수를 전달하기 위해서 세 가지 일반적인 방법을 사용한다.
1) 매개변수를 레지스터 내에 전달하는 것
2) 매개변수는 메모리 내의 블록이나 테이블에 저장되고, 블록의 주소가 레지스터 내에 매개변수로 전달된다.
3) 5개 이하 매개변수가 있으면 레지스터를 사용, 5개가 넘으면 블록 방법을 사용한다. (Linux)
* 시스템 콜의 유형 (Types of System Calls)
시스템 콜은 다섯 가지의 중요한 범주로 묶을 수 있다.
- 프로세스 제어
- 파일 조작
- 장치 조작
- 정보 유지 보수
- 통신과 보호
1) 프로세스 제어
* 끝내기(end), 중지(abort)
실행 중인 프로그램은 수행을 정상적으로( end() ) 또는 비정상적으로( abort() ) 멈출 수 있어야 한다.
* 적재(load), 수행(execute)
한 프로그램을 실행하고 있는 프로세스가 다른 프로그램을 적재( load() )하고 실행( execute() )하기를 원할 수 있다.
이때 한 가지 문제는 적재된 프로그램이 종료되었을 때 어디로 제어를 되돌려 주느냐 하는 것이다.
만약 제어가 기존 프로그램으로 되돌아간다면, 반드시 기존 프로그램의 메모리 이미지를 보관해야 한다.
만약 두 프로그램이 병행하게 수행된다면, 다중 프로그래밍 될 새로운 프로세스를 생성한 것이다.
* 프로세스 생성, 프로세스 종료
새로운 job, process 또는 그들의 집합을 생성한다면, 그들의 실행을 제어할 수 있어야 한다.
* 프로세스 속성 획득, 속성 결정
이러한 제어는 job의 우선순위, 시간 등을 포함한 프로세스의 속성을 결정하고 재설정(reset)할 수 있는 능력이 필요하다.
또한 잘못되었거나 더 이상 필요 없을 경우 종료하기를(terminate_process) 원할 수 있다.
*시간 기다림(wait)
새로운 프로세스를 생성한 후에는 실행이 끝나기를 기다려야 할 필요가 있을 수 있다.
이 경우 일정 시간만큼 기다리기(wait_time)를 하거나, 특정 이벤트(wait_event)가 발생할때까지 기다리는 것이다.
이 경우 신호(signal_event)를 보내야 한다.
* 메모리 할당 및 자유화
빈번하게 둘 이상의 프로세스들은 데이터를 공유한다.
공유되는 데이터의 일관성을 보장하기 위해서 운영체제는 프로세스가 공유 데이터를 잠글 수 있는 시스템 콜을 제공한다.
그러면 잠금이 해제될 때까지 어느 프로세스도 데이터에 접근할 수 없게 된다.
2) 파일 관리 (File Management)
* 파일 생성, 삭제
우선 파일을 생성( create() )하고 삭제( delete() )할 수 있어야 한다.
이들은 파일 이름이나 파일 속성의 일부를 요구한다.
* 파일 열기(open), 닫기(close)
파일이 생성되면 그것을 열고( open() ) 사용해야 한다.
파일을 더 이상 사용하지 않는다면 파일 닫기( close() )가 필요하다.
* 읽기, 쓰기, 위치 변경(reposition)
파일을 열은 후 읽기( read() ), 쓰기( write() )를 할 수 있다.
또한 위치 변경, 예를 들면 되감기( rewind() )나 파일 끝으로 건너뛰기가 가능하다.
* 파일 속성 획득 및 설정
파일 시스템이 파일을 조직하기 위해 디렉터리 구조를 가진다면, 여러 속성의 값을 결정할 수 있어야 한다.
파일 속성은 파일 이름, 유형, 보호 코드, 회계 정보 등을 포함한다.
이러한 기능을 위해서는 최소한 파일 속성 획득(get_file_attribute), 파일 속성 설정(set_file_attribute)의 두 시스템 콜이 필요하다.
3) 장치 관리 (Device Management)
* 장치 요구(request), 방출(release)
다수의 사용자가 동시에 사용하는 시스템은 독점적인 장치 사용을 보장받기 위해 우선 그 장치를 요청 ( request() )하는 것을 요구한다.
또한 그 장치의 사용이 끝나면, 우리는 그것을 반드시 방출 ( release() )해야 한다.
* 읽기, 쓰기, 위치 변경(reposition)
파일과 마찬가지로, 장치를 요청하면 읽기, 쓰기, 위치 변경이 가능하다.
* 장치 속성 획득, 설정
* 장치의 논리적 부착(attach) 또는 분리(detach)
4) 정보 유지 (Information Maintenance)
많은 운영체제는 프로그램의 시간 프로파일(time profile)을 제공한다.
시간 프로파일은 그 프로그램이 특정 위치, 혹은 위치의 집합에서 수행한 시간의 양을 나타낸다.
시간 프로파일은 추적 설비나 정규 타이머 인터럽트가 필요하다.
더욱이 운영체제는 현재 운영되고 있는 모든 프로세스에 관한 정보를 가지고 있으며, 이러한 정보에 접근하기 위한 시스템 콜이 있다.
5) 통신 (Communication)
통신 모델에는 메시지 전달과 공유 메모리의 두 가지 일반적인 모델이 있다.
메시지 전달 모델
통신하는 두 프로세스가 정보를 교환하기 위해 서로 메시지를 주고 받는다.
통신이 이루어지기 전에 연결이 반드시 열려야 한다.
공유 메모리 모델
프로세스는 다른 프로세스가 소유한 메모리 영역에 대한 접근을 하기 위해 System Call을 사용한다.
(일반적으로 운영체제는 한 프로세스가 다른 프로세스의 메모리에 접근하는 것을 막으려고 하기 때문)
6) 보호 (Protection)
보호는 컴퓨터 시스템이 제공하는 자원에 대한 접근을 제어하기 위한 기법을 지원한다.
2.4 시스템 서비스 (System Services)
시스템 서비스는 시스템 유틸리티(system utility)라고 알려진, 프로그램 개발과 실행을 위해 더 편리한 환경을 제공한다.
단순히 시스템 콜에 대한 사용자 인터페이스뿐만아니라, 프로그래밍언어지원, 백그라운드 서비스 등이 있다.
사용자 대부분이 보는 운영체제의 관점은 실제 시스템 콜에 의해서보다는 시스템 프로그램과 응용에 의해 정의된다.
우리가 지금 보고 있는 이 글도 그저 UI를 보는 것일뿐, 시스템 콜에 대해 생각하고 있지 않은 것처럼 말이다.
2.5 링커와 로더 (Linkers and Loaders)
일반적으로 프로그램을 CPU에서 실행하려면, 프로그램을 메모리로 가져와 프로세스 형태로 배치해야 한다.
이 장에서는 이러한 절차를 링커와 로더로 설명한다.
소스 파일은 임의의 물리 메모리 위치에 적재되도록 설계된 오브젝트 파일로 컴파일 된다.
이러한 형식을 재배치 가능 오브젝트 파일이라고 한다.
링커는 이러한 재배치 가능 오브젝트 파일을 하나의 이진 실행 파일로 결합한다.
로더는 이진 실행 파일을 메모리에 적재하는 데 사용되며, CPU 코어에서 실행할 수 있는 상태가 된다. 링크 및 로드와 관련된 활동은 재배치로, 프로그램 부분에 최종 주소를 할당하고 프로그램 코드와 데이터를 해당 주소와 일치하도록 조정하여 프로그램이 실행될 때 코드가 라이브러리 함수를 호출하고 변수에 접근할 수 있게 한다.
'운영체제' 카테고리의 다른 글
공룡책과 함께 OS를 배워보자 5일차 - CPU 스케줄링 (2) | 2021.08.13 |
---|---|
공룡책과 함께 OS를 배워보자 4일차 - 스레드 (0) | 2021.08.13 |
공룡책과 함께 OS를 배워보자 3일차 - 프로세스 (0) | 2021.08.13 |
공룡책과 함께 OS를 배워보자 1일차 - Overview (0) | 2021.08.13 |
공룡책과 함께 OS를 배워보자 0일차 - 준비 운동 (1) | 2021.08.13 |