Skip to content

Commit 9e94839

Browse files
author
seungwonme
committed
Update
1 parent ae4024b commit 9e94839

30 files changed

+247
-57
lines changed

img/mem-01.png

63.7 KB
Loading

img/mem-02.png

148 KB
Loading

ipc/README.md

-2
This file was deleted.

md/ch09/README.md

+48-49
Original file line numberDiff line numberDiff line change
@@ -11,98 +11,97 @@
1111
- [메모리가 불연속적일 때](#메모리가-불연속적일-때)
1212
- [Paging](#paging)
1313

14-
1514
> **전반적인 명령어 실행**
1615
>
1716
> 1. 메모리로 부터 한 명령어 가져옴
1817
> 2. 명령어를 해독
1918
> 3. 메모리에서 피연산자를 가져와 피연산자에 대해 명령 실행
2019
> 4. 계산 결과를 메모리에 다시 저장
2120
22-
## Basic Hardware
21+
# Basic Hardware
2322

24-
### CPU가 직접 접근할 수 있는 유일한 범용 저장장치
23+
## CPU가 직접 접근할 수 있는 유일한 범용 저장장치
2524

2625
1. 메인 메모리 -> 버스를 통해 전송되므로 많은 CPU 클록 틱 사이클 소요 -> 데이터가 없어서 명령이 지연되는 stall 현상 발생 -> CPU와 메인 메모리 사이에 빠른 속도의 메모리인 cache 추가
2726
2. 각 코어에 내장된 레지스터 -> accessible 1 cycle of the CPU clock
2827

29-
### 올바른 동작을 위한 메모리 관리
28+
## 올바른 동작을 위한 메모리 관리
3029

31-
![](/img/image.png)
30+
![](/img/mem-01.png)
3231
물리 메모리의 접근 속도도 중요하지만 올바른 동작을 보장하는 것도 중요
3332

34-
- 사용자 프로그램으로부터 운영체제 영역 보호
35-
- 사용자 프로그램 간 보호
36-
운영체제가 CPU와 메모리 간의 접근 중 개입 -> 성능 저하 -> 하드웨어가 지원
33+
- 사용자 프로그램으로부터 운영체제 영역 보호
34+
- 사용자 프로그램 간 보호
35+
운영체제가 CPU와 메모리 간의 접근 중 개입 -> 성능 저하 -> 하드웨어가 지원
3736

3837
**각각의 프로세스가 독립된 메모리 공간을 가지도록 보장**
3938
병행 실행을 위해 여러 프로세스가 메모리에 적재되게 하는 것이 필수적 -> base register and limit register 이용하여 특정 프로세스만 접근 가능한 legal memory space 설정
4039

4140
> `base register` <= `legal memory` <= `base register + limit register`
4241
43-
- 사용자 모드에서 illegal 접근을 한다면 운영체제는 치명적인 오류로 간주 -> trap 발생
44-
- base register와 limit register는 운영체제의 특권 명령으로만 변경 가능
42+
- 사용자 모드에서 illegal 접근을 한다면 운영체제는 치명적인 오류로 간주 -> trap 발생
43+
- base register와 limit register는 운영체제의 특권 명령으로만 변경 가능
4544

46-
## Address Binding
45+
# Address Binding
4746

4847
`program` -> 디스크에 저장되어 있는 binary executable file
4948

50-
![](../../../_AttachedFiles/Screenshot%202024-08-17%20at%2017.24.22.png)
49+
![](/img/mem-02.png)
5150

52-
- `source program`에서 주소는 숫자가 아닌 심볼 형태(변수)로 표현된다.
53-
- `compiler`는 이 심볼 주소를 relocatable addresses(예를 들어 이 모듈의 첫 번째 바이트로부터 열네 번째 바이트 주소)로 바인딩
54-
- `linker` or `loader` is binds `relocatable addresses` to `absolute addresses`
51+
- `source program`에서 주소는 숫자가 아닌 심볼 형태(변수)로 표현된다.
52+
- `compiler`는 이 심볼 주소를 relocatable addresses(예를 들어 이 모듈의 첫 번째 바이트로부터 열네 번째 바이트 주소)로 바인딩
53+
- `linker` or `loader` is binds `relocatable addresses` to `absolute addresses`
5554

56-
## Logical vs Physical Address Space
55+
# Logical vs Physical Address Space
5756

58-
- Logical address: CPU가 생성하는 주소
59-
- Physical Address Space: 메모리의 실제 주소 (메모리 주소 레지스터에 주어지는 주소)
57+
- Logical address: CPU가 생성하는 주소
58+
- Physical Address Space: 메모리의 실제 주소 (메모리 주소 레지스터에 주어지는 주소)
6059

6160
프로그램 실행 시 가상 주소를 물리 주소로 변환하는 작업은 하드웨어 장치인 MMU(Memory Management Unit)에 의해 실행된다.
6261

63-
## Memory Allocation
62+
# Memory Allocation
6463

65-
### 메모리가 연속적일 때
64+
## 메모리가 연속적일 때
6665

67-
#### 가변 파티션
66+
### 가변 파티션
6867

69-
- 프로세스를 메모리의 가변 크기 파티션에 할당
70-
- 각 파티션에는 정확히 하나의 프로세스만 적재
71-
- 운영체제는 사용 가능, 불가능 부분을 나타내는 `hole` 테이블을 유지
72-
- `hole`: 하나의 큰 사용 가능한 메모리 블록
73-
- 메모리가 충분하지 않다면 프로세스가 거부하거나 대기큐에 넣어서 프로세스가 적재될 `hole`이 생긴다면 프로세스를 실행시킬 수 있다.
74-
- 5를 차지하는 A 프로세스가 `hole(0, 9)` 에 들어가면 `hole(0,4)`에 들어가고 `hole(5, 9)`가 새로운 `hole`이 왼다.
68+
- 프로세스를 메모리의 가변 크기 파티션에 할당
69+
- 각 파티션에는 정확히 하나의 프로세스만 적재
70+
- 운영체제는 사용 가능, 불가능 부분을 나타내는 `hole` 테이블을 유지
71+
- `hole`: 하나의 큰 사용 가능한 메모리 블록
72+
- 메모리가 충분하지 않다면 프로세스가 거부하거나 대기큐에 넣어서 프로세스가 적재될 `hole`이 생긴다면 프로세스를 실행시킬 수 있다.
73+
- 5를 차지하는 A 프로세스가 `hole(0, 9)` 에 들어가면 `hole(0,4)`에 들어가고 `hole(5, 9)`가 새로운 `hole`이 왼다.
7574

7675
**동적 메모리 할당 문제**
7776

78-
- first-fit: `hole` 테이블을 순회하면서 첫 번째로 발견한 가용 공간을 할당
79-
- best-fit: `hole` 테이블을 모두 순회하여 가장 로스가 적은 가용 공간을 할당
80-
- worst-fit: 가장 큰 가용 공간을 할당 => 나머지 가용공간은 새로운 `hole`이 된다.
77+
- first-fit: `hole` 테이블을 순회하면서 첫 번째로 발견한 가용 공간을 할당
78+
- best-fit: `hole` 테이블을 모두 순회하여 가장 로스가 적은 가용 공간을 할당
79+
- worst-fit: 가장 큰 가용 공간을 할당 => 나머지 가용공간은 새로운 `hole`이 된다.
8180

8281
-> first-fit과 best-fit가 가장 비용이 적었다.
8382

84-
#### External Fragmentation
83+
### External Fragmentation
8584

86-
- 프로세스들이 메모리에 적재되고 제거되는 일이 반복되다 보면 어떤 가용 공간은 너무 작은 조각이 되어버리는 문제, 모든 유휴공간을 합치면 충분한 공간이 되지만 여러 곳에 분산되어있을 때 발생
87-
- 가변 파티션 방식은 모두 `External Fragmentation` 문제를 겪음
88-
- first-fit 방식은 `50% rule` => 메모리의 $1/3$ 을 쓸 수 없게 될 수 있음
89-
- 해결책: 모든 메모리를 한 군데로 몰고 모든 가용 공간을 큰 블록을 만드는 `compaction` 방식
90-
- 외부 단편화를 해결할 수 있으나 프로세스들의 재배치가 execution time에 동적으로 이루어지는 경우에만 가능
91-
- 위치를 옮기고 기준 레지스터만 변경 -> 비용이 큼
85+
- 프로세스들이 메모리에 적재되고 제거되는 일이 반복되다 보면 어떤 가용 공간은 너무 작은 조각이 되어버리는 문제, 모든 유휴공간을 합치면 충분한 공간이 되지만 여러 곳에 분산되어있을 때 발생
86+
- 가변 파티션 방식은 모두 `External Fragmentation` 문제를 겪음
87+
- first-fit 방식은 `50% rule` => 메모리의 $1/3$ 을 쓸 수 없게 될 수 있음
88+
- 해결책: 모든 메모리를 한 군데로 몰고 모든 가용 공간을 큰 블록을 만드는 `compaction` 방식
89+
- 외부 단편화를 해결할 수 있으나 프로세스들의 재배치가 execution time에 동적으로 이루어지는 경우에만 가능
90+
- 위치를 옮기고 기준 레지스터만 변경 -> 비용이 큼
9291

93-
#### Internal Fragmentation
92+
### Internal Fragmentation
9493

95-
- 프로세스의 크기에 딱 떨어지는 hole은 없으므로 엄청 작은 단위의 `hole`이 생길 수 있음, 이는 테이블에 기록해야 하기 때문에 더 큰 오버헤드가 됨
96-
- 이 문제 때문에 메모리를 아주 작은 공간들로 분할하여 프로세스가 요청하면 할당을 항상 이 분할된 크기의 배수로 해주는 것이 일반적
94+
- 프로세스의 크기에 딱 떨어지는 `hole` 없으므로 엄청 작은 단위의 `hole`이 생길 수 있음, 이는 테이블에 기록해야 하기 때문에 더 큰 오버헤드가 됨
95+
- 이 문제 때문에 메모리를 아주 작은 공간들로 분할하여 프로세스가 요청하면 할당을 항상 이 분할된 크기의 배수로 해주는 것이 일반적
9796

98-
### 메모리가 불연속적일 때
97+
## 메모리가 불연속적일 때
9998

100-
#### Paging
99+
### Paging
101100

102-
- `frame`: 물리 메모리를 같은 크기의 블록으로 나눈 것
103-
- `page`: `frame`에 대응되는 논리 메모리, 컴퓨터에 따라 4KB ~ 1GB의 크기를 가짐
104-
- 저장장치는 `frame`혹은 `frame`의 묶음인 `cluster`와 동일한 고정 크기 블록으로 나누어짐
105-
- 모든 Logical address는 페이지 번호 `p`와 페이지 오프셋 `d: offset` 두 개의 부분으로 나누어짐
101+
- `frame`: 물리 메모리를 같은 크기의 블록으로 나눈 것
102+
- `page`: `frame`에 대응되는 논리 메모리, 컴퓨터에 따라 4KB ~ 1GB의 크기를 가짐
103+
- 저장장치는 `frame`혹은 `frame`의 묶음인 `cluster`와 동일한 고정 크기 블록으로 나누어짐
104+
- 모든 Logical address는 페이지 번호 `p`와 페이지 오프셋 `d: offset` 두 개의 부분으로 나누어짐
106105

107106
-> 메모리에 대한 프로그래머의 인식이 실제 내용과 다름
108107

@@ -114,6 +113,6 @@
114113

115114
**Internal Fragmentation**
116115

117-
- `page`의 배수로 프로세스에게 공간이 할당되기 때문에 External Fragmentation는 발생하지 않지만 Internal Fragmentation이 일어남
118-
- `page`의 크기가 작아지면 Internal Fragmentation이 완화되지만 page table의 크기가 커짐
119-
- `page`의 크기가 커지면 Internal Fragmentation이 악화되지만 디스크의 처리 속도가 올라감 (프로세스 크기가 올라감에 따라 채택)
116+
- `page`의 배수로 프로세스에게 공간이 할당되기 때문에 External Fragmentation는 발생하지 않지만 Internal Fragmentation이 일어남
117+
- `page`의 크기가 작아지면 Internal Fragmentation이 완화되지만 page table의 크기가 커짐
118+
- `page`의 크기가 커지면 Internal Fragmentation이 악화되지만 디스크의 처리 속도가 올라감 (프로세스 크기가 올라감에 따라 채택)

memory/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Memory

process/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Process

process/context-switching/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Context Switching
2+
1. CPU의 현재 상태를 저장
3+
2. 다음 실행할 프로세스의 상태를 복원
4+
5+
## Context
6+
- `Context`는 CPU 레지스터의 값, 프로세스 상태, 메모리 관리 정보 등을 포함한다.
7+
- `Context`는 PCB(Process Control Block)에 저장된다.

process/interrupt/README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Interrupt
2+
3+
## CPU 동작
4+
1. 명령어를 수행
5+
2. `interrupt request line` 검사
6+
7+
### Interrupt 동작
8+
1. I/O device가 이 라인에 신호를 보내면 CPU가 확인하여 각종 레지스터의 값과 상태정보를 저장한다음 (cs), 메모리 상의 `ISR (Interrupt Handler Routine)`으로 jump
9+
2. `ISR`
10+
1. `interrupt handler`가 interrupt 발생 원인 조사
11+
2. 필요한 작업 수행
12+
3. interrupt 이전으로 복귀 명령

process/ipc/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Inter-Process Communication
2+
3+
`File`, `Signal`, `Socket`, `Message Queue`, `Pipe`, `Shared Memory` 등 다양한 방법으로 프로세스간 통신을 할 수 있다.\
4+
이러한 방법들은 성능, 사용법, 특징 등이 다르기 때문에 상황에 맞게 사용해야 한다.
5+
6+
- [Wikipedia](https://en.wikipedia.org/wiki/Inter-process_communication)
7+
- [Inter Process Communication (IPC) - GeeksforGeeks](https://www.geeksforgeeks.org/inter-process-communication-ipc/)

process/ipc/file/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# File

process/ipc/file/read

50.4 KB
Binary file not shown.

process/ipc/file/read.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <iostream>
2+
#include <fstream>
3+
4+
using namespace std;
5+
6+
const char* FILENAME = "file.txt";
7+
8+
int main(void)
9+
{
10+
fstream rFile(FILENAME);
11+
string s;
12+
if (!rFile.is_open())
13+
{
14+
cout << "Failed to open " << FILENAME << endl;
15+
exit(EXIT_FAILURE);
16+
}
17+
getline(rFile, s);
18+
cout << s << endl;
19+
remove(FILENAME);
20+
rFile.close();
21+
return 0;
22+
}

process/ipc/file/write

44 KB
Binary file not shown.

process/ipc/file/write.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#include <iostream>
2+
#include <fstream>
3+
4+
using namespace std;
5+
6+
const char* FILENAME = "file.txt";
7+
8+
int main(void)
9+
{
10+
fstream wFile(FILENAME, fstream::out);
11+
if (!wFile.is_open())
12+
{
13+
cout << "Failed to open " << FILENAME << endl;
14+
exit(EXIT_FAILURE);
15+
}
16+
wFile << "Hello, File!";
17+
wFile.close();
18+
return 0;
19+
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

ipc/msg-queue/src/receiver.cpp renamed to process/ipc/msg-queue/src/receiver.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
#include <string.h>
66
#include <sys/stat.h>
77

8+
const char* FILENAME = "/myqueue";
9+
810
int main()
911
{
1012
mqd_t mq;
1113
char buffer[256];
1214

1315
// 메시지 큐 열기
14-
mq = mq_open("/myqueue", O_RDONLY);
16+
mq = mq_open(FILENAME, O_RDONLY);
1517
if (mq == -1)
1618
{
1719
perror("mq_open");
@@ -29,6 +31,6 @@ int main()
2931

3032
// 메시지 큐 닫기 및 삭제
3133
mq_close(mq);
32-
mq_unlink("/myqueue");
34+
mq_unlink(FILENAME);
3335
return 0;
3436
}
File renamed without changes.

ipc/msg-queue/src/sender.cpp renamed to process/ipc/msg-queue/src/sender.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
#include <string.h>
66
#include <sys/stat.h>
77

8+
const char* MSG = "Hello, Process 2!";
9+
const char* FILENAME = "/myqueue";
10+
811
int main()
912
{
1013
mqd_t mq;
1114
struct mq_attr attr;
12-
char *msg = "Hello, Process 2!";
1315

1416
// 메시지 큐 속성 설정
1517
attr.mq_flags = 0;
@@ -18,21 +20,21 @@ int main()
1820
attr.mq_curmsgs = 0;
1921

2022
// 메시지 큐 생성 및 열기
21-
mq = mq_open("/myqueue", O_CREAT | O_WRONLY, 0644, &attr);
23+
mq = mq_open(FILENAME, O_CREAT | O_WRONLY, 0644, &attr);
2224
if (mq == -1)
2325
{
2426
perror("mq_open");
2527
exit(1);
2628
}
2729

2830
// 메시지 보내기
29-
if (mq_send(mq, msg, strlen(msg) + 1, 0) == -1)
31+
if (mq_send(mq, MSG, strlen(MSG) + 1, 0) == -1)
3032
{
3133
perror("mq_send");
3234
exit(1);
3335
}
3436

35-
printf("Message sent: %s\n", msg);
37+
printf("Message sent: %s\n", MSG);
3638

3739
// 메시지 큐 닫기
3840
mq_close(mq);

process/ipc/pipe/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Pipe

process/ipc/pipe/client

55.3 KB
Binary file not shown.

process/ipc/pipe/client.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <iostream>
2+
#include <fcntl.h>
3+
#include <unistd.h>
4+
#include <cstring>
5+
#include <sys/stat.h>
6+
7+
const char* FIFO_NAME = "my_fifo";
8+
const int BUFFER_SIZE = 256;
9+
10+
int main() {
11+
// FIFO에 읽기 위한 파일 디스크립터 열기
12+
int fd = open(FIFO_NAME, O_RDONLY);
13+
if (fd == -1) {
14+
perror("open");
15+
return 1;
16+
}
17+
18+
char buf[BUFFER_SIZE];
19+
memset(buf, 0, BUFFER_SIZE);
20+
21+
ssize_t bytesRead = read(fd, buf, BUFFER_SIZE);
22+
if (bytesRead == -1) {
23+
perror("read");
24+
} else {
25+
std::cout << "Received message: " << buf << std::endl;
26+
}
27+
28+
// 파일 디스크립터 닫기
29+
close(fd);
30+
31+
// FIFO 파일 삭제
32+
if (unlink(FIFO_NAME) == -1) {
33+
perror("unlink");
34+
}
35+
36+
return 0;
37+
}

process/ipc/pipe/pipe.cpp

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include <unistd.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
6+
7+
const int READ_END = 0;
8+
const int WRITE_END = 1;
9+
const int BUFFER_SIZE = 16;
10+
11+
int main(void)
12+
{
13+
int fd[2];
14+
if (pipe(fd) == -1)
15+
{
16+
perror("pipe");
17+
}
18+
19+
pid_t pid = fork();
20+
if (pid == -1)
21+
{
22+
perror("fork");
23+
}
24+
25+
if (pid == 0)
26+
{
27+
const char* msg = "Hello, Pipe!";
28+
close(fd[READ_END]);
29+
ssize_t bytesWritten = write(fd[WRITE_END], msg, strlen(msg));
30+
printf("bytesWritten: %ld\n", bytesWritten);
31+
return 0;
32+
}
33+
waitpid(pid, NULL, 0);
34+
close(fd[WRITE_END]);
35+
36+
char buf[BUFFER_SIZE];
37+
memset(buf, 0, BUFFER_SIZE);
38+
39+
ssize_t bytesRead = read(fd[READ_END], buf, BUFFER_SIZE);
40+
printf("%s, %ld\n", buf, bytesRead);
41+
return 0;
42+
}

process/ipc/pipe/server

55.2 KB
Binary file not shown.

0 commit comments

Comments
 (0)