프로그램은 매우 단순한 일을 한다:
- 명령어를 메모리에서 Fetch하고,
- Decode하고 (무슨 명령어인지 파악),
- Data를 얻고 (연산),
- Execute한다.
OS는 여러 프로그램을 쉽게 실행하게끔 하고, 프로그램 간의 메모리 공유, 장치와 상호작용할 수 있게 한다.
System Call을 사용해 OS에 원하는 작업을 수행시킬 수 있다.
OS는 Virtualization을 통해 다음을 가능하게끔 한다:
- CPU 공유
- Memory 공유
- Disk 공유
CPU 가상화
A program that loops and prints (cpu.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <assert.h>
#include "common.h" // Contains Spin() function
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "usage: cpu <string>\n");
exit(1);
}
char *str = argv[1];
while (1) {
Spin(1); // Repeatedly checks the time and returns once it has run for a second
printf("%s\n", str);
}
return 0;
}
하나의 프로세서만 가지고 있음에도 불구하고, 4개의 프로그램 모두 동시에 실행되는 것처럼 보인다.
Memory 가상화
실제 물리 메모리는 byte로 배열되어 있다. 프로그램은 실행 중 자신의 모든 자료들을 메모리에 유지하고 Read (load), Write (store) 하는데, 각 프로그램은 각자 고유의 메모리 영역을 가지고 있는 것처럼 보인다.
// A program that accesses memory (mem.c)
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "common.h"
int main(int argc, char *argv[]) {
int *p = malloc(sizeof(int)); // a1: allocate memory
assert(p != NULL);
printf("(%d) address of p: %08x\n", getpid(), (unsigned) p); // a2: print out the address of the memory
*p = 0; // a3: put zero into the first slot of the memory
while (1) {
Spin(1);
*p = *p + 1;
printf("(%d) p: %d\n", getpid(), *p); // a4
}
return 0;
}
각 프로그램이 동일한 주소에 메모리가 할당된 것으로 나타내어진다.
각 프로세스는 자신만의 Virtual Address Space를 가진다.
한 프로그램의 메모리 연산은 다른 프로세스와 독립적이며, 서로의 공간에 영향을 주지 않는다.
병행성 (Concurrency)
운영체제는 여러 프로세스를 실행시켜 한 번에 많은 일을 한다. 멀티스레드 프로그램도 동일한 문제가 있다.
- main 프로그램은
pthread_create()
로 두 개의 thread를 생성한다.
A Multi-threaded Program (thread.c)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "common.h"
volatile int counter = 0; // 공유 변수
int loops;
void *worker(void *arg) {
for (int i = 0; i < loops; i++) {
counter++;
}
return NULL;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "usage: threads <value>\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;
}
counter++ 는 세 개의 명령어로 구성된다.
- Memory -> register load
- Add
- Register -> memory store
이렇게 세 명령어가 Atomically하게 실행되지 않기 때문에 문제가 발생한다. (Critical Section 문제) OS는 이 문제에 해결방법을 제시한다.
Persistence (영속성)
DRAM과 같은 장치는 data를 volatile (휘발성) 하게 저장하므로, 전원이 꺼지거나 system crash가 발생하면 메모리의 data가 손실될 수 있다. -> 영속적 저장 필요.
- HW, SW 필요:
- H/W: I/O devices (HDD, SSD, …etc)
- S/W: File System
File System은 사용자가 생성한 file을 디스크에 안전하고 효율적으로 저장해야 한다.
- 파일 생성 예제:
/tmp/file
에 "hello world" 문자열을 저장하는 프로그램
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
int fd = open("/tmp/file", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
assert(fd >= 0);
int rc = write(fd, "hello world\n", 13);
assert(rc == 13);
close(fd);
return 0;
}
- open(), write(), close() 등의 System call들은 OS에서 File System과 분리된 부분으로 전달된다.
- Data가 어디에 저장될지 결정되고, device driver를 통해 저장 장치에 기록된다.
- Crash handling을 위해 Journaling, Copy-On-Write와 같은 복잡한 쓰기 방법을 사용한다.
OS Design Goals
- Abstraction
- High Performance
- Protection between programs
- Reliability
- Energy, Security, Mobility…
'Computer Science > OS' 카테고리의 다른 글
2-5. Virtualization: Multi-Level Feedback Queue (0) | 2024.11.05 |
---|---|
2-4. Virtualization: Scheduler(FIFO, SJF, STCF, RR)와 성능 지표 (1) | 2024.11.05 |
2-3. Virtualization: Limited Direct Execution (0) | 2024.11.04 |
2-2. Virtualization: 파일 디스크립터와 입출력 관리 (0) | 2024.11.03 |
2-1. Virtualization: 프로세스 관리와 자료구조, Process API (0) | 2024.11.03 |