[Operating System] 운영체제 구조

남태일·2023년 12월 5일

Operating System

목록 보기
2/9
post-thumbnail

저번 글에서 운영체제의 개요를 쭉 훑어보았다.

이번에는 운영체제의 구조를 한번 살펴보자.


운영체제 서비스

운영체제는 프로그램과 그 프로그램의 사용자에게 특정 서비스를 제공한다.
운영체제의 서비스 종류는 아래와 같다.

  • 사용자 인터페이스(User Interface)
    • 대부분의 운영체제에서 제공한다.
    • 일반적으로 "그래픽 사용자 인터페이스(GUI)"가 사용되며, 모바일 기기에서는 "터치스크린 인터페이스"가 사용된다.
    • 가벼운 운영체제에서는 "명령어 라인 인터페이스(CLI)"를 사용한다.
  • 프로그램 실행(Program Execution)
    • 프로그램을 메모리에 적재해서 실행되도록 한다.
  • 입출력 연산(I/O Operation)
    • 사용자들은 입출력 장치를 직접 제어할 수 없다.
    • 운영체제가 입출력 수행의 수단을 제공한다.
  • 파일 시스템 조작(File System Manifulation)
    • 파일 생성, 삭제, 권한 등의 기능을 제공한다.
  • 통신(Communication)
    • 동일한 컴퓨터 내의 프로세스간 통신이나, 네트워크로 연결된 서로 다른 컴퓨터의 프로세스간 통신을 지원한다.
    • 공유 메모리 또는 메시지 전달 기법으로 구현된다.
  • 오류 탐지(Error Detection)
    • 하드웨어 적인 오류(메모리 오류, 정전, 네트워크 접속 실패, 프린터 종이 부족)를 탐지하고 조치한다.
    • 사용자 프로그램에서 발생하는 오류(연산 오버플로우, 할당 받지 않은 메모리 접근)를 탐지하고 조치한다.
  • 자원 할당(Resource Allocation)
    • 여러 프로세스들이 실행될 때, 각 프로세스에게 자원을 할당해준다.
  • 기록(Logging)
    • 어떤 프로그램의 어떤 종류의 자원을 얼마나 사용하는지 기록해준다.
  • 보호와 보안(Protection & Security)
    • 여러 사용자가 컴퓨터를 사용하는 환경에서 패스워드와 같은 기능을 통해 보안을 지킨다.
    • 여러 프로세스가 실행될 때, 다른 프로세스나 운영체제에 영향을 끼치지 않도록 보호한다.

시스템 콜(System Call)

자원 할당, 파일 접근과 같이 운영체제를 통해 사용할 수 있는 서비스에 대한 인터페이스를 제공한다.

프로그래밍을 할 때, 입출력 작업, 메모리 할당과 같은 요청은 시스템 콜 함수를 통해 운영체제에게 요청하여 이루어진다.
이러한 시스템 콜은 API(Application Programming interface)로 제공된다.
API는 각 함수에 전달되어야 할 매개 변수와 반환값을 포함하여 프로그래머가 사용 가능한 함수들의 집합을 명시한다.

프로그래머가 사용 가능한 가장 흔한 API 세 가지는 다음과 같다.

  • Windows 운영체제의 Windows API.
  • POSIX 기반 운영체제(Linux, MacOS, ...)의 POSIX API.
  • JVM(Java Virtual Machine)에서 실행될 수 있는 Java API.

프로그래머가 시스템 콜 API를 호출하면, 시스템 콜 API가 내부적으로 시스템 콜을 호출하는 식으로 동작한다.
프로그래머는 API 명세에 맞게 호출만 하면, 내부 시스템 콜은 어떤식으로 동작하는지 몰라도 된다.

시스템 콜의 유형


링커와 로더(Linkers and Loaders)

일반적으로 프로그램은 보조기억장치에 이진 실행 파일(a.out 또는 program.exe)로 존재한다.
프로그램을 실행하려면 프로그램을 메모리에 적재해서 프로세스로 배치되어야 한다.
프로그램 컴파일부터 실행까지의 과정을 한번 살펴보자.

  • 소스 파일은 오브젝트 파일로 컴파일된다.
  • "링커"는 이러한 오브젝트 파일을 하나의 이진 실행 파일로 결합한다.
    링킹 단계에서 표준 라이브러리와 같은 다른 오브젝트 파일 또는 라이브러리도 포함될 수 있다.
  • "로더"는 이진 실행 파일을 메모리에 적재하는데 사용된다.

그림의 동적 링크 라이브러리는 Windows에서 사용하는 DLL과 같은 "동적 라이브러리"를 말한다.
DLL을 사용하면, 프로그램 실행 중 필요한 부분만 적재할 수 있다는 것이다.
또한 여러 프로세스가 하나의 라이브러리를 공유하기 때문에, 메모리도 절약할 수 있다.

오브젝트 파일 및 실행 파일은 일반적으로 표준화된 형식을 가진다.
이 표준 형식은 프로그램에 대한 메타데이터를 포함하고 있다.
UNIX, Linux 시스템의 경우 이 형식을 "ELF(Executable and Linkable Format)"이라고 한다.
오브젝트 파일과 실행 파일 각각을 위한 별도의 ELF 형식이 사용된다.
Windows 시스템은 "PE(Portable Executable)" 형식을 사용하고 macOS는 "Mach-O" 형식을 사용한다.


프로그램이 운영체제마다 다른 이유

기본적으로 한 운영체제에서 컴파일된 프로그램은 다른 운영체제에서 실행할 수 없다.
왜 그럴까?

각 운영체제는 고유한 시스템 콜 집합을 제공하기 때문이다.
운영체제간 시스템 콜이 어느정도 같더라도, 다른 장벽으로 인해 다른 운영체제에서 프로그램을 실행하기는 어렵다.

시스템의 low level 관점에서 아래와 같은 문제가 존재한다.

  • 각 운영체제는 실행 파일 형식이 정해져 있기 때문에, 명시된 구조 형태로 실행 파일이 있어야 올바르게 실행할 수 있다.
  • CPU는 다양한 명령어 세트를 가지며 해당 명령어가 포함된 프로그램만 올바르게 실행할 수 있다.
  • 운영체제의 시스템 콜 형식이 각각 다르다.

그러나 다음 세 가지 방법 중 한 가지를 사용하여 프로그램이 여러 운영체제에서 실행될 수 있게 만들 수 있다.

  • 인터프리터 언어를 사용한다. (Python, Ruby, ...)
    • 컴파일 방식보다 성능이 떨어진다.
  • Java 같은 전용 가상 머신이 있는 언어를 사용한다.
    • 컴파일 방식보다 성능이 떨어진다.
  • 각 운영체제에 맞게 프로그램을 작성한다.
    • 오래걸리고 많은 테스트와 디버깅을 프로그램의 새로운 버전마다 수행해야한다.

운영체제 부팅

운영체제가 설치된 컴퓨터에서는 컴퓨터 전원이 켜지면 해당 운영체제를 사용할 수 있어야 한다.
즉, 메모리에 운영체제를 적재해야 하는데 커널의 위치를 어떻게 알 수 있을까?
저번 글에서 잠깐 말했듯이, "부트스트랩" 프로그램이 커널을 찾고 메모리에 적재한다.

그럼 부트스트랩은 어떻게 실행되는걸까?
컴퓨터 전원을 처음 켜면 BIOS라고 하는 비휘발성 펌웨어(보통 EEPROM)에 있는 부트스트랩이 실행되어 부팅 과정을 거친다.

커널을 메모리에 적재하는 작업을 "부팅"이라고 하며, 부팅 과정은 아래와 같다.

  • 부트스트랩 프로그램이 커널의 위치를 찾는다.
  • 커널이 메모리에 적재되고 시작된다.
  • 커널은 하드웨어를 초기화 한다.
  • 루트 파일 시스템(/)이 마운트 된다.

이 시점에서 시스템이 실행 중이라고 말할 수 있다.

0개의 댓글