참고 자료
[책] 운영체제 아주 쉬운 세 가지 이야기
2장 운영체제 개요
프로그램이 실행될 때 어떤 일이 일어날까?
명령어를 실행한다.
프로세서는 명령어를 초당 수십억 번 반입(fetch)하고, 해석(decode)하고, 실행(execute)한다
명령어 작업을 완료한 후 프로세서는 다음 명령어로, 그 다음 명령어로 프로그램이 종료될 때까지 실행을 계속한다
시스템을 사용하기 쉽게하기 위해(easy to use) 프로그램 실행 시 다양한 일들이 발생한다는 것을 배운다.
운영체제(operating system, OS)은 하나의 소프트웨어, 시스템을 사용하면서 편리하고 정확하고 올바르게 동작시킬 책임이 있다.
운영체제는 가상화(virtualization)기법을 사용하여 프로세서, 메모리, 디스크 같은 물리적(physical)인 자원을 이용하여 편리한 가상(virtual) 형태의 자원을 생성한다. 그래서 운영체제를 가상 머신(virtual machine)이라고 부른다.
운영체제는 사용자에게 가상 머신과 관련된 기능(파일 접근, 프로그램 실행)을 요청할 수 있도록 API를 제공한다. 보통 운영체제는 응용 프로그램이 사용 가능한 수백 개의 시스템 콜을 제공한다.
운영체제는 가상화를 통해 많은 프로그램들이 CPU를 공유하여, 동시에 실행될 수 있게 한다. 또한 각자 명령어와 데이터를 접근할 수 있게 한다. 이런 이유로 자원 관리자(resource manager)라고도 불린다.
CPU, 메모리, 디스크는 시스템의 자원이다. 효율적이고 공정하게 관리하는 것이 운영체제의 역할이다.
2.1 CPU 가상화
운영체제가 물리적 자원을 가상화 시키는 이유
- 일관된 인터페이스 제공(추상화)
- 운영체제는 다양한 하드웨어(예: CPU, 메모리, 디스크, 네트워크 장치)에 대한 공통된 인터페이스를 제공
- 예를 들어, 파일 시스템은 저장장치(HDD, SSD, USB 등)의 물리적인 차이를 감추고, 사용자가 open(), read(), write() 같은 공통된 API를 사용할 수 있도록 한다.
- 안전한 자원 관리 (격리 및 보호)
- 여러 프로세스가 같은 물리 자원을 공유하지만, 운영체제는 각 프로세스가 자신의 메모리 공간만 접근하도록 제한한다.
- 예를 들어, 가상 메모리는 프로세스마다 독립적인 주소 공간을 제공해 다른 프로세스의 메모리를 침범하지 못하게 한다.
- 효율적인 자원 사용 (공유 및 스케줄링)
- 하드웨어 변경에 대한 유연성
즉, 가상화를 통해 사용자는 단순하고 일관된 인터페이스를 사용하면서도, 성능과 보안을 유지하며 효율적으로 시스템을 활용할 수 있다.
그림 5.2는 사용자가 입력한 문자열을 무한 루프로 출력하는 프로그램 4개를 단일 프로세서에서 동시에 실행시킨 결과이다.
결과를 보면 프로그램 4개 모두 동시에 실행되는 것처럼 보인다
이는 OS가 하드웨어의 도움을 받아 시스템에 매우 많은 수의 가상 CPU가 존재하는듯한 환상을 만들어 낸 것이다.
이렇게 하나 이상의 CPU를 통해 무한개의 CPU가 존재하는 것처럼 변환하여 동시에 많은 프로그램을 실행하는 것을 CPU 가상화(virtualizing the CPU)라 한다.
특정 순간에 두 개의 프로그램을 실행되기를 원한다면, 누가 먼저 실행되어야 하는가? 이 질문은 운영체제의 정책에 달려있다.
운영체제의 여러 부분에서 이러한 유형의 문제에 답하기 위한 정책들이 사용된다.
2.2 메모리 가상화
현재 우리가 사용하고 있는 컴퓨터의 물리 메모리 모델은 매우 단순하다. 바이트 배열이다. 메모리를 읽기 위해서는 데이터에 주소(address)를 명시해야 한다. 메모리에 쓰기(혹은 갱신)을 위해서는 주소와 데이터를 명시해야 한다.
메모리는 프로그램이 실행되는 동안 항상 접근된다. load, store 같은 메모리 접근을 위한 명령어를 통하여 자료 구조에 접근한다.
명령어 역시 메모리에 존재한다는 사실을 잊지 말자
그림 5.3은 malloc()을 호출하여 메모리를 할당하는 그림이다.
- a1: 메모리를 할당받는다
- a2: 할당받은 메모리의 주소를 출력한다.
- a3: 새로 할당받은 메모리의 첫 슬롯에 숫자 0을 넣는다.
- while 루프
- <Spin()>1초 대기 후, 변수 p가 가리키는 주소에 저장되어 있는 값을 1 증가시킨다.
- 출력할 때마다 <getpid()>실행 중인 프로그램의 프로세스 식별자 PID와 값이 함께 출력된다.
프로그램의 출력 결과
그림 5.3은 새로 할당된 주소는 00200000이다. 그리고 프로그램이 진행되면서 값을 갱신하고 그 결과를 출력한다.
그림 5.4는 같은 프로그램을 여러 번 실행했다. 프로그램들은 같은 주소(00200000)에 메모리를 할당받지만 각각이 독립적으로 00200000 번지의 값을 갱신한다. 각 프로그램은 물리 메모리를 다른 프로그램과 공유하는 것이 아니라 각자 자신의 메모리를 가지고 있는 것처럼 보인다.
운영체제가 메모리 가상화(virtualizing memory)를 하기 때문에 이런 현상이 생긴다. 각 프로세스는 자신만의 가상 주소 공간(virtual address space, 주소 공간(address space))을 갖는다.
운영체제는 이 가상 주소 공간을 컴퓨터의 물리 메모리로 매핑한다. 실행 중인 프로그램 입장에서는 자기 자신만의 물리 메모리를 갖는다.
실제로는 물리 메모리는 공유 자원이고 운영체제에 의해 관리된다. 이러한 일들이 정확히 어떻게 일어나는지는 책의 가상화 (virtualization)에 나온다.
2.3 병행성
이 책의 주요 주제이다. 병행성(동시성, concurrency)
프로그램이 한 번에 많은 일을 하려 할 때 동시에 발생하고, 반드시 해결하는 문제들을 가리킬 떄 이 용어를 사용한다. 병행성 문제는 운영체제 자체에서 발생하고 심각하고 흥미로운 문제를 발생시킨다.
병행성 문제는 멀티 쓰레드 프로그램도 동일한 문제를 드러낸다.
책에서는 2개의 쓰레드로 공유 변수를 10000번 증가시켜서 멀티 쓰레드 프로그램에서의 병행성 문제를 보여준다. 각각 10000번 증가시킨다면 기존 변수가 N이면 N+20000을 기대하지만 결과는 그렇지 않다. 왜 이런 일이 발생할까?
변수를 증가시키는 부분은 세 개의 명령어로 이루어진다.
- counter값을 메모리에서 레지스터로 탑재 명령어
- counter값을 1 증가시키는 명령어
- counter값을 레지스터에서 메모리로 저장하는 명령어
이렇게 세 개의 명령어가 원자적(automically)으로 실행되지 않기 떄문에 이상한 일이 발생할 수 있다.
2.4 영속성
세 번째 주요 주제는 영속성(persistence)이다. DRAM 같은 메모리 장치는 데이터를 휘발성(volatile) 방식으로 저장하기 때문에 메모리의 데이터는 전원 공급이 끊어지거나 시스템이 고장나면 메모리의 모든 데이터는 사라진다.
데이터를 영속적으로 저장할 수 있는 하드웨어나 소프트웨어가 필요하다.
하드웨어는 I/O 장치 형태로 제공된다. 요즘에는 SSD가 많이 사용되고 있기는 하지만 장기간 보존할 정보를 저장하는 장치로는 하드 드라이브가 사용된다.
디스크를 관리하는 운영체제 소프트웨어는 파일 시스템(file system)이라고 부른다. 파일 시스템은 사용자가 생성한 파일을 시스템의 디스크에 안전하고 효율적으로 저장할 책임이 있다.
그림 5.6은 문자열 "hello world"를 포함한 파일 /tmp/file을 생성하는 코드이다. 여기서 프로그램은 운영체제를 세 번 호출한다. 첫째 open() 콜은 파일을 생성. 둘째 write() 콜은 파일에 데이터를 쓴다. 셋째 close() 콜은 파일을 닫는다. 이들 시스템 콜(system call)은 운영체제에서 파일 시스템(file system)이라 불리는 부분으로 전달된다. 파일 시스템은 요청을 처리하고 에러가 발생하면 에러 코드를 반환한다.
데이터를 디스크에 쓰기 위해서는 파일 시스템이 많은 작업을 해야 한다. 새 데이터가 어디에 저장될지 결정해야 하고, 파일 시스템이 관리하는 다양한 자료 구조를 통하여 데이터의 상태를 추적해야 한다. 운영체제는 시스템 콜을 통해 표준화된 방법으로 장치에 접근할 수 있도록 하며, 이를 위해 장치 드라이버(device driver)가 필요하다. 파일 시스템이 데이터를 영속적으로 관리하는 방법은 훨씬 더 복잡하다. 성능을 위해 쓰기 요청을 지연시켜 한 번에 처리하며, 시스템 오류 대비를 위해 저널링(journaling)이나 쓰기- 시- 복사(Copy-On-Write) 같은 기법을 사용한다. 또한 효율적인 디스크 작업을 위해 단순 리스트부터 B-트리 같은 복잡한 구조까지 다양한 자료구조를 사용한다.
2.5 설계 목표
5.5는 운영체제의 설계 목표에 대해 설명한다. 운영체제는 CPU, 메모리, 디스크 등의 물리 자원을 가상화하여 사용자가 쉽게 접근할 수 있도록 한다. 추상화는 복잡한 시스템을 쉽게 이해하고 사용할 수 있도록 하는 개념으로, 운영체제 설계에서 중요한 원칙이다. 또한 성능 최적화는 가상화와 기능성을 제공하면서도 시간(명령어의 개수)과 공간(메모리 또는 디스크)오버헤드를 최소화하는 것이 중요하다. 보호 및 고립 측면 응용 프로그램 간, 그리고 운영체제와 응용 프로그램 간의 보호를 보장하여 안정성을 유지해야 한다. 신뢰성은 운영체제의 실패는 모든 응용 프로그램에 영향을 주므로 높은 신뢰성을 유지하는 것이 필수적이다. 또한 에너지 효율성, 보안, 이동성 등도 운영체제 설계에서 중요한 요소로 고려된다.
이러한 목표들은 운영체제의 설계 및 구현 과정에서 적절한 절충점을 찾는 데 필수적이다.
'Computer Sience > Operating System' 카테고리의 다른 글
[OS] 운영체제 아주 쉬운 세 가지 이야기 6장 제한적 직접 실행 원리 (0) | 2025.04.01 |
---|---|
[OS] 운영체제 아주 쉬운 세 가지 이야기 5장 프로세스 API (0) | 2025.03.31 |
[OS] 운영체제 아주 쉬운 세 가지 이야기 4장 프로세스의 개념 (0) | 2025.03.31 |
스레드 컨텍스트 스위칭 vs 프로세스 컨텍스트 스위칭 (0) | 2024.05.18 |
OS level에서 어떻게 여러 프로그램이 동시에 실행될까? (0) | 2024.05.17 |