이번 학기 운영체제 강의를 듣게 되어 공부 및 복습하는 겸 블로그에 상세히 포스팅 해보려고 한다.
선수 지식으로는 C/C++ 프로그래밍, 자료구조, 시스템소프트웨어 학문을 알고 있다면 더 수월하게 이해 가능할 것이다.
Operating Systems : Three Easy Pieces 라는 원서를 기반으로 진행되는데 교수님이 이에 관해 재미있는 말씀을 해주셨다. 유명한 운영체제 원서인 공룡책과 다르게 이 책은 표지가 혜성인데, 기존의 공룡책을 박살내겠다는 의지가 담겼다고 한다(?)
Virtualization, Concurreny, Persistence 라는 3개의 대주제로 진행될 것이며 xv6를 이용한 프로젝트도 준비되어있다.
그럼 운영체제 공부를 시작하도록 하자.
🤔 프로그램이 돌아갈 때 어떤 일이 벌어질까?
평소 프로그램이 돌아갈 때 어떤 동작이 일어나는 지 생각해본 적 있는가? 프로그램이 실행되면 아래와 같은 동작들이 순차적으로 실행된다.
- 메모리에서 명령어를 fetch 한다.
- Decode : 명령어가 무엇인지 알아낸다.
- Excute : 더하거나, 메모리에 접근하거나, 조건을 체크하는 등의 명령을 수행한다.
- 프로세서가 다음 명령에로 이동하여 1~3을 반복한다.
이러한 일을 응용프로그램이 직접 관리하고 접근한다면 서로 다른 앱간 충돌이 일어나거나, 성능적으로 효율적이지 못할 것이다. 따라서 하드웨어와 응용어플리케이션 사이 관리하고 조율하는 역할을 하는 프로그램을 운영체제 (Opearating System) 이라고 한다.
💡운영 체제 (Opearating System)
운영체제는
- 프로그램을 실행하기 더 쉽게 만들어 준다.
- 메모리를 공유하도록 허가해준다
- 디바이스와 상호작용 가능하도록 해준다
OS는 시스템을 정확하고, 효과적으로 작동하도록 보장하는 역할을 한다.
운영체제에 알아야할 큼지막한 주제를 알아보도록 하자
가상화 (Virtualization)
OS는 물리적 자원을 가상의 것으로 변환시켜준다. 이를 가상화라고한다.
여기서 물리적 자원이라 함은 프로세서, 메모리, 디스크와 같은 실제 데이터를 저장할 수 있는 공간을 뜻한다.가상의 형태는 더 응용프로그램에게 일반적이고, 강력하며 더 쉽게 이용할 수 있도록 해준다.
가끔 OS를 가상화 머신 (virtual machine) 이라고도 한다.
CPU 가상화
시스템은 아주 많은 숫자의 가상화된 CPU를 가지고 있다.CPU를 가상화함으로써 하나의 CPU를 무한대의 CPU로 변환할 수 있으며 여러개의 프로그램을 동시에 돌아가는 것 처럼 실행할 수 있다.
메모리 가상화
물리적인 메모리는 수많은 bytes의 배열이다.프로그램은 메모리에 자료구조를 저장한다. 읽거나 쓰는 등의 동작이 가능하다.
만약 P라는 주소에 접근하여 1초에 1씩 증가시키는 프로그램이 있다고 하자.만약 동시에 P라는 프로그램을 2개를 실행시킨다면 P 주소의 값은 2배로 증가할까?
답은 그렇지 않다.각각의 프로그램은 그들만의 private한 가상 메모리를 가지며, 가상화된 공간에 완전히 격리된다.
각 프로그램에서 같은 P의 주소에 접근했다고 생각할 수 있지만, 이는 가상화된 메모리 공간이며 응용프로그램은 실제 물리적인 주소를 알수 없다. 이는 운영체제만이 알고 있을 것이다.
시스템 콜 (System call)
시스템 콜은 사용자가 OS에게 무엇을 해야할지 알려주도록 해준다.OS는 이러한 API와 std lib과 같은 인터페이스를 제공해준다.
- 프로그램 실행
- 메모리 접근
- 디바이스 접근
전형적으로 OS는 수백개의 시스템 콜을 가지고 있다.
OS는 자원 관리자
운영체제는 CPU나 메모리와 같은 자원을 관리한다.많은 프로그램이 실행되면, CPU를 공유한다. 많은 프로그램이 병렬적으로 실행되면 메모리 자원을 공유함으로써 각각의 명령과 데이터를 가진다. 또한 많은 프로그램이 디바이스에 접근하려하면 디스크를 공유하도록 해준다.
Concurrency Problem 동시성 문제
OS는 여러 프로그램을 동시에 실행하며, 현대 멀티 쓰레드를 이용하는 프로그램에서는 concurrency 문제가 발생한다.
volatile int counter = 0;
int loops;
void *worker(void *arg) {
int i;
for(i=0;i<loops;i++) {
counter++;
}
return NULL;
}
int main(int argc, char *argv[]) {
if(argc != 2) {
fprint(stderr, "usage: threads <values>\\n");
exit(1);
}
loops = atoi(argv[1]);
pthread_t p1, p2;
printf("Initial value : %d\\n", counter);
Pthread_create(&p1, NULL, worker, NULL);
Pthread_create(&p2, NULL, worker, NULL);
Pthread_join(p1, NULL);
Pthread_join(p2, NULL);
printf("Final value : %d\\n", counter);
return 0;
}
Pthread_create 함수는 worker 함수를 새로운 쓰레드에서 실행 시키고,join은 그 쓰레드가 종료될 때 까지 기다려준다.
argv 인자 값으로 넘겨준 만큼 각각의 쓰레드에서 counter을 증가시키고 종료하는 프로그램인 것이다.그럼 만약 10000을 준다면 같은 자원인 counter에 각각 10000씩 더하니 20000이 나와야 할 것이다.
하지만 실제로 실행시켜보면 Final value로 출력되는 counter 값은 20000보다 작은 걸 확인할 수 있다.왜 이런일 이 일어날까? 🤔
코드에서 counter++ 로 한 줄로 쓰여진 명령은 실제로 3가지 동작으로 구분된다.1. counter 값을 메모리에서 레지스터로 load한다2. 레지스터 값을 증가 시킨다.3. 레지스터의 값을 다시 메모리에 store한다.
이러한 3가지 동작은 한번에(atomically) 일어나지 않는다. 값을 증가시키고 store 하기도 전에 load 한다면 제대로 카운팅 되지않는 concurrency problem이 발생하는 것이다.
영속성 Persistence
DRAM과 같은 디바이스는 값을 volatile하게 저장한다.하드웨어와 소프트웨어는 데이터를 persistently 영속적이게 저장할 필요가 있다.
😄 운영체제를 설계하는 목표는 ?
- 시스템을 추상화 함으로써 더 쉽고 편이하게 사용하도록 한다.
- 더 높은 성능을 제공한다.
- 응용프로그램 간의 충돌을 막는다.
- 안정성을 보장한다.
- 에너지 절약, 보안 등등....
'Computer Science > Operating System' 카테고리의 다른 글
[운영체제] 컨텍스트 스위치(Context Switch)란? (0) | 2022.04.10 |
---|---|
[운영체제] 프로세스(Process)란? (0) | 2022.04.09 |