diff --git a/.gitignore b/.gitignore index 6301d17..8b25c74 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,4 @@ yarn-error.log .pnp.js # Yarn Integrity file .yarn-integrity +/package-lock.json \ No newline at end of file diff --git a/contents/posts/operation-system/1/index.md b/contents/posts/operation-system/jc1/index.md similarity index 98% rename from contents/posts/operation-system/1/index.md rename to contents/posts/operation-system/jc1/index.md index 7df4780..520acbf 100644 --- a/contents/posts/operation-system/1/index.md +++ b/contents/posts/operation-system/jc1/index.md @@ -1,5 +1,5 @@ --- -title: "1. 운영체제의 역할과 커널의 기능" +title: "운영체제의 역할과 커널의 기능" description: "운영체제의 역할과 커널의 기능" date: 2025-09-04 update: 2025-09-04 diff --git a/contents/posts/operation-system/10/index.md b/contents/posts/operation-system/jc10/index.md similarity index 75% rename from contents/posts/operation-system/10/index.md rename to contents/posts/operation-system/jc10/index.md index f7c28aa..9689900 100644 --- a/contents/posts/operation-system/10/index.md +++ b/contents/posts/operation-system/jc10/index.md @@ -1,5 +1,5 @@ --- -title: "10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점" +title: "멀티 프로세스와 멀티 쓰레드의 차이 및 장단점" description: "멀티 프로세스와 멀티 쓰레드의 차이 및 장단점" date: 2025-09-13 update: 2025-09-13 @@ -8,11 +8,11 @@ tags: series: "프로세스와 쓰레드에 대해서 알아보기" --- -![img.png](멀티프로세스.png) +![img.png](multi_process.png) -멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술이다. +멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술입니다. 보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해 -여러개의 프로세스를 생성하는 것이다. +여러개의 프로세스를 생성하는 것입니다.

@@ -20,13 +20,13 @@ series: "프로세스와 쓰레드에 대해서 알아보기" ### 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부모 프로세스가 -여러개의 자식 프로세스를 생성한다. +여러개의 자식 프로세스를 생성합니다. 부모 프로세스는 자식 프로세스의 PID를 알고있으며 자식또한 PID와 PPID를 알고있어 -서로 통신이 가능하다. +서로 통신이 가능합니다. 이런 성질은 각각 독립적이지만 통신이 가능하게 만들었고 멀티 프로세스의 대표적인 예가 -브라우저의 탭이라고 할 수 있다. +브라우저의 탭이라고 할 수 있습니다. 브라우저 탭은 문제가 발생해서 닫아야 하는 상황이여도 다른 탭까지 닫히지 않고 개별적으로 운용을 할 수 있는걸 기억해보면 독립적이란 말을 더 잘 이해할 수 있을것이다. @@ -40,10 +40,10 @@ series: "프로세스와 쓰레드에 대해서 알아보기" 1. 안정성 -멀티 프로세스의 안정성은 각각의 프로세스가 독립적이기 떄문에 가능하다. +멀티 프로세스의 안정성은 각각의 프로세스가 독립적이기 떄문에 가능합니다. 대표적인 예로 좀전에 설명을 했던 특정 브라우저 탭이 문제가 발생하여 닫아야 하는 상황에서 -같은 브라우저의 다른 탭까지 닫히지는 않는다. -이런것이 독립적인 성격에 의한 안정성이라고 할 수 있다. +같은 브라우저의 다른 탭까지 닫히지는 않습니다. +이런것이 독립적인 성격에 의한 안정성이라고 할 수 있습니다.

@@ -54,18 +54,18 @@ series: "프로세스와 쓰레드에 대해서 알아보기" 1. 문맥교환 (Context Switching) Overhead -멀티 태스킹을 이루는 기술인 문맥 교환 과정에서 성능 저하가 발생할 수 있다. +멀티 태스킹을 이루는 기술인 문맥 교환 과정에서 성능 저하가 발생할 수 있습니다. 프로세스를 컨텍스트 스위칭 하면, CPU는 다음 프로세스의 정보를 불러오기 위해 메모리를 검색하고, CPU 캐시 메모리를 초기화하며, 프로세스 상태를 저장하고, -불러올 데이터를 준비해야 하기 떄문에, 빈번한 문맥교환이 발생하고 이 비용은 곧 오버헤드로 발생할 수 있다. +불러올 데이터를 준비해야 하기 떄문에, 빈번한 문맥교환이 발생하고 이 비용은 곧 오버헤드로 발생할 수 있습니다.

2. 자원 공유 비효율성 -프로세스는 독립적인 메모리를 가지고, 멀티 프로세스는 독립적인 메모리 공간의 합일 것이다. -그렇기 때문에 메모리 비효율성을 초래한다. +프로세스는 독립적인 메모리를 가지고, 멀티 프로세스는 독립적인 메모리 공간의 합일 것입니다. +그렇기 때문에 메모리 비효율성을 초래합니다.

@@ -74,17 +74,17 @@ series: "프로세스와 쓰레드에 대해서 알아보기" --- -![img.png](멀티스레드.png) +![img.png](multi_thread.png)
-이전에 보았던 것처럼 스레드는 하나의 프로세스 내에 있는 실행 흐름이다. -멀티 스레드는 하나의 프로세스 안에 여러개의 실행흐름을 가지는 것이다. -멀티 스레드 또한 멀티 프로세스 처럼 여러개의 작업을 동시 실행 할 수 있다. +이전에 보았던 것처럼 스레드는 하나의 프로세스 내에 있는 실행 흐름입니다. +멀티 스레드는 하나의 프로세스 안에 여러개의 실행흐름을 가지는 것입니다. +멀티 스레드 또한 멀티 프로세스 처럼 여러개의 작업을 동시 실행 할 수 있습니다. -이전에 보았던 것처럼 멀티 프로세스는 브라우저의 여러개의 탭을 통해 예시를 들었다. +이전에 보았던 것처럼 멀티 프로세스는 브라우저의 여러개의 탭을 통해 예시를 들었습니다. 하지만, 멀티 스레드는 같은 브라우저라 할지라도 동일탭에 여러 실행 흐름을 말하게 되고 -예를들어 네트워크 처리 스레드, 검색 스레드 와 같이 동일한 프로세스 내 기능들을 말하게 된다. +예를들어 네트워크 처리 스레드, 검색 스레드 와 같이 동일한 프로세스 내 기능들을 말하게 됩니다.

@@ -96,8 +96,8 @@ series: "프로세스와 쓰레드에 대해서 알아보기" ### 프로세스보다 스레드가 가벼움 스레드는 프로세스보다 용량이 가볍다. 이유는 데이터, 코드, 힙 영역을 -프로세스와 공유해서 사용하기 때문에 내장된 정보다 프로세스보다 작기 떄문이다. -그렇기 때문에 스레드를 제거하는 작업이 프로세스를 제거하는 작업보다 가볍다. +프로세스와 공유해서 사용하기 때문에 내장된 정보다 프로세스보다 작기 떄문입니다. +그렇기 때문에 스레드를 제거하는 작업이 프로세스를 제거하는 작업보다 가볍습니다.

@@ -105,7 +105,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기" ### 자원의 효율성 멀티 스레드는 하나의 프로세스 내에서 스택영역을 제외한 영역을 공유하기 때문에 -프로세스 간 통신을 사용하지 않고도 자원의 공유가 가능하여 자원을 효율적으로 사용할 수 있다. +프로세스 간 통신을 사용하지 않고도 자원의 공유가 가능하여 자원을 효율적으로 사용할 수 있습니다.

@@ -113,20 +113,20 @@ series: "프로세스와 쓰레드에 대해서 알아보기" ### Context Switching 비용 감소 스레드 문맥 교환 또한 오버헤드가 존재하지만, 프로세스 문맥교환과 비교했을 때, -상대적으로 오버헤드가 적다. +상대적으로 오버헤드가 적습니다. 이유는 프로세스 컨텍스트 스위칭 비용은 스위칭할 때마다 CPU 캐시에 있는 내용을 모두 초기화하고, -새로운 프로세스 정보를 CPU 캐시에 적재해야 하기 떄문이다. -하지만, 스레드 문맥교환은 스레드 개별적인 정보만 교체하면 되기 떄문에 비용이 상대적으로 낮다. +새로운 프로세스 정보를 CPU 캐시에 적재해야 하기 떄문입니다. +하지만, 스레드 문맥교환은 스레드 개별적인 정보만 교체하면 되기 떄문에 비용이 상대적으로 낮습니다.

## 멀티 스레드의 단점 -멀티 프로세스는 개별적인 작업으로 인해 독집적이고, 각자의 문제를 전파하지 않는다고 하였다. +멀티 프로세스는 개별적인 작업으로 인해 독집적이고, 각자의 문제를 전파하지 않는다고 합니다. -하지만, 멀티 스레드는 하나의 스레드가 문제가 발생하면 다른 스레드들고 영향을 받아 전체가 종료가 될 수 있다. +하지만, 멀티 스레드는 하나의 스레드가 문제가 발생하면 다른 스레드들고 영향을 받아 전체가 종료가 될 수 있습니다.

@@ -134,14 +134,14 @@ series: "프로세스와 쓰레드에 대해서 알아보기" ## 데드락 데드락이란 하나의 자원을 사용하기위해 여러 곳에서 접근했고, 그상황에서 교착상태가 일어났을때 -여러대의 스레드가 서로 대기하면서 무한정 기다리는 현상을 데드락이라고 한다. +여러대의 스레드가 서로 대기하면서 무한정 기다리는 현상을 데드락이라고 합니다. -예를들어, 스레드 1 은 자원 A을 점유하고 있는 상태에서 자원 B가 필요한 상황이다. -그리고 스레드 2 는 자원 B를 점유하고 있는 상태에서 자원 A이 필요한 상황이다. +예를들어, 스레드 1 은 자원 A을 점유하고 있는 상태에서 자원 B가 필요한 상황입니다. +그리고 스레드 2 는 자원 B를 점유하고 있는 상태에서 자원 A이 필요한 상황입니다. 하지만 스레드 1은 자원 B가 필요한 상황에서 자원 A을 빌려줄 수 있는 상황이 아니고, -스레드 2또한 자원 A이 필요한 상태에서 자원 B를 빌려줄 수 없는 상황인 것이다. +스레드 2또한 자원 A이 필요한 상태에서 자원 B를 빌려줄 수 없는 상황인 것입니다. 이처럼 다수의 쓰레드가 같은 lock을 동시에, -다른 명령에 의해 획득하려 할 때 서로 절대 불가능한 일을 계속적으로 기다리는 상황을 이야기 한다. +다른 명령에 의해 획득하려 할 때 서로 절대 불가능한 일을 계속적으로 기다리는 상황을 이야기 합니다. diff --git "a/contents/posts/operation-system/10/\353\251\200\355\213\260\355\224\204\353\241\234\354\204\270\354\212\244.png" b/contents/posts/operation-system/jc10/multi_process.png similarity index 100% rename from "contents/posts/operation-system/10/\353\251\200\355\213\260\355\224\204\353\241\234\354\204\270\354\212\244.png" rename to contents/posts/operation-system/jc10/multi_process.png diff --git "a/contents/posts/operation-system/10/\353\251\200\355\213\260\354\212\244\353\240\210\353\223\234.png" b/contents/posts/operation-system/jc10/multi_thread.png similarity index 100% rename from "contents/posts/operation-system/10/\353\251\200\355\213\260\354\212\244\353\240\210\353\223\234.png" rename to contents/posts/operation-system/jc10/multi_thread.png diff --git "a/contents/posts/operation-system/11/\353\217\231\354\213\234\354\204\261\354\235\264\354\212\210.png" b/contents/posts/operation-system/jc11/concurrency.png similarity index 100% rename from "contents/posts/operation-system/11/\353\217\231\354\213\234\354\204\261\354\235\264\354\212\210.png" rename to contents/posts/operation-system/jc11/concurrency.png diff --git a/contents/posts/operation-system/11/index.md b/contents/posts/operation-system/jc11/index.md similarity index 83% rename from contents/posts/operation-system/11/index.md rename to contents/posts/operation-system/jc11/index.md index c1ef596..df8c7dd 100644 --- a/contents/posts/operation-system/11/index.md +++ b/contents/posts/operation-system/jc11/index.md @@ -1,5 +1,5 @@ --- -title: "11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법" +title: "멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법" description: "멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법" date: 2025-09-14 update: 2025-09-14 @@ -15,7 +15,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기"
-![img.png](동시성이슈.png) +![img.png](concurrency.png)
@@ -26,7 +26,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기" 스레드 a가 좋아요 카운트를 늘리면 11가 됩니다. 하지만 스레드 a와 b는 좋아요 카운트에 동시에 접근해서 초기값 10을 받은 상태라면 스레드 b는 늘어난 11라는 숫자대신 10을 기준으로 값을 줄이게 됩니다. 그럼 최종 결과는 10이 아닌 9라는 값으로 나오게 됩니다. -이처럼 멀티 스레드 환경에서는 하나의 자원에 동시에 접근하게 되면 이러한 문제가 발생할 수 있다. +이처럼 멀티 스레드 환경에서는 하나의 자원에 동시에 접근하게 되면 이러한 문제가 발생할 수 있습니다.

@@ -36,7 +36,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기" --- 그럼 우리가 추구해야 할 문제는 스레드 안전한 멀티 스레드 프로그래밍을 구현할 수 있어야 한다. 이것을 구현하는 -방법에 대해 이야기 하려고 한다. +방법에 대해 이야기 하려고 합니다.

@@ -60,7 +60,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기"
-- 공유 자원에 하나의 Thread만 접근할 수 있도록 세마포어/ 뮤텍스락을 통제하는 방법이다. +- 공유 자원에 하나의 Thread만 접근할 수 있도록 세마포어/ 뮤텍스락을 통제하는 방법입니다.
@@ -68,10 +68,10 @@ series: "프로세스와 쓰레드에 대해서 알아보기"
-- 공유 자원에 접근할 때 원자 연산을 이용하거나 원자적으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현하는 방법이다. +- 공유 자원에 접근할 때 원자 연산을 이용하거나 원자적으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현하는 방법입니다. - Atomic - 공유 자원 변경에 필요한 연산을 원자적으로 분리한 뒤에 실제로 데이터의 변경이 이루어지는 시점에 Lock을 걸고, - 데이터를 변경하는 시간 동안 다른 쓰레드의 접근이 불가능하도록 하는 방법이다. + 데이터를 변경하는 시간 동안 다른 쓰레드의 접근이 불가능하도록 하는 방법입니다.
@@ -79,8 +79,8 @@ series: "프로세스와 쓰레드에 대해서 알아보기"
-- 공유 자원의 사용을 최대한 줄이고 각가의 쓰레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는 방법이다. -- 일반적으로 공유 상태를 피할 수 없을 때 사용하는 방식이며, 전역 변수 사용을 자제하라는 뜻으로 생각하면 된다. +- 공유 자원의 사용을 최대한 줄이고 각가의 쓰레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는 방법입니다. +- 일반적으로 공유 상태를 피할 수 없을 때 사용하는 방식이며, 전역 변수 사용을 자제하라는 뜻으로 생각하면 됩니다.
@@ -88,9 +88,9 @@ series: "프로세스와 쓰레드에 대해서 알아보기"
-- 쓰레드 호출과 상관 없이 프로그램에 문제가 없도록 작성하는 방법이다. -- 어떤 함수가 한 스레드에 의해 호출되어 실행 중이라면 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 옳바르게 주어져야 한다. -- 쓰레드끼리 독립적으로 동작할 수 있도록 코드를 작성하는 것으로 생각하면 된다. +- 쓰레드 호출과 상관 없이 프로그램에 문제가 없도록 작성하는 방법입니다. +- 어떤 함수가 한 스레드에 의해 호출되어 실행 중이라면 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 옳바르게 주어져야 합니다. +- 쓰레드끼리 독립적으로 동작할 수 있도록 코드를 작성하는 것으로 생각하면 됩니다.

diff --git a/contents/posts/operation-system/jc12/index.md b/contents/posts/operation-system/jc12/index.md new file mode 100644 index 0000000..2b9e02a --- /dev/null +++ b/contents/posts/operation-system/jc12/index.md @@ -0,0 +1,95 @@ +--- +title: "CPU 스케줄링의 목적과 스케줄러의 종류" +description: "CPU 스케줄링의 목적과 스케줄러의 종류" +date: 2025-09-15 +update: 2025-09-15 +tags: + - 운영체제 +series: "CPU 스케줄링" +--- + +## CPU 할당? + +--- + +지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용 +하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등 +CPU사용에 여러 변수가 있습니다. + +한가지 의문점은, 누가? 어떻게? CPU를 할당하는지 배운적은 없습니다. +여기서 CPU라는 리소스에 대한 사용을 결정짓는건 운영체제입니다. +그리고 오늘 글의 주제인 CPU 스케줄링은 운영체제가 CPU라는 자원을 배분하는 행위를 지칭합니다. + +
+
+ +## CPU 스케줄링 우선순위 + +--- + +![img.png](priority.png) + +운영체제는 많은 프로세스에게 공정하게 CPU라는 공용자원을 배분하기 위해 고려해야 하는것이 우선순위 입니다. +우선순위라는 기준을 매겨야 하는 이유는 +운영체제는 어떤 프로세스는 당장 처리해야 할 중요성을 띄거나, IO작업이 많거나, CPU 사용시간 자체가 길거나처럼 각자의 사정이 있고, 이 사정 가운대 효율적으로 자원을 배분해야 하기 떄문입니다. + +
+ +'우선순위가 높다'라는 표현은 CPU 사용에 우선권을 가집니다. 즉 먼저 처리되어야 한다 라는 뜻입니다. +대표적으로 우선순위가 높은 프로세스는 입출력이 많은 프로세스 입니다. +(입출력 처리가 많은 프로세스가 우선순위가 높은 이유는 아래에서 설명합니다.) + +대부분의 프로세스는 I/O 작업과 CPU처리를 번갈아가면서 수행하게 됩니다. 이 말은 프로세스 상태 변화에서 실행, 대기를 번갈아 가면서 사용한다는 뜻입니다. +그렇지만 모든 프로세스가 동일한 비율로 I/O와 CPU처리를 하는것은 아닙니다. 여기서 CPU작업의 비율이 많다면 **CPU 집중 프로세스**라고 하게 되며, 반대로 I/O작업의 +비율이 많다면 **입출력 집중 프로세스** 라고 부르게 됩니다. + +CPU집중 프로세스는 실행상태가 많고, 입출력 집중 프로세스는 대기 상태가 많으니 입출력 집중 프로세스를 빠르게 대기 상태로 넘겨주는 것이 CPU사용에 대해서 더 효율적인 +방법일것입니다. 그렇기 떄문에 입출력 처리가 많은 프로세스가 우선순위가 높습니다. + +여담으로, CPU를 이용하는 작업을 **CPU 버스트**, 입출력을 이용하는 작업을 **입출력 버스트**라고 부르게 됩니다. + +
+
+ +이러한 우선순위는 **PCB**에 기록됩니다. **PCB** 우선순위 기준으로 먼저 처리할 프로세스를 결정하고 처리하게 됩니다. + +
+
+ +## 스케줄링 큐 + +--- + +![img.png](queue_scheduling.png) + +우선순위는 **PCB**에 기록되지만, 운영체제가 매 CPU 할당 과정마다 **PCB**를 확인하고 결정하는건 비효율 적인 방식입니다. +그렇기 때문에 프로세스는 마치 '줄을 서는것'처럼 대기하게 됩니다. 이것을 **스케줄링 큐**라고 부르게 됩니다. + +
+ +![img.png](ready_queue.png) + +
+ +운영체제는 메모리로 적재되고 싶은 프로세스들을 큐에 삽입하여 줄을 세우고, CPU를 사용하고 싶거나, 특정 입출력장치를 사용하거 싶은 프로세스들을 줄세웁니다. +이 과정에서 사용할 자원에 따라 다른 큐에서 대기하게 됩니다. + +운영체제가 관리하는 큐로는 **준비큐**와 **대기큐**로 이루어 져 있습니다. **준비 큐**는 말그대로 CPU를 이용하고 싶은 프로세스들이 대기하게 되고, + +
+ +![img.png](wait_queue.png) + +
+ +**대기 큐**는 +입출력장치를 이용하기 위한 대기 상태에 돌입한 프로세스들이 서는 줄입니다. +큐에 들어와 있다고 해도 항상 순서대로 작동하는 것은 아니고 **우선 순위**를 고려합니다. + +
+ +## 출처 + +--- + +[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard) diff --git a/contents/posts/operation-system/jc12/priority.png b/contents/posts/operation-system/jc12/priority.png new file mode 100644 index 0000000..4cdb917 Binary files /dev/null and b/contents/posts/operation-system/jc12/priority.png differ diff --git a/contents/posts/operation-system/jc12/queue_scheduling.png b/contents/posts/operation-system/jc12/queue_scheduling.png new file mode 100644 index 0000000..ea542d1 Binary files /dev/null and b/contents/posts/operation-system/jc12/queue_scheduling.png differ diff --git a/contents/posts/operation-system/jc12/ready_queue.png b/contents/posts/operation-system/jc12/ready_queue.png new file mode 100644 index 0000000..9378e7e Binary files /dev/null and b/contents/posts/operation-system/jc12/ready_queue.png differ diff --git a/contents/posts/operation-system/jc12/wait_queue.png b/contents/posts/operation-system/jc12/wait_queue.png new file mode 100644 index 0000000..eba9c94 Binary files /dev/null and b/contents/posts/operation-system/jc12/wait_queue.png differ diff --git a/contents/posts/operation-system/jc13/index.md b/contents/posts/operation-system/jc13/index.md new file mode 100644 index 0000000..e4e4bff --- /dev/null +++ b/contents/posts/operation-system/jc13/index.md @@ -0,0 +1,114 @@ +--- +title: "선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법" +description: "선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법" +date: 2025-09-16 +update: 2025-09-16 +tags: + - 운영체제 +series: "CPU 스케줄링" +--- + +## 선점형? 비선점형? 개요 + +--- + +**CPU 스케줄링**은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다. + +여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다. + +
+
+ +## 선점형 스케줄링 + +--- + +> 선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다. + +즉, 어떤 프로세스가 CPU라는 자원을 사용하고 있음에도 운영체제가 CPU를 사용중인 프로세스로부터 자원을 강제로 빼앗아 다른 프로세스에 할당할 수 있는 +스케줄링 방식을 의미합니다. + +다르게 표현한다면 어떠한 프로세스도 CPU를 독점할 수 없다는 말입니다. + +선점형의 예시중 하나는 지금까지 보았던, 특정 주기마다 CPU에 대한 할당 권한을 다른 프로세스에게 넘겨주는 방식이 있습니다. + +
+ +![img.png](preemptive.png) + +
+
+ +## 비 선점형 스케줄링 + +--- + +비선점형 스케줄링이란 하나의 프로세스가 자원을 사용하고 있다면 그 프로세스가 종료되거나 +스스로 대기 상태에 접어들기 전까진 다른 프로세스가 끼어들 수 없는 스케줄링입니다. + +다르게 표현한다면 특정 프로세스가 CPU를 사용하기 시작했다면 자원 사용을 독점할 수 있는 방식입니다. + +
+ +![img.png](non_preemptive.png) + +
+
+ +## 선점, 비선점의 장 단점 + +--- + +대부분의 운영체제는 **선점형 스케줄링**를 사용중입니다. 그럼에도 **비선점형 스케줄링**를 사용하는 곳이 있는데 그것은 각자의 장 단점이 존재하기 때문입니다. + +
+ +- 선점형 스케줄링 장점 + +> 선점형 스케줄링은 어는 한 프로세스의 자원 독점을 막고 프로세스들에 골고루 자원을 분배 할 수 있다는 장점이 있습니다. + +
+ +- 선점형 스케줄링 단점 + +> 콘텍스트 스위칭이 빈번하기 떄문에 오버헤드가 많이 발생합니다. + +
+
+ +- 비 선점형 스케줄링 장점 + +> 상대적으로 선점형 보다 콘텍스트 스위칭에 대한 오버헤드가 작게 발생합니다. + +
+ +- 선점형 스케줄링 단점 + +> 하나의 프로세스가 작업이 끝나기를 기다려야 하기 때문에, 모든 프로세스가 골고루 자원을 사용할 수 없습니다. + + +
+
+ +## 기아 상태(Starvation) + +--- + +기아 상태란 우선순위가 밀린 프로세스가 영원히 자신의 우선순위까지 순서가 오지 못해 실행되지 못하는 상태를 기아 상태라고 합니다. + +
+
+ +## 기아 상태 해결법 + +--- + +이러한 기아 상태를 해결하기 위한 방법으로는 + +**에이징** 기법을 활용하는 것입니다. + +기아 상태가 발생하는 이유는 항상 자신보다 높은 우선순위를 가지는 프로세스가 존재하기 떄문입니다. + +**에이징** 기법은 준비큐에서 대기가 길어진 프로세스들에게 우선순위를 조금씩 높여주는 방식을 사용합니다. +결국 조금씩 우선순위가 높아진다면 언젠가는 해당 프로세스가 실행될 수 있게 됩니다. + diff --git a/contents/posts/operation-system/jc13/non_preemptive.png b/contents/posts/operation-system/jc13/non_preemptive.png new file mode 100644 index 0000000..3c6b6db Binary files /dev/null and b/contents/posts/operation-system/jc13/non_preemptive.png differ diff --git a/contents/posts/operation-system/jc13/preemptive.png b/contents/posts/operation-system/jc13/preemptive.png new file mode 100644 index 0000000..e7cedcd Binary files /dev/null and b/contents/posts/operation-system/jc13/preemptive.png differ diff --git a/contents/posts/operation-system/jc14/fcfs.png b/contents/posts/operation-system/jc14/fcfs.png new file mode 100644 index 0000000..651e08e Binary files /dev/null and b/contents/posts/operation-system/jc14/fcfs.png differ diff --git a/contents/posts/operation-system/jc14/index.md b/contents/posts/operation-system/jc14/index.md new file mode 100644 index 0000000..8456174 --- /dev/null +++ b/contents/posts/operation-system/jc14/index.md @@ -0,0 +1,178 @@ +--- +title: "CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)" +description: "CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)" +date: 2025-09-17 +update: 2025-09-17 +tags: + - 운영체제 +series: "CPU 스케줄링" +--- + +## 스케줄링 알고리즘 개요 + +--- + +스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다. + +
+ +- 비선점 스케줄링 + - 선입 선처리 스케줄링 (FCFS) + - 최단 작업 우선 스케줄링 (SJF) + +
+ +- 선점 스케줄링 + - 라운드 로빈 스케줄링 + - 최소 잔여 시간 우성 스케줄링 (SRT) + - 우선순위 스케줄링 + +
+ +# 비 선점 스케줄링 + +
+
+ +## 선입 선처리 스케줄(FCFS) + +--- + +![img.png](fcfs.png) + +
+ +FCFS는 **준비 큐**에 들어가있는 순서대로 CPU를 할당하는 간단한 스케줄링 입니다. + +하지만, FCFS 방식에는 **호위 효과**라는 문제가 있습니다. + +그림을 보면 프로세스 A, B, C순서대로 실행되며 각각 실행 시간이 17, 5, 2 ms가 걸리게 됩니다. +이상황에서 프로세스 B는 실행 상태가 되기 위해 최소 17ms를 기다려야 하며, 프로세스 c는 22ms를 기다리게 됩니다. + +> 이러한 현상을 **호위 효과(Convoy effect)** 라고 하며 이것이 FCFS 스케줄링의 단점입니다. + +
+
+ +하지만, 이러한 FCFS 방식도 배치 처리 시스템이나 작업 길이가 거의 비슷하고 사용자와 상호 작용이 필요하지 않는 환경에는 +적합하며, 멀티프로그래밍이나 실시간 시스템에서는 부적합합니다. + +
+
+ +## 최단 작업 우선 스케줄링(SJF) + +--- + +![img.png](sjf.png) + +
+ +최단작업 우선 스케줄링(SJF)는 이전 FCFS방식에서 **호위 효과**를 억제하기 위해 사용하는 방식입니다. + +**호위 효과**는 실행시간이 긴 프로세스 때문에 다른 프로세스가 기다리는 시간이 길다는 문제가 있고, +이러한 문제를 실행시간이 짧은 프로세스를 먼저 시행되게 하여 해결하는 방식입니다. + +그림을 통해 보면 FCFS방식의 평균 대기시간은 13ms인 반면에 SJF방식의 편균대기 시간은 3ms로 줄어든것을 +확인할 수 있습니다. + +> 즉 SJF방식은 호위효과를 줄여 프로세스들의 평균대기시간을 줄이는 방법으로 이해하면 됩니다. + +하지만, 이러한 방식도 문제가 있는데, 실행 시간이 긴 프로세스가 **기아**상태에 빠지기 쉽다는 것입니다. + +이러한 방식은 평균 대기 시간을 중요하게 여기는 시스템에 적합하며, 실시간 시스템이나 사용자 대화형 시스템에 부적합하게 됩니다. + +
+
+ +# 선점 스케줄링 + +
+
+ +## 라운드 로빈 스케줄링 + +--- + +![img.png](round_robin.png) + +
+ +라운드 로빈 스케줄링은 선입 선처리 방식(FCFS)방식에서 **타임 슬라이스**가 더해진 방식입니다. +여기서 말하는 **타임 슬라이스**는 CPU를 사용할 수 있는 정해진 시간을 의미합니다. + +그림에서처럼 타임 슬라이스가 4ms이면 한번에 4ms까지 CPU를 할당받을 수 있고, 그 이후는 큐 가장 뒤로 들어가며 +콘텍스트 스위칭이 일어나게 됩니다. + +
+ +> 라운드 로빈 방식의 중요한 포인트는 **슬라이스 크기**입니다. + +만약 슬라이스 크기가 지나치게 크다면 **FCFS**방식과 다를게 없을 것이고, 지나치게 작다면 콘텍스트 스위칭으로 인한 +오버헤드가 많이 발생할 것입니다. + +
+
+ +## 최소 잔여 시간 우선 스케줄링 (SRT) + +--- + +![img.png](srt.png) + +
+ +최단 작업 우선 알고리즘(SJF) 그리고 라운드 로빈 알고리즘을 합친 형태입니다. +즉 작업 시간이 짧은 프로세스를 먼저 실행하되, 타임슬라이스 보다 큰 프로세스는 다시 큐 뒤로 보내고 작업을 이어가는 방식입니다. + +위 알고리즘은 특이한 점이 있어서 상세히 설명하겠습니다. + +
+ +### SRT 동작 방식 + +1. 새로운 프로세스가 도착하면 그 프로세스의 남은 실행 시간을 계산합니다 +2. 준비 큐에 있는 프로세스 중에서 현재 실행 중인 프로세스를 포함하여 가장 짧은 실행 시간을 가진 프로세스에 CPU를 할당합니다 +3. 만약 새로운 프로세스가 도착하고 현재 실행 중인 프로세스 보다 남은 실행 시간이 더 짧다면 현재 프로세스는 중단되고 CPU는 새 프로세스에 할당되는 '선점'이 발생합니다. +4. 선점이 발생하면 운영체제는 콘텍스트 스위칭으로 CPU자원을 현재 프로세스에서 새 프로세스로 교체합니다. +5. 선점된 프로세스는 준비 큐로 이동합니다. + +
+ +SRT또한 SJF와 비슷한 장 단점을 공유하는데, 평균 대기 시간을 최소화 하는 장점을 가지지만, 작업 시간이 긴 +프로세스는 CPU 할당을 받기 어렵다는 단점이 있습니다. + +
+
+ +## 우선 순위 스케줄링 + +--- + +우선순위 스케줄링은 우선순위를 부여하고, 가장 높은 우선순위를 가진 프로세스부터 실행하는 알고리즘 입니다. +만약 같은 우선순위가 있다면 선입 선처리로 처리 됩니다. + +이러한 우선순위 알고리즘 방식은 기아(Starvation) 현상을 동반하며 이는 에이징 방식으로 해결가능 하다고 이전 파트에서 설명했으니 +넘어가겠습니다. + + + + + + + + + +## 출처 + +--- + +[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard) + +[SRT 출처](https://devshovelinglife.tistory.com/977) + + + + + + diff --git a/contents/posts/operation-system/jc14/round_robin.png b/contents/posts/operation-system/jc14/round_robin.png new file mode 100644 index 0000000..a81078a Binary files /dev/null and b/contents/posts/operation-system/jc14/round_robin.png differ diff --git a/contents/posts/operation-system/jc14/sjf.png b/contents/posts/operation-system/jc14/sjf.png new file mode 100644 index 0000000..da9e968 Binary files /dev/null and b/contents/posts/operation-system/jc14/sjf.png differ diff --git a/contents/posts/operation-system/jc14/srt.png b/contents/posts/operation-system/jc14/srt.png new file mode 100644 index 0000000..d2fa54e Binary files /dev/null and b/contents/posts/operation-system/jc14/srt.png differ diff --git a/contents/posts/operation-system/jc15/index.md b/contents/posts/operation-system/jc15/index.md new file mode 100644 index 0000000..e43564d --- /dev/null +++ b/contents/posts/operation-system/jc15/index.md @@ -0,0 +1,95 @@ +--- +title: "멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링" +description: "멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링" +date: 2025-09-18 +update: 2025-09-18 +tags: + - 운영체제 +series: "CPU 스케줄링" +--- + +## 다단계 큐 스케쥴링(Multilevel queue scheduling) + +--- + +멀티 레벨 스케줄링은 **우선순위** 스케줄링의 발전된 형태입니다. +아래 그림을 통해 설명 하면, + +
+ +![img.png](multilevel_queue.png) + +
+ +이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데, +멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다. + +가장 높은 우선순위에 있는 큐들을 처리하고, 가장 높은 우선순위 큐가 비게 된다면 그 아래 우선순위의 큐를 처리하게 됩니다. +그림을 통해 이해하자면, 우선순위 0 -> 우선순위 1 -> 우선순위 2 이렇게 처리하게 되는것입니다. + +멀티레벨 큐의 특징으로는 각각의 큐들을 개별적으로 핸들링 할 수 있습니다. +예를들어, 특정 큐의 타임 슬라이드와 다른 큐의 타임 슬라이드를 다르게 처리 한다던가, 혹은 스케줄링 방식 자체를 +FCFS를 적용하고 다른 곳에서는 라운드로빈을 적용하는것 처럼 개별적인 핸들링이 가능합니다. + +
+
+ +### 다단계 큐 스케쥴링 문제점 + +--- + +다단계 큐 스케줄링의 문제점으로는 **기아** 현상이 있습니다. + +멀티레벨 큐 방식에서는 큐간의 이동이 불가능합니다. 그렇기 떄문에 우선순위가 낮은 곳에 배정받은 프로세스들은 +이전에 보았던 **에이징**방식을 사용할수 없습니다. 그렇기 때문에 이러한 방식은 우선순위가 올때 까지 기다려야 하는 +기아 현상을 문제로 가지고 있습니다. + +이러한 방식의 해결법은 아래 설명할 다단계 피드백 큐 스케줄링으로 해결이 가능합니다. + +
+
+ +## 다단계 피드백 큐 스케줄링(multilevel feedback queue scheduling) + +--- + +![img.png](multi_feedback_queue.png) + +
+ +다단계 피드백 큐 스케줄링 같은경우는 프로세스들이 큐 사이로 이동할 수 있습니다. 그렇기 때문에 이전 방식에서 보았던 +**기아**현상을 직접적으로 해결할 수 있습니다. + +
+ +### 다단계 피드백 큐 스케줄링 특징 + + +이러한 이동가능한 점 때문에 **멀티 레벨 큐**와 다른 점이 있습니다. +**멀티 레벨 피드백 큐**는 처음 생성된 프로세스가 우선순위가 가장 높은 큐로 삽입이 됩니다. 그 이후 CPU를 할당받고 +타임슬라이드 동안 실행되며, 이 실행이 끝나게 된다면 다음 우선순위 큐로 넘어 갑니다(우선순위가 낮아짐). 또 다음 우선순위 +큐에서 실행이 끝나지 않는다면 또 다음 우선순위로 넘어가고 이 과정을 반복합니다. + +이렇게 우선순위가 낮아지는 방식을 사용함으로써 자동으로 **CPU 버스트**가 많은 프로세스는 우선순위가 낮아지고, +**IO 버스트**가 많은 프로세스는 상대적으로 우선순위가 높아질것입니다. + +### 기아 해결 + +또한, 프로세스들이 이동가능 하기 때문에 우선순위가 낮아져 **기아**상태에 빠진 프로세스에는 **에이징**기법을 적용해 +다시 우선순위를 높이게 됩니다. + + + + + + + + + + + + + + + + diff --git a/contents/posts/operation-system/jc15/multi_feedback_queue.png b/contents/posts/operation-system/jc15/multi_feedback_queue.png new file mode 100644 index 0000000..03ff975 Binary files /dev/null and b/contents/posts/operation-system/jc15/multi_feedback_queue.png differ diff --git a/contents/posts/operation-system/jc15/multilevel_queue.png b/contents/posts/operation-system/jc15/multilevel_queue.png new file mode 100644 index 0000000..b5609b0 Binary files /dev/null and b/contents/posts/operation-system/jc15/multilevel_queue.png differ diff --git a/contents/posts/operation-system/jc16/concurrency.png b/contents/posts/operation-system/jc16/concurrency.png new file mode 100644 index 0000000..0cf559d Binary files /dev/null and b/contents/posts/operation-system/jc16/concurrency.png differ diff --git a/contents/posts/operation-system/jc16/execution_order.png b/contents/posts/operation-system/jc16/execution_order.png new file mode 100644 index 0000000..92b6abe Binary files /dev/null and b/contents/posts/operation-system/jc16/execution_order.png differ diff --git a/contents/posts/operation-system/jc16/index.md b/contents/posts/operation-system/jc16/index.md new file mode 100644 index 0000000..13593e6 --- /dev/null +++ b/contents/posts/operation-system/jc16/index.md @@ -0,0 +1,120 @@ +--- +title: "병행성과 병렬성의 차이 및 프로세스 동기화의 필요성" +description: "병행성과 병렬성의 차이 및 프로세스 동기화의 필요성" +date: 2025-09-19 +update: 2025-09-19 +tags: + - 운영체제 +series: "프로세스 동기화" +--- + +## 병행성(Concurrency) + +--- + +![img.png](concurrency.png) + + +병행성은 다른 말로 **동시성**이라고 부르는 용어입니다. +이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 **컨텍스트 스위칭**을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다. +이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실행되는 것은 아닙니다. + +동시성의 핵심 키워드는 **동시에 처리되게 보이는것**입니다. + +
+
+ +## 병렬성(Parallelism) + +--- + +![img.png](parallelism.png) + +병렬 처리는 프로그램의 독립적인 작업을 동시에 실행할 수 있는 능력입니다. 이러한 작업은 +다른 프로세스 코어 단위에서, 혹은 분산 시스템 처럼 완전히 다른 컴퓨터에서 동시에 실행될 수 도 있습니다. + +병렬성의 핵심 키워드는 **실제로 동시에 처리되고 있는것**입니다. + + +
+
+ +## 동기화 + +--- + +동시다발적으로 실행되는 프로세스들은 공동의 목적을 수행하기 위해 서로 협력하며 영향을 주고 받기도 합니다. +조금 전 설명했던 **동시성**, **병렬성** 모두 동시다발적으로 수행되는 환경입니다. + +이런 환경의 예시를 하나들면, 워드 프로세스가 있습니다. 해당 프로세스는 글을 쓸수도 있고, 쓰여진 글을 읽을 수도 있고, +맞춤법을 검사하는 기능도 있습니다. 하지만 해당 프로세스가 따로 동작하는 것이 아닌 모두 하나의 프로그램처럼 보여지고 있습니다. + +이런 상황을 **동시 다발적**이란 표현을 통해 하고, 이런 동시 다발적인 상황의 **수행 시기**를 맞춰주는 것이 +**동기화**라고 합니다. + +
+ +### 수행 시기를 맞추다? + +이전에 설명한 **수행 시기**를 맞추다는 말은 추상적입니다. + +이를 두가지 관점으로 볼 수 있습니다. + +1. 실행 순서 제어: 프로세스를 올바른 순서대로 실행하는것 +2. 상호 배제: 동시에 접근해서는 안 되는 자원에 하나의 프로세스만 접근하는 것 + +다시 말해 **동기화**는 실행 순서를 제어하는 **동기화**와, **상호 배제**를 위한 동기화가 있습니다. + +
+
+ +## 1. 실행 순서를 제어하는 동기화 + +--- + +![img.png](execution_order.png) + +실행 순서를 제어한다는 것은 요리 레시피 순서를 지키는것과 같습니다. +재료를 준비하고, 손질하고, 요리하는 이런 일련의 과정을 지켜 보았을 때 +재료 손질이 준비보다 먼저일 수 없고, 요리또한 손질보다 먼저일 수 없습니다. + +프로세스도 마찬가지로 무언가를 읽게 하였는데 읽은 대상이 생성 되어있고, 작성되어있어야 합니다. +이런 것을 **실행 순서**라고 표현하며 이것을 지키게 하는 것을 **동기화**라고 표현합니다. + + +
+
+ +## 2. 상호 배제를 위한 동기화 + +--- + +**상호 배제**란 공유가 불가능한 자원의 동시 사용을 피하기 위해 사용하는 알고리즘입니다. +여기서 말하는 공유가 불가능한 자원은 실제로 공유하면 안되는 자원이 아닌, 동시 사용하는 경우 문제가 발생하는 +자원입니다. + +아래 예시를 통해서 보면 + +![img.png](mutual_exclusion.png) + +프로세스A는 현재 잔고에서 2만원을 더하고, 프로세스B는 현재 잔고에서 5만원을 더합니다. +이러한 경우 총합 7만원을 더하는 형태가 될것입니다. + +하지만 프로세스A가 값을 더하고(12만원) 저장하기 전에 **콘텍스트 스위칭**이 일어난다면 다음 프로세스B는 +저장하기 전 값을 조회하고(10만원) 자신의 값을 저장할것 입니다(15만원). +다시 프로세스 A로 돌아오면 12만원을 저장하고 프로세스 B로 돌아오면 15만원을 저장합니다. +이과정에서 서로의 결과를 무시하는 방향으로 진행되고 최종적으로 마지막에 저장한 값은 다른 프로세스의 결과를 +반영하지 않는 상태가 됩니다. + +이런 상황은 동시에 사용하는 자원에 대해 **동기화**를 이루지 못해서 발생한 경우이고, 이 경우 **상호 배제를 위한 동기화** +를 진행해야 합니다. + +
+
+ +## 출처 + +--- + +[동시성, 병렬성 출처](https://www.baeldung.com/cs/concurrency-vs-parallelism) +[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard) diff --git a/contents/posts/operation-system/jc16/mutual_exclusion.png b/contents/posts/operation-system/jc16/mutual_exclusion.png new file mode 100644 index 0000000..634cc9c Binary files /dev/null and b/contents/posts/operation-system/jc16/mutual_exclusion.png differ diff --git a/contents/posts/operation-system/jc16/parallelism.png b/contents/posts/operation-system/jc16/parallelism.png new file mode 100644 index 0000000..8593154 Binary files /dev/null and b/contents/posts/operation-system/jc16/parallelism.png differ diff --git a/contents/posts/operation-system/jc17/critical_section.png b/contents/posts/operation-system/jc17/critical_section.png new file mode 100644 index 0000000..1e00829 Binary files /dev/null and b/contents/posts/operation-system/jc17/critical_section.png differ diff --git a/contents/posts/operation-system/jc17/index.md b/contents/posts/operation-system/jc17/index.md new file mode 100644 index 0000000..5f1be8b --- /dev/null +++ b/contents/posts/operation-system/jc17/index.md @@ -0,0 +1,60 @@ +--- +title: "임계구역과 경쟁상태" +description: "임계구역과 경쟁상태" +date: 2025-09-20 +update: 2025-09-20 +tags: + - 운영체제 +series: "프로세스 동기화" +--- + +### 공유자원 + +--- + +동시에 실행되는 프로세스에서 **공통**으로 사용하는 자원을 우리는 **공유자원**이라고 부릅니다. + +
+
+ +## 임계구역(Critical Section) + +--- + +공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 **임계 구역**이라고 부릅니다. + +두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한 프로세스의 +작업이 마무리되면 그제서야 기다렸던 프로세스가 임계 구역에 진입 합니다. + +![img.png](critical_section.png) + + +
+
+ +## 경쟁상태(Race Condition) + +--- + +**임계 구역**은 두 개 이상의 프로세스가 동시에 실행되면 안 되는 영역이지만, 잘못된 실행으로 여러 프로세스가 +**공유 자원**을 사용하는 경우에 문제가 발생합니다. +이러한 문제를 **경쟁 상태**라고 합니다. + +이러한 **경쟁 상태**는 데이터의 일관성이 깨지는 문제를 발생시킵니다. + +
+
+ +## 운영체제가 임계구역 문제를 해결하는 세가지 원칙 + +--- + +### 1. 상호배제: 한 프로세스가 임계 구역에 진입했다면 다른 프로세스가 들어올 수 없다. +### 2. 진행: 임계구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세는 들어갈 수 있어야 한다. +### 3. 유한 대기: 한 프로세스가 임계구역에 진입하고 싶다면 언젠가는 임계구역에 들어갈 수 있어야 한다.(무한정 대기x) + +## 출처 + +--- + +[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard) diff --git a/contents/posts/operation-system/jc18/index.md b/contents/posts/operation-system/jc18/index.md new file mode 100644 index 0000000..5c8619c --- /dev/null +++ b/contents/posts/operation-system/jc18/index.md @@ -0,0 +1,252 @@ +--- +title: "상호배제와 동기화 기법" +description: "상호배제와 동기화 기법" +date: 2025-09-21 +update: 2025-09-21 +tags: + - 운영체제 +series: "프로세스 동기화" +--- + +## 상호배제(Mutual Exclusion) + +--- + +상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다. + +일상생활에서 비유하면, 화장실 사용과 같습니다. +한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다. +컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 프로세스만 사용할 수 있어야 합니다. + +
+ +## 왜 상호배제가 필요할까? +현대 운영체제는 멀티태스킹 환경에서 여러 프로세스가 동시에 실행됩니다. +이때 프로세스들이 공유하는 자원(메모리, 파일, 데이터베이스 등)에 동시에 접근하면 다음과 같은 문제가 발생할 수 있습니다. + +### 1.경쟁 상황(Race Condition) + +두 프로세스가 동시에 같은 데이터를 수정하려 할 때, 실행 순서에 따라 결과가 달라지는 상황입니다. +예를 들어, 은행 계좌 잔액을 동시에 업데이트하는 두 거래가 있다면, 최종 잔액이 예상과 다를 수 있습니다. + +### 2. 데이터 일관성 파괴 + +여러 프로세스가 동시에 데이터를 수정하면 데이터의 무결성이 깨질 수 있습니다. 이는 시스템 전체의 신뢰성에 큰 영향을 미칩니다. + +
+
+ +## 동기화 기법 + +--- + +이런 **상호 배제**에 대해 방지하는 방법으로는 **뮤텍스**, **세마포어**, **모니터** 기법이 있습니다. + +
+
+ +## 뮤텍스 락(Mutex lock) + +--- + +**뮤텍스 락**의 풀네임은 **Mutual Exclusion Lock**입니다. 즉 상호 배제 단어에 lock을 붙인 단어와 일치합니다. + +이 말은 상호배제를 구현하기 위해 **Locking**방식을 사용하는 방법입니다. + +**뮤텍스 락**은 화장실 사용에 비유해보겠습니다. + +![img.png](toilet.png) + +
+ +화장실은 한칸에 한사람만 받을 수 있습니다. 칸에 사람이 들어가있다면 해당 칸에 다른 사람이 들어올 수 없습니다. +다른 사람이 들어오는 시점은 먼저 사용하던 사람이 해당 칸을 나가게 되면 사용할 수 있습니다. + +이 내용을 설명하는 이유는, 위 방식의 흐름이 뮤텍스 락과 동일하기 때문입니다. + +간단한 **뮤텍스락**을 코드를 통해서 보겠습니다. + +**자물쇠**에 해당하는 전역변수 하나, 그리고 해당 **자물쇠**를 잠구고, 푸는 두가지 함수만 있으면 구현가능합니다. + +
+
+ +````java +acquire(){ + while (lock == true){ + ..... + } + + lock = true; +} +```` + +````java +release(){ + lock = false; + } +```` + +
+ +해당 함수들은 차례대로 화장실 문이 잠겼는지 확인하고 잠기지 않았다면 들어가서 잠구는 함수 **Acquire**, +그리고 화장실을 나올때 잠금을 해제 하는 **Release**로 볼 수 있습니다. + +이 함수를 아래 수도코드 처럼, 임계 구역 들어가기전, 나온 후 에 사용하게 되면 + +````java +acquire(); +// 임계 구역 +release(); +```` + +**lock**여부를 확인 한 후, 들어가도 되면 본인이 **lock**을 걸고 이미 **lock**이 걸려있다면 +임계 구역 코드 전에서 계속 기다리게 됩니다. + +
+ +### 뮤텍스 락의 단점 + + +하지만, 이런 방식에는 큰 문제가 있는데 **바쁜대기(Busy Wait)** 을 수행하게 됩니다. +명칭 그대로 대기를 하는 상황임에도 바쁘게 행동하는 것을 말하게 됩니다. + +**대기**를 하는 상황에 행동을 하는것은 **lock 확인**작업에 **CPU**를 사용하겠다는 것을 의미하고, +이런 기다림은 해당 **lock** 이 풀릴떄까지 지속됩니다. 즉, 비효율적입니다. + +
+
+ +## 세마포(semaphore) + +--- + +**세마포**는 동기화 방식중 하나입니다. **뮤텍스 락**과 비교하면 공유자원의 갯수를 다루는 방식이 다릅니다. +**뮤텍스 락**은 공유자원이 하나라고 가정하고 라킹을 수행하지만, **세마포**는 공유 자원이 여러 개 있을경우 +각 프로세스는 해당 공유자원에 접근이 가능합니다. + +마치 공중화장실에서 화장신 칸 수 만큼 공유자원이 있고, 각 칸에 사람이 들어가는 것을 관리하는 방식입니다. + +![img.png](semaphore.png) + +**세마포**는 사진과 같은 **철도 신호기**에서 유래한 단어 입니다. 그렇기 때문에 철도 신호와 같은 방식을 사용합니다. + +**뮤텍스 락**은 공유 자원을 **잠금**, **해제**를 수행하면서 해당 자원을 관리하지만, + +**세마포**의 경우 **빨간불**, **초록불** 처럼 가도 되는지, 멈춰야 하는지 상태를 알려줍니다. + +**세마포**도 간단하게 코드로 구현이 가능합니다. + +먼저 **공유자원의 갯수**를 나타내는 전역 변수 한개와, 임계구역에 들어가도 되는지, 기다려야 할지 알려주는 함수 **Wait**, +그리고 기다리고 있는 프로세스에게 **이제 출발하라**를 나타내는 **Signal**함수가 있습니다. + +
+ +````java +wait() { + while(S <= 0){ + + } + S--; +} +```` + +````java +signal() { + S++; +} +```` + +위 코드를 차례대로 **Wait**, **Signal**함수를 구현한것이고 전역 변수 S의 값이 양수, 즉 사용해도 되는 +공유자원이 있을 경우 **Wait**함수의 while문을 탈출합니다. + +그 경우 사용가능한 공유 자원 갯수를 하나 줄입니다. + +````java +wait(); +// 임계 구역 +signal(); +```` + +임계 구역을 나오게 되면 signal이 수행될것이고, 사용가능한 자원을 하나 반납하게 될것입니다. + +
+ +근데 while문이 있다면 **뮤텍스락**처럼 **바쁜 대기** 상태가 발생할 수 있다는걸 암시하게 됩니다. +하지만 이는 세마포가 **CPU**를 사용하지 않게 구현하며 해결할 수 있습니다. + +
+ +## 세마포가 busy wait를 해결하는 방법 + +--- + +아래 두가지 함수를 통해서 세마포는 **busy wait**를 해결합니다. + +````java +wait(){ + S--; + if ( S < 0){ + add this process to Queue; + sleep(); + } +} +```` + +````java +signal(){ + S++ + if ( S <= 0){ + remove a process p from Queue; + wakeup(p); + } +} +```` +위 방식은 이전처럼 while문을 통한 접근 가능여부를 체크하는 것이 아닌 만약 접근 불가능 한경우(사용가능한 공유 자원이 없을떄) +해당 프로세스의 **PCB**를 **세마포**를 위한 **대기 큐**에 넣습니다. + +프로세스는 대기 큐에 들어가게 되면서 이후 해당 **PCB**를 **준비 큐**로 돌리기 전까지 **CPU**자원을 잡아 먹지 않게 됩니다. + +
+
+ +## 모니터 + +--- + +세마포 기법 자체는 동기화도구로써 좋은 효능을 보여주지만, 사용자 측면에서 불편한 점이 있다. +임계 구역에 앞뒤로 wait, signal 함수를 사용하고 휴먼에러로 인한 실수가 발생한다면 예기치 못한 결과를 발생시킬 수 있기 때문이다. + +이에 **모니터**라는 동기화 도구가 생기게 된다. + +모니터는 공유 자원과, 공유 자원에 접근하기 위한 인터페이스를 묶어 관리합니다. + +
+ +![img.png](monitor.png) + +
+ +이를 위해 모니터를 통해 공유 자원에 접근하고자 하는 프로세스를 큐에 삽입하고, 큐에 삽입된 순서대로 하나씩 공유 자원을 이용하도록 합니다. +모니터는 공유 자원을 다루는 인터페이스에 접근하기 위한 큐를 만들고, 모니터 안에 항상 하나의 프로세스만 들어오도록 하여 **상호 배제**를 수행합니다. + +또한, 모니터는 **실행 순서**를 제어하는 동기화 또한 수횅합니다. **조건 변수**를 사용해서 실행 순서를 제어하게 됩니다. + +
+ +![img.png](monitor2.png) + +
+ +해당 그림처럼 기존 **상호 배제를 위한 큐**가 아닌 **조건 변수**에 대한 큐가 있습니다. 이 **조건 변수**는 기존처럼 **wait**, **signal** 연산을 +수횅할 수 있습니다. + +상호 배제를 위한 큐에서 가장 선두에 있는 프로세스A보다 특정 프로세스B가 더 먼저 시행되어야 한다면, B가 수행되기 전까지 앞선 프로세스들은 **wait** 연산을 통해 +조건 변수에 대한 큐에서 대기하게 되고, 그렇게 대기를 하게되면 최우선 시행되는 프로세스는 **B**가 될것입니다. 이런 형태로 모니터는 실행 순서를 제어합니다. + +## 출처 + +--- + +[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard) + diff --git a/contents/posts/operation-system/jc18/monitor.png b/contents/posts/operation-system/jc18/monitor.png new file mode 100644 index 0000000..b1e1a05 Binary files /dev/null and b/contents/posts/operation-system/jc18/monitor.png differ diff --git a/contents/posts/operation-system/jc18/monitor2.png b/contents/posts/operation-system/jc18/monitor2.png new file mode 100644 index 0000000..0cab2b6 Binary files /dev/null and b/contents/posts/operation-system/jc18/monitor2.png differ diff --git a/contents/posts/operation-system/jc18/semaphore.png b/contents/posts/operation-system/jc18/semaphore.png new file mode 100644 index 0000000..a7fbf1b Binary files /dev/null and b/contents/posts/operation-system/jc18/semaphore.png differ diff --git a/contents/posts/operation-system/jc18/toilet.png b/contents/posts/operation-system/jc18/toilet.png new file mode 100644 index 0000000..13c85ff Binary files /dev/null and b/contents/posts/operation-system/jc18/toilet.png differ diff --git a/contents/posts/operation-system/jc19/dpp.png b/contents/posts/operation-system/jc19/dpp.png new file mode 100644 index 0000000..a395978 Binary files /dev/null and b/contents/posts/operation-system/jc19/dpp.png differ diff --git a/contents/posts/operation-system/jc19/index.md b/contents/posts/operation-system/jc19/index.md new file mode 100644 index 0000000..c4abd26 --- /dev/null +++ b/contents/posts/operation-system/jc19/index.md @@ -0,0 +1,212 @@ +--- +title: "교착상태와 해결 방법" +description: "교착상태와 해결 방법" +date: 2025-09-22 +update: 2025-09-22 +tags: + - 운영체제 +series: "프로세스 동기화" +--- + +## 교착상태란?(Dead Lock) + +--- + +**교착상태**란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다. + +**교착상태**를 설명하는 대표적인 예시로 **식사하는 철학자 문제**라는게 있습니다. + +
+ +### 식사하는 철학자 + +--- + +![img.png](dpp.png) + +
+ +식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습니다. +식사를 하려면 두개의 포크를 들어야 하는 상황입니다. + +이를 순서도로 표현하면 + +1. 생각을 하다가 왼쪽 포크를 들 수 있다면 든다. +2. 생각을 하다가 오른쪽 포크를 들 수 있다면 든다. +3. 왼쪽, 오른쪽 포크를 모두 집어들면 정해진 시간동안 식사를 한다. +4. 식사 시간이 끝나면 오른쪽 포크를 내려놓는다. +5. 나머지 왼쪽 포크도 내려놓는다. +6. 1번부터 반복한다. + +
+ +위와같은 상황일때 모든 철학자가 왼쪽 포크를 들고 있거나, 반대쪽 포크를 들고 있다면 식사는 영원히 끝나지 않습니다. 이유는 포크라는 자원은 +철학자의 수만큼 존재하고 각 철학자는 두개의 포크를 원하는 상태에서 모든 포크를 얻을때까지 가디라기 떄문에, 모든 철학자가 포크를 기다리기만 하는 +상황이 발생합니다. + +이러한 문제는 **일어나지 않을 사건을 기다리며 진행이 멈춰 버리는** **교착상태**와 같습니다. + +여기서 철학자를 **프로세스 혹은 스레드** 포크를 **자원** 그리고 생각하는 행위가 자원을 기다리는 것이라고 생각한다면, 프로세스와 스레드는 +**자원**을 사용하기 위해 **기다리는 행위**만 계속하는 상황이 되는것입니다. + +
+
+ +## 교착상태 발생조건 + +--- + +교착상태가 발생할 조건에는 네가지가 있습니다. 차례대로 **상호배제**, **점유와 대기**, **비선점**, **원형 대기**입니다. 해당 조건은 +모두 만족해야지 **교착상태**가 발생하고 하나라도 해당하지 않는다면 **교착상태**는 발생하지 않습니다. + +
+ +### 1. 상호 배제 + +교착 상태가 발생한 근본적인 원인은 해당 자원을 하나의 프로세스만 사용하기 때문입니다. 프로세스도 마찬가지로 한 프로세스가 사용하는 자원을 다른 프로세스가 +사용할 수 없을때, 교착상태가 발생합니다. + +### 2. 점유와 대기 + +프로세스는 자원을 할당받은 상태에서 다른 자원을 할당받기를 기다린다면 교착 상태가 발생할 수 있습니다. 이렇게 **자원을 할당받은 상태에서 다른 자원을 +할당받기를 기다리는 상태**를 **점유와 대기**라고 합니다. + +### 3. 비선점 + +이전에 **선점**, **비선점**이라는 개념을 보았습니다. **비선점**이란 프로세스나 스레드가 자원을 할당받으면 그 작업이 끝나기전까지 자원을 뻇어갈수 없다는 +특징이 있었습니다. 교착상태가 발생하는 원인은 **점유와 대기**상태중 필요한 자원을 **선점**할수 없이 계속 기다리기만 하여서 발생하는 문제 입니다. + +### 4. 원형 대기 + +**자원 할당 그래프**가 원의 형태로 그려지면 교착 상태가 발생할 수 있습니다. 이렇게 프로세스들이 원의 형태로 자원을 대기하는 것을 **원형 대기**라고 합니다. + +
+
+ +## 교착상태 해결방법 + +--- + +교착상태를 해결하는 방법은 크게 세가지로 나눌수 있습니다. +> 1. 예방 +> 2. 회피 +> 3. 검출 후 회복 + +
+
+ +## 예방을 통한 해결 + +--- + +예방이란 교착상태 발생 조건에 부합하지 않게 자원을 분배하는 방식입니다. + +이전에 말한 **교착상태**발생 조건에 해당하는 네 가지 중 하나를 충족 하게 되면 **교착 상태**를 해결할 수 있습니다. + +### 상호 배제를 없애는 방식 + +> 이론적으로는 가능하나, 모든 자원이 상호 배제를 없애기는 어렵기 때문에 비현실적이다. + +
+ +### 점유와 대기를 없애는 방식 + +> 특정 자원이 먼저 점유를 수행하여 작업을 끝내고, 다른 프로세스에게 자원을 몰아주는 방식으로 해결이 가능합니다. +> +> 하지만 이런 방식은 자원 활용률이 낮아 진다는 문제가 있습니다. + +
+ +### 비선점 조건을 없애는 방식 + +> 비선점 방식으로 작업을 다루게 되면 교착상태가 발생해도 자원을 뺏어 해결 할 수 있습니다. +> +> 하지만, 이런방식의 문제점은 모든 자원이 비선점 기능을 사용할 수 없다는 점에 있습니다. +> +> 예를들어, 프린터는 비선점 방식을 수행하는 자원입니다. + +
+ +### 원형 대기 조건을 없애는 방식 + +> 모든 자원에 번홀을 붙이고 오름차순으로 자원을 할당하면 원형 대기는 방생하지 않습니다. +> 마치 원형이 아닌, 선형으로 자원을 나열하는 방식입니다. +> +> 이런 방식은 자원에 일일이 번호를 붙여야 한다는점과, 특정 번호는 자원 활용률이 떨어질수 있다는 문제가 있습니다. + +
+
+ +## 회피를 통한 해결 + +--- + +회피 방식에서는 교착 상태 발생이 한정된 자원을 무분별하게 할당하였서 그렇다고 가정합니다. 그렇기 때문에 회피방식은 자원을 신중하게 할당하는 방식으로 +해결합니다. + +즉, 교착 상태가 발생하지 않을 정도의 양만큼만 자원을 배분하는 방법을 **교착 상태 회피**라고 부릅니다. + +**안정 상태**, **불안전 상태**가 있습니다. 각각 교착상태가 발생하지 않는 상태를 **안정상태**, 발생할 가능성이 있는 상태를 **불안정 상태**라고 부릅니다. + +**회피**를 통해 교착상태를 해결하기 위해 **안전 순서열**을 고려해서 문제를 해결합니다. + +> 안전순서열: 교착 상태 없이 안전하게 프로세스들에 자원을 할당할 수 있는 순서를 의미합니다. + +
+ +내용을 종합하면 **안전 순서열**이 있고 그것을 사용할때 상태를 **안정상태**, 안전 순서열이 없을 때 상태는 **불안정상태**라고 부르게 됩니다. + +
+
+ +## 교착 상태 검출 후 회복 + +--- + +마지막으로, 교착상태를 피하기 위해서는 **검출**, **회복** 방식을 사용합니다. + +두가지 방식을 고려할 수 있는데, + +1. 선점을 통한 회복 +2. 프로세스 강제종료 + +
+ +### 선점을 통한 회복 + +교착 상태가 해결될 때까지 한 프로세스씩 자원을 몰아주는 방식입니다. 교착 상태가 해결될 떄까지 다른 프로세스로부터 자원을 빼앗고 할당하는 방식입니다. + +
+ +### 강제종료를 통한 회복 + +교착 상태에 놓인 순간 모든 프로세스를 종료 하는 방법 혹은 프로세스를 하나씩 종료해서 확인해보는 방법이 있습니다. + +전자는 가장 확실하지만 모든 작업에 대한 진행사항을 잃을 가능성이 있고, 후자는 전자보다 손실에 대한 부담은 적지만 오버헤드가 커진다는 단점이 있습니다. + + + + + + + + + + + + + + + + + + + + + +## 출처 + +--- + +[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard) + diff --git a/contents/posts/operation-system/2/index.md b/contents/posts/operation-system/jc2/index.md similarity index 96% rename from contents/posts/operation-system/2/index.md rename to contents/posts/operation-system/jc2/index.md index 494bdf2..d726ab3 100644 --- a/contents/posts/operation-system/2/index.md +++ b/contents/posts/operation-system/jc2/index.md @@ -1,5 +1,5 @@ --- -title: "2. CPU 스케줄링, 시스템 자원 관리" +title: "CPU 스케줄링, 시스템 자원 관리" description: "CPU 스케줄링, 시스템 자원 관리" date: 2025-09-05 update: 2025-09-05 diff --git a/contents/posts/operation-system/jc20/index.md b/contents/posts/operation-system/jc20/index.md new file mode 100644 index 0000000..ee1f307 --- /dev/null +++ b/contents/posts/operation-system/jc20/index.md @@ -0,0 +1,117 @@ +--- +title: "물리주소, 논리주소 그리고 메모리 분할 방식" +description: "물리주소, 논리주소 그리고 메모리 분할 방식" +date: 2025-09-23 +update: 2025-09-23 +tags: + - 운영체제 +series: "가상메모리, 메모리분할" +--- + +## 물리주소와 논리주소 + +--- + +![img.png](memory_address.png) + +메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다. +이 저장된 메모리의 데이터를 **CPU** 혹은 **실행중인 프로그램**이 읽어 실행하게 됩니다. + +해당 그림은 두가지 관점으로 **주소**를 나누고 사용하는 방식을 그림으로 나타낸 것입니다. + +왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요? + +> 이유는 메모리에 저장되어 있는 정보는 변화가 빠르고 이를 시시각각 알기어렵기 때문에 + +가령 프로그램이 새롭게 실행될때, 삭제 될때 혹은 같은 프로그램일지라도 실행될때마다 실행되는 주소가 다르기 때문입니다. + +그렇기때문에 주소를 두가지 관점으로 나눠서 사용하게 됩니다. + +> **물리주소**란 실제로 정보가 저장된 하드웨어상 주소를 의미합니다. + +> **논리주소**란 실행중인 프로그램에 부여된 0번지부터 시작되는 주소를 의미합니다. + +여기서 주의할점은 **논리주소**는 0번지 부터 시작하는 논리적 주소이기 때문에, **고유성**이 없습니다. 하지만 **물리주소**는 +하드웨어상 주소기 때문에 **고유성**이 있습니다. + +
+
+ +## 메모리 할당 방식 + +--- + +**메모리 할당**이란 주기억 장치에 프로세스를 저장하는 과정입니다. +이러한 과정은 크게 **두가지**로 나누어집니다. + +1. 연속 할당 +2. 불연속 할당 + +
+ +## 연속할당 + +--- + +연속 할당은 프로세스가 연속된 메모리 영역에 할당되는 방법을 말합니다. +각 프로세스는 연속적인 메모리 주소 범위 내에 위치하게 됩니다. 이렇게 연속할당을 하게 되면 +빈공간보다 프로세스 공간이 더 작은 경우가 있는데 이러한 현상을 **단편화**라고 합니다. + +연속할당의 종류로는 **고정 크기 파티셔닝**, **가변 크기 파티셔닝**이 있습니다. + +
+ +### 고정 크기 파티셔닝 + +고정 크기 파티셔닝은 메모리를 고정된 크기의 파티션으로 나누어 각 파티션에 프로세스를 할당하는 방식입니다. +예를들어, 모든 파티션을 10MB로 설정하고 파티션마다 프로세스를 할당하는 방식을 사용할 수 있습니다. + +이러한 방식은 모든 프로세스가 지정한 파티션 크기만큼 떨어지는것이 아니기 떄문에 효율적이지 못한 단점이 있습니다. + +
+ +### 가변 크기 파티셔닝 + +가변 크기 파티셔닝은 파티션의 크기를 유동적으로 조절하는 메모리 할당 방식입니다. +이러한 방식은 **고정 크기 파티셔닝**보다는 효율적이지만, 메모리 공간에 어떤 프로세스를 저장해야 할지 결정하는게 +복잡합니다. + +
+
+ +## 불연속 할당 + +--- + +불연속 할당은 한 프로세스를 메모리 여러 곳에 분산 저장하는 방법입니다. **페이징**, **세그멘테이션** 이 있습니다. + +
+ +### 페이징 + +페이징은 프로세스의 주소 공간을 페이지라는 동일한 크기의 구획으로 나누고, 주기억 장치도 페이지와 동일한 크기의 +프레임이라는 구획으로 나눕니다. 이후 한 페이지를 한 프레임에 적재하는 방식입니다. + +자세한 내용은 이후에 다루게 됩니다. + +
+ +### 세그멘테이션 + +프로세스의 주소공간을 세그먼트라는 단위로 나누어 주기억 장치에 적재합니다. +프로세스는 코드, 데이터, 스택 등으로 구성되기 때문에 각각을 한 세그먼트로 나누어서 메모리에 적재합니다. + +이 과정에서, base주소와, limit주소를 이용하여 프로세스가 자신에게 할당된 메모리 영역만 사용하게 합니다. + + +
+ + + +## 출처 + +--- + +[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard) + + diff --git a/contents/posts/operation-system/jc20/memory_address.png b/contents/posts/operation-system/jc20/memory_address.png new file mode 100644 index 0000000..812a22b Binary files /dev/null and b/contents/posts/operation-system/jc20/memory_address.png differ diff --git a/contents/posts/operation-system/jc21/best_fit.png b/contents/posts/operation-system/jc21/best_fit.png new file mode 100644 index 0000000..da8cb02 Binary files /dev/null and b/contents/posts/operation-system/jc21/best_fit.png differ diff --git a/contents/posts/operation-system/jc21/first_fit.png b/contents/posts/operation-system/jc21/first_fit.png new file mode 100644 index 0000000..cbccac3 Binary files /dev/null and b/contents/posts/operation-system/jc21/first_fit.png differ diff --git a/contents/posts/operation-system/jc21/index.md b/contents/posts/operation-system/jc21/index.md new file mode 100644 index 0000000..021d541 --- /dev/null +++ b/contents/posts/operation-system/jc21/index.md @@ -0,0 +1,185 @@ +--- +title: "메모리 배치기법 그리고 단편화에 대해" +description: "메모리 배치기법 그리고 단편화에 대해" +date: 2025-09-24 +update: 2025-09-24 +tags: + - 운영체제 +series: "가상메모리, 메모리분할" +--- + +## 연속 메모리 할당 + +--- + +![img.png](sequencial_memory.png) + +**연속 메모리 할당**이란 메모리에 프로세스가 그림처럼 **연속적**으로 배치되는 상황을 가정합니다. + +프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다. + +이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 **스와핑**과 관련이 있습니다. + +
+ +## 스와핑이란? + +--- + +메모리는 실행시킬 프로세스를 적재하게 됩니다. 하지만, 이런 프로세스들 중에 현재 실행되지 않는 프로세스는 처리해줘야 합니다. +메모리 리소스가 한정적이기 때문입니다. + +여기서 말하는 실행되지 않는 프로세스의 예시는 **I/O**작업, 오랫동안 사용되지 않는 프로세스가 이에 해당합니다. + +
+ +![img.png](swaping.png) + +
+ +그렇다면 이러한 프로세스를 메모리에서 처리하는 방법이 필요한데 그 방법이 **스와핑** 입니다. + +**스와핑**은, 두가지 행위를 통해서 수행할 수 있습니다. + +> 스왑 아웃: 현재 실행되지 않는 프로세스가 메모리에서 스왑 영역으로 옮겨지는 것 (메모리 -> 스왑 영역) + +> 스왑 인: 스왑영역에 있던 프로세스가 다시 메모리로 옮겨지는 것 (스왑 영역 -> 메모리) + +또한 메모리에서 보조기억장치로 옮겨질때 **스왑영역**으로 프로세스를 옮겨두는데 그 영역을 **스왑 영역**이라고 합니다. + +
+
+ +## 메모리 할당 방식 + +--- + +프로세스는 메모리 속 비어있는 공간에 적재되어야 합니다. 비어 있는 메모리 공간에 프로세스를 연속적으로 할당하기 위해 +**세가지** 방법을 고려할 수 있습니다. + +1. **최초 적합(first fit)** +2. **최적 적합(best fit)** +3. **최악 적합(worst fit)** + +각방식을 아래 예시를 통해 들어보려 합니다. + +프로세스 A,B,C는 이미 적재되어있고, 빈 공간 A,B,C가 있습니다. 앞으로 적재할 프로세스는 20MB크기를 가지고 있으며 +적재 방식에 따라 이를 어디에 적재할지 달라지게 됩니다. + +![img.png](memory_stacking.png) + +
+ +## 최초 적합 + +--- + +최초 적합은 메모리 내의 빈 공간을 순서대로 검색하다가 적재할 수 있는 공간을 발견하면 그 공간에 프로세스를 배치하는 방식입니다. +이전 그림에서 운영체제가 빈공간 A,B,C 순서대로 검색을 하였다면 가장 먼저 검색된 A 빈공간에 적재되는 방식입니다. + +![img.png](first_fit.png) + +적재후 모습은 그림과 같으며 해당 방식은 검색을 최소화 하며 **빠른 할당**을 가능하게 하는 장점이 있습니다. +하지만, 이후에 보게 될 **외부 단편화**가 생길 가능성이 높아지게 됩니다. + +
+
+ +## 최적 적합 + +--- + +최적 적합은 운영체제가 빈공간을 **모두** 검색한 후 프로세스가 적재될 수 있는 공간 중 가장 **작은 공간**에 프로세스를 +배치하는 방식입니다. +이전 그림에서는 빈 공간 C가 가장 적합한 크기를 가진 공간이기 때문에 그곳에 적재 됩니다. + +![img.png](best_fit.png) + +적재후 모습은 그림과 같으며 해당 방식은 적재할 프로세스 크기를 고려한 방식이기 때문에 **외부 단편화**를 +최소화 할 수 있다는 장점이 있지만, **모든**공간을 검색하는 행위가 **오버헤드**를 발생시키기 때문에 느려집니다. + +
+
+ +## 최악 적합 + +--- + +최악 적합은 운영체제가 빈 공간을 모두 검색한 후, 가장 큰 공간에 프로세스를 적재하는 방식입니다. + +![img.png](worst_fit.png) + +적재 후 모습은 가장 빈공간의 크기가 큰 B에 적재되는 것을 확인할 수 있습니다. 이러한 방식은 +외부 단편화의 발생 빈도도 크며, 모든 공간을 검색한다는 비효율적인 측면도 가지고 있습니다. + +
+ +지금까지 **외부 단편화**라는 용어가 단점으로 설명했습니다. +그렇다면, **외부 단편화**는 어떠한 문제일까요? + +
+ +## 단편화 + +--- + +단편화는 크게 두가지로 나눌 수 있습니다. + +1. 내부 단편화 +2. 외부 단편화 + +
+ +### 내부 단편화 + +![img.png](first_fit.png) + +내부 단편화 문제는 이전 **최초 적합** 사례에서 볼 수 있습니다. +빈공간A의 크기는 30MB인데 적재한 프로세스는 20MB입니다. 이런경우 10MB의 빈공간이 생기게 되고 이러한 비어있는 +공간을 **내부 단편화**가 발생했다고 표현합니다. + +
+ +### 외부 단편화 + +![img.png](first_fit.png) + +외부 단편화 문제는 이전 **최초 적합** 사례를 이어서 설명하겠습니다. +현재 그림속 비어있는 공간은 **80MB**입니다. 하지만 해당 공간에 **80MB**크기의 프로세스를 적재할 수 없습니다. +이유는, 빈 공간이 연속적인것이 아닌 프로세스C에 의해 끊어져있기 때문입니다. + +이처럼, 프로세스를 할당하기 어려울 만큼 작은 메모리 공간들로 인해 메모리가 낭비되는 현상을 지칭합니다. + +이러한 외부 단편화를 해결할 수 있는 대표적인 방안은 메모리를 **압축**하는 방법이 있습니다. + +
+ +## 압축 + +--- + +**압축**이란 흩어져 있는 빈 공간들을 하나로 모으는 방식으로 메모리 내에 저장된 프로세스를 재배치 시켜 빈 공간을 +하나의 큰 빈 공간으로 만드는 방법입니다. + +이러한 방식은 단점이 있는데, 메모리의 빈공간을 모으는 작업은 시스템을 중지 시킨다는 문제가 있습니다. +또한, 메모리를 옮기는 작업이 큰 오버헤드를 만들고, 최적화 방법에 대한 정답을 고르기가 어렵습니다. + + + + + + + + +## 출처 + +--- + +[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard) + + + + + + + diff --git a/contents/posts/operation-system/jc21/memory_stacking.png b/contents/posts/operation-system/jc21/memory_stacking.png new file mode 100644 index 0000000..ed36ec0 Binary files /dev/null and b/contents/posts/operation-system/jc21/memory_stacking.png differ diff --git a/contents/posts/operation-system/jc21/sequencial_memory.png b/contents/posts/operation-system/jc21/sequencial_memory.png new file mode 100644 index 0000000..a744e9c Binary files /dev/null and b/contents/posts/operation-system/jc21/sequencial_memory.png differ diff --git a/contents/posts/operation-system/jc21/swaping.png b/contents/posts/operation-system/jc21/swaping.png new file mode 100644 index 0000000..f955b9a Binary files /dev/null and b/contents/posts/operation-system/jc21/swaping.png differ diff --git a/contents/posts/operation-system/jc21/worst_fit.png b/contents/posts/operation-system/jc21/worst_fit.png new file mode 100644 index 0000000..5d0e924 Binary files /dev/null and b/contents/posts/operation-system/jc21/worst_fit.png differ diff --git a/contents/posts/operation-system/jc22/index.md b/contents/posts/operation-system/jc22/index.md new file mode 100644 index 0000000..f7797b0 --- /dev/null +++ b/contents/posts/operation-system/jc22/index.md @@ -0,0 +1,232 @@ +--- +title: "페이징" +description: "페이징" +date: 2025-09-25 +update: 2025-09-25 +tags: + - 운영체제 +series: "가상메모리, 메모리분할" +--- + +### 연속 할당의 문제점 + +--- + +연속적 할당의 대표적인 문제점은 **외부 단편화**가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해 +필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다. + +이러한 문제를 해결하기 위해서는 **불연속 할당** 방식 중 대표적인 **페이징**기법을 사용할 수 있습니다. + +
+
+ +## 페이징이란? + +--- + +![img.png](paging.png) + +페이징 기법은 프로세스를 일정한 단위로 자릅니다. 또한 프로세스가 들어갈 메모리 공간 또한 일정한 단위로 자릅니다. + +여기서 프로세스를 일정한 단위로 자르면 일정한 **논리 주소 공간**이 생기는데 이것을 **페이지**라고 부르며, +일정한 단위로 잘린 메모리 **물리 주소 공간**은 **프레임**이라고 부르게 됩니다. + +여기서 **프레임**, **페이지**의 일정한 단위는 동일한 크기로 자르게 됩니다. + +이렇게 만들어진 **페이지**를 **프레임**에 할당하는 가상 메모리 관리 기법을 **페이징**기법이라고 부르게 됩니다. + +이렇게 일정한 크기를 정하고 불연속 할당을 수행하면 외부 단편화 문제를 줄일 수 있습니다. + +
+ +### 페이징에서 스와핑 + +![img.png](paging_swaping.png) + +페이징에서도 이전과 마찬가지로 **스와핑**이 사용됩니다. 차이가 있다면 기존 연속 할당 방식 스와핑은 +프로세스 전체가 스왑영역으로 넘어가지만, **페이징 스와핑**은 사용하지 않는 특정 **페이지**만 스왑아웃 +시킬 수 있습니다. + +이러한 방식은 이후 **가상메모리** 방식을 사용하는데 핵심이 됩니다. + +
+ +## 페이지 테이블 + +--- + +불연속 할당 방식에는 실행순서에 대한 문제가 하나 있습니다. +연속적 할당 방식에서는 실행순서를 CPU에게 알려줄 필요가 없습니다. 왜냐하면 실제로 물리 메모리에 연속적으로 +프로세스에 대한 정보가 있기 때문에 순서대로 실행시키면 되기 때문입니다. + +하지만, **불연속 할당**은 상황이 다릅니다. 메모리상 프로세스에 대한 정보가 연속적이지 않기 떄문에 +이를 실행시키는 **CPU**입장에서는 어떤 프로세스를 실행시켜야 할지 알기 어렵습니다. + +
+ +![img.png](page_table.png) + +
+ +이를 해결하기 위해서 **페이지 테이블**이란것을 사용합니다. + +**페이지 테이블**은 **페이지 번호**, **프레임 번호**를 짝지어 줍니다. 그렇게 되면 **CPU**입장에서는 +**페이지 번호**만 알고있다면 **페이지 테이블**을 통해 **프레임**으로 접근이 가능하기 때문입니다. + +페이지 테이블은 프로세스마다 각자의 페이지 테이블을 가지게 됩니다. + +
+
+ +## 페이지 테이블 베이스 레지스터(PTBR) + +--- + +페이지 테이블은 프로세스마다 가지고 있고, 이는 **메모리**에 저장됩니다. + +하지만, CPU 입장에서는 결국 **페이지 테이블**의 위치를 알아야 합니다. 이러한 기능을 수행하는게 +**CPU**내의 존재하는 **PTBR**입니다. + +**PTBR**은 **CPU**내에 존재하고 **페이지 테이블**의 위치를 기록합니다. + +![img.png](ptbr.png) + +해당 그림처럼 특정 프로세스 작업을 수행하기 위해서 **CPU**는 해당 **PTBR**내부 프로세스의 페이지 테이블을 +조회합니다. 이후 메모리내부 해당 페이지 테이블 주소로 넘어가서 특정 프로세스의 페이지 까지 접근하게 됩니다. + +
+
+ +### 비효율적인 접근 + +--- + +이전 **페이지 테이블**을 참조하는데 한가지 문제가 있습니다. + +**CPU**는 **페이지 테이블**로 접근하고, 해당 값들을 통해 실제 **페이지**로 접근합니다. + +즉, 하나의 조회에 대해 두가지 접근을 수행하게 됩니다. 이러한 방식은 비효율적입니다. +그렇기 때문에 **캐싱**기능을 통해 이를 해결하고 이러한 기능을 수행하는게 **TLB**입니다. + +
+ +## TLB(Translation Lookaside Buffer) + +--- + +![img.png](tlb.png) + +**TLB**는 CPU 곁에 존재하며 이는 페이지 테이블에 대한 **캐시 메모리**입니다. +참조 지역성에 근거해 주로 최근에 사용된 페이지 위주로 가져와서 저장합니다. + +여타한 캐싱 기능과동일하게 리소스가 **TLB**를 통해서 나오게 되면, **히트**했다. 그것이 아니라면 +**미스**했다 라고 표현합니다. + + +
+
+ +## 페이징에서의 주소 변환 + +--- + +**특정 주소**에 접근하기 위해서는 두가지 관점의 정보가 필요하게 됩니다. + +1. 어떤 페이지 혹은 프레임에 접근하고 싶은지 +2. 접근하려는 주소가 그 페이지 혹은 프레임으로부터 얼마나 떨어져 있을지 + +
+ +이중에서 1번은 기존 **페이지 번호**를 통해서 해결할 수 있습니다. +하지만, 2번의 말은 조금 애매하게 들리는데 이를 풀어서 설명하면, +하나의 **주소**내에서도 **논리** 혹은 **물리**주소에 따른 순차적인 주소가 있습니다. + +n번지, n+1번지, n+2번지.... 처럼 세부적인 **지점**을 의미합니다. + +1번 주소를 통해서 **페이지**혹은 **프레임**에 접근한다면 그 중 명확한 지점을 식별해야 하기 때문에 + +페이징 시스템에서는 **페이지번호**, **변위**를 이용합니다. + +자세한 예시는 아래 그림을 통해서 하겠습니다. + +
+ +![img.png](paging_address_trans.png) + +페이지, 페이지 테이블, 프레임을 나타내는 그림입니다. 이러한 그림은 특정 페이지에 접근하기 위해 +페이지 테이블을 참조하고 프레임 번호를 얻어 실제 메모리 프레임에 접근하는 시퀀스 입니다. + +만약 **CPU**가 5번페이지에 변위가 2인 곳에 접근하려고 하면 10번지로 접근하게 될것입니다. + +1. 5번 페이지는 1번 프레임에 있다. +2. 1번 프레임의 시작 번지수는 8번지이다 +3. 8번지에 변위 2를 더해서 최종주소는 10이 된다. + +여기서 주의 할점은, 논리주소의 변위를 최종 물리 주소상 프레임 번지에 더하였다는 것입니다. +> 이말은, 논리주소의 변위 == 물리주소의 변위 입니다. + +이것이 가능한 이유는 처음 페이징 방식을 사용할때 페이지와 프레임 변환과정에서 **특정 크기**로 나누게 되고, +그 간격이 같기 때문에 논리주소의 변위랑 물리주소의 변위는 같다는 결론이 나옵니다. + +
+
+ +## 페이지 테이블 엔트리 + +--- + +페이지 테이블 엔트리는 페이지 테이블 **row**를 지칭하는 단위입니다. + +![img.png](pte.png) + +지금까지는 이러한 페이지 테이블에는 페이지 번호, 프레임 번호만 존재 한다고 설명했습니다. +하지만, 다른 중요한 정보들도 있습니다. + +1. 유효 비트 +2. 보호 비트 +3. 참조 비트 +4. 수정 비트 + +
+ +### 유효 비트 + +유효비트는 해당 페이지에 접근 가능한지 여부를 알려줍니다. 대표적으로 접근 불가능 한 경우는 +**스와핑**으로 인한 해당 **페이지**가 **스왑영역**으로 들어간 경우입니다. + +이러한 경 **페이지 폴트**라는 예외가 발생하며, 하드웨어 인터럽트 처럼 처리 됩니다. + +1. CPU는 기존 작업 내역을 백업합니다. +2. 페이지 폴트 처리 루틴을 실행합니다. +3. 페이지 처리 루틴은 원하는 페이지를 메모리로 가져온 뒤 유효 비트를 1로 변경해줍니다. +4. 페이지 폴트를 처리했다면 이제 CPU는 해당 페이지에 접근할 수 있게 됩니다. + +
+ +### 보호 비트 + +보호비트는 페이지 보호 기능을 위해 존재합니다. 리눅스의 읽기 쓰기 권한을 생각하면 됩니다. +해당 페이지가 읽기 전용 페이지라면 보호비트는 0을 나타내고, 읽고 쓰기가 가능하다면 1을 나타냅니다. + +
+ +### 참조 비트 + +**CPU**가 접근한적 있는지 여부를 나타냅니다. 참조된 비트라면 1을 나타내며, 그렇기 않다면 0으로 유지됩니다. + +
+ +### 수정 비트 + +해당 페이지에 데이터를 쓴 적이 있는 여부를 나타냅니다. 수정 여부를 확인해야 하는 이유는 **스와핑** 떄문입니다. +만약 **CPU**가 페이지에 대한 내용을 수정했다면, 스와핑 과정에서 보조 기억장치에 있는 데이터 또한 수정해야 하기 때문입니다. + + + + + +## 출처 + +--- + +[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard) diff --git a/contents/posts/operation-system/jc22/page_table.png b/contents/posts/operation-system/jc22/page_table.png new file mode 100644 index 0000000..f7e7c17 Binary files /dev/null and b/contents/posts/operation-system/jc22/page_table.png differ diff --git a/contents/posts/operation-system/jc22/paging.png b/contents/posts/operation-system/jc22/paging.png new file mode 100644 index 0000000..6346487 Binary files /dev/null and b/contents/posts/operation-system/jc22/paging.png differ diff --git a/contents/posts/operation-system/jc22/paging_address_trans.png b/contents/posts/operation-system/jc22/paging_address_trans.png new file mode 100644 index 0000000..1f971ff Binary files /dev/null and b/contents/posts/operation-system/jc22/paging_address_trans.png differ diff --git a/contents/posts/operation-system/jc22/paging_swaping.png b/contents/posts/operation-system/jc22/paging_swaping.png new file mode 100644 index 0000000..9f70f9c Binary files /dev/null and b/contents/posts/operation-system/jc22/paging_swaping.png differ diff --git a/contents/posts/operation-system/jc22/ptbr.png b/contents/posts/operation-system/jc22/ptbr.png new file mode 100644 index 0000000..8aa525b Binary files /dev/null and b/contents/posts/operation-system/jc22/ptbr.png differ diff --git a/contents/posts/operation-system/jc22/pte.png b/contents/posts/operation-system/jc22/pte.png new file mode 100644 index 0000000..a4934ea Binary files /dev/null and b/contents/posts/operation-system/jc22/pte.png differ diff --git a/contents/posts/operation-system/jc22/tlb.png b/contents/posts/operation-system/jc22/tlb.png new file mode 100644 index 0000000..9159742 Binary files /dev/null and b/contents/posts/operation-system/jc22/tlb.png differ diff --git a/contents/posts/operation-system/jc23/degree_of_multiprogramming.png b/contents/posts/operation-system/jc23/degree_of_multiprogramming.png new file mode 100644 index 0000000..ccb43d4 Binary files /dev/null and b/contents/posts/operation-system/jc23/degree_of_multiprogramming.png differ diff --git a/contents/posts/operation-system/jc23/fifo.png b/contents/posts/operation-system/jc23/fifo.png new file mode 100644 index 0000000..894d7dc Binary files /dev/null and b/contents/posts/operation-system/jc23/fifo.png differ diff --git a/contents/posts/operation-system/jc23/index.md b/contents/posts/operation-system/jc23/index.md new file mode 100644 index 0000000..d088b3d --- /dev/null +++ b/contents/posts/operation-system/jc23/index.md @@ -0,0 +1,288 @@ +--- +title: "요구페이징을 잘 수행하기 위해서 필요한 것들" +description: "요구페이징을 잘 수행하기 위해서 필요한 것들" +date: 2025-09-26 +update: 2025-09-26 +tags: + - 운영체제 +series: "가상메모리, 메모리분할" +--- + +## 서론 + +--- + +지금까지 **가상 메모리**를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다. +이러한 행위는 한정된 **메모리**를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다. + +그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다. + +1. 불필요한 페이지를 **선별** 후 **스왑 아웃** 한다. +2. 프로세스에게 적절한 **프레임**을 할당한다. + +각각 **페이지 교체 알고리즘**, **프레임 할당**이라고 부릅니다. + +또한, 이러한 작업은 **요구 페이징(demand paging)** 이라는 작업을 더 효율적으로 할 수 있게 돕습니다. + +이 글은 요구 페이징에 대해서 알아보고, 요구 페이징이 안정적으로 작동하기 위해 필연적인 페이지 교체 알고리즘과, 프레임 할당을 설명합니다. + +
+
+ +## 요구 페이징(demand paging) + +--- + +프로세스를 메모리에 적재할 떄 처음부터 모든 페이지를 적재하지 않고 필요한 페이지만을 메모리에 적재하는 방식을 +**요구 페이징**이라고 부릅니다. + +요구 페이징은 다음과 같은 플로우로 진행됩니다. + +1. CPU가 특정 페이지에 접근하는 명령어를 내린다. +2. 페이지가 메모리에 존재하면 **유효비트 1**을 나타내며 해당 프레임에 접근한다. +3. 존재 하지 않는다면 **유효비트 0**을 나타내며 **페이지 폴트**가 발생한다. +4. **페이지 폴트**가 발생하면 해당 페이지를 메모리로 적재하고 유효비트를 1로 설정한다. +5. 1번을 다시 시행한다. + +이러한 **요구 페이징**은 필요한 페이지만 그때그때 불러서 적재 후 사용한다는 의미를 나타냅니다. + +**요구 페이징**을 안정적으로 수행하기 위해서는 크게 두가지를 고려해야 합니다. +첫번째는, **요구 페이징**은 메모리 기준 **Input**작업 입니다. +그렇다면 반대로 **Output**작업도 필요하게 됩니다. + +왜냐하면 메모리는 한정되고 상대적으로 덜 필요한 페이지를 **스왑아웃**하는 작업도 필요하기 때문입니다. + +이러한 방식을 **페이지 교체** 라고 부르며, 그중 여러가지 방식이 있기 때문에 **페이지 교체 알고리즘**으로 분류하고 명명합니다. + +두번째는, 한정된 프레임을 잘 배분하는 것으로 **스왑 아웃**자체를 줄일 수 있기 때문에 **프레임 할당** 또한 +**요구 페이징**을 수행하기 위해 중요합니다. + +
+
+ +# 페이지 교체 알고리즘 + +--- + +페이지 교체 알고리즘은 **스왑 아웃**할 페이지를 **선별**하는 알고리즘입니다. +그렇기 때문에 어떤 **선별 기준**에 따라 알고리즘을 나누게 됩니다. + +일반적으로 **기준**은 **페이지 폴트** 발생 비율입니다. **페이지 폴트**는 보조기억장치로 부터 +정보를 가져와서 메모리로 할당하여 그 정보를 불러와야 하는 비효율적인 시퀀스를 가지고 있습니다. +이러한 **페이지 폴트** 발생 비율이 적은 교체 알고리즘을 좋다고 평가합니다. + +그리고 **페이지 폴트 횟수**는 **페이지 참조열**을 통해서 진행합니다. + +가령, + +> 2 2 2 3 5 5 5 3 3 7 + +이라는 페이지 참조가 발생한다면 **페이지 참조열**은 여기서 연속된 중복을 제거한 순서입니다. + +> 2 3 5 3 7 + +이 해당 순서에 **페이지 참조열**이 됩니다. 이렇게 중복을 제거하는 이유는 연속된 참조는 **페이지 폴트**대상이 +아니기 때문입니다. + +
+
+ +## FIFO 페이지 교체 알고리즘 + +FIFO 페이지 교체 알고리즘은 이름 그대로 먼저 들어온 페이지를 먼저 내보내는 방식입니다. + +![img.png](fifo.png) + +해당 그림을 통해 설명하면 2,3,1 번의 순서대로 프레임에 쌓이게 되며 마지막 1번 페이지가 적재 된 이후에는 +프레임이 가득차게 됩니다. 이후 3번은 이미 적재된 페이지이기 때문에 넘어갑니다. + +5번 페이지가 적재 되는 시점에 프레임은 가득 차있고, 5번페이지는 적재 되어있지 않기 때문에 **선별**후 **교체**하는 +작업이 필요합니다. + +여기서 **FIFO**방식은 가장 먼저들어온 페이지를 내보낸다라고 설명드린것처럼 처음들어온 **2페이지** **스왑아웃** 시키게 됩니다. +빈 공간에 필요한 **5페이지**를 넣게 됩니다. + +이렇게 먼저 들어온 페이지를 먼저 내보내는것을 **FIFO 교체 알고리즘**이라고 명명합니다. + +하지만 이러한 방식에는 큰 단점이 있는데, 먼저 들어온 페이지가 실행 내내 사용 될 수도 있습니다. +즉, 먼저 들어왔다고 해서 교체에 대상이 되기는 합당한 이유가 아니기 때문입니다. + +
+
+ +## 2차 기회 페이지 교체 알고리즘 + +--- + +해당 알고리즘은 **FIFO**방식을 개선한 알고리즘 입니다. 이름 처럼 한번의 기회를 더 주는 방식입니다. +두가지 케이스가 있습니다. 기본적으로 가장 오래된 페이지를 **스왑 아웃**한다는 방식은 같습니다. +만약 **스왑 아웃** 시점이 오게 되면, 해당 **참조 비트**를 확인합니다. + +CPU에 의해서 **참조** 된적이 있다면, 해당 **참조 비트**를 0으로 바꾸고 적재 시간을 현재로 변경하며, +**참조 비트**가 0이라면 오래되면서 참조된적도 없기 떄문에 바로 **스왑 아웃** 시켜버립니다. + +
+
+ +## 최적 페이지 교체 알고리즘 + +--- + +**최적 페이지 교체** 방식은 이름그대로 최적의 방안을 찾는 알고리즘입니다. +미래를 통해 오랫동안 사용되지 않을 페이지를 **스왑아웃** 시키면서 문제를 해결합니다. + +![img.png](optimal_page_replace.png) + +해당 그림을 통해 설명하면 5번 페이지를 요청할때 페이지 폴트가 발생하고 그 과정에서 이후 미래를 고려해서 +1번이 사용되지 않는다고 판단해 1번을 **스왑 아웃**하는 방식입니다. + +해당 알고리즘은 **페이지 폴트**가 가장 낮습니다. +그렇지만, 현실적인 구현이 어렵습니다. 미래를 예측하는건 어려운 작업입니다. 그렇기 떄문에 현실적으로 가능한 +알고리즘으로 여기기 보단, **페이지 폴트**가 가장 낮다는 점을 고려하여 상대적인 **성능 평가**를 목적으로 사용합니다. + +다른 **교체 알고리즘**의 하한선으로 잡고 비교대상으로 쓰여집니다. + +
+
+ +## LRU 페이지 교체 알고리즘 (Least Recently Used Page Algorithm) + +--- + +해당 알고리즘은 **최적 페이지 교체 알고리즘**을 변형해 **미래**를 예측하는것이 아닌, **과거**를 통해 +사용되지 않은 페이지를 **스왑아웃**하는 방식을 차용합니다. + +'최근에 사용되지 않은 페이지는 앞으로도 사용되지 않을 것이다' 라는 점을 토대로 구성됩니다. + +![img.png](lru.png) + +페이지마다 마지막으로 사용한 시간을 토대로 최근에 가장 사용이 적었던 페이지를 교체합니다. +해당 그림에서는 5번 페이지가 적재될 시기에 가장 오래 사용되지 않는 **2**를 **스왑아웃** 시키는것을 +알 수 있습니다. + +
+
+ +## 스래싱과 프레임 할당 + +--- + +요구 페이징을 잘 수행하기 위해 **페이지 폴트**를 줄이는 방식을 이야기 했습니다. +이러한 **페이지 폴트**를 줄이기 위해 **교체 알고리즘**을 적절하게 선택하는것이 중요하단것을 알게 되었습니다. + +하지만, **페이지 폴트**를 발생시키는 이유에는 **프레임 수의 한정**이라는 문제가 있습니다. +프레임이 무지막지 하게 많다면 모든 프로세스를 할당할 수 있을것이고, 그렇게 되면 **스왑 아웃**이 발생할 이유도 없을것입니다. + +그렇기 때문에 **페이지 폴트**의 발생을 줄이기 위해 적절하게 **프레임을 할당**하는 것또한, 중요합니다. + +역으로 자원을 효율적으로 사용하고, 가상메모리와 같은 기법을 사용하면서 **페이징에 프로세스 실제 실행시간보다 +더큰 리소스를 사용**하는 문제가 생길 수도 있습니다. + +이렇게 배보다 배꼽이 큰 상황, 플어서 이야기하면 +> 페이징 시간이 프로세스 실제 실행보다 더 길어지는 상황 + +을 **스레싱**이라고 부르게 됩니다. + +
+ +### 멀티 프로그래밍 정도 + +![img.png](degree_of_multiprogramming.png) + +해당 그래프는 세로축 **CPU 이용률**, 가로축 **메모리에 올라와 있는 프로세스 수**를 나타냅니다. +그래프에서 알 수 있듯이 프로세스수가 증가하면, CPU이용률 또한 증가합니다 하지만 일정 가로축을 넘어가면 +**CPU**이용률이 줄어드는 것을 알게 됩니다. + +즉, 프로세스가 너무 많이 발생하면 각 프로세스에 할당된 **프레임**이 부족하고 그런 문제로 인해 **페이지 폴트**가 +자주 발생하게 됩니다. + +CPU를 아무리 좋은것을 사용해도 메모리 공간이 부족하면 컴퓨터 성능이 안좋아지는 이유가 이런이유입니다. + +
+
+ +# 프레임 할당 + +--- + +스래싱의 근본적 이유는 각 프로세스가 필요로 하는 **프레임**이 부족하기 때문입니다. 그렇기 떄문에 +운영체제는 **프레임**을 적절하게 할당할 수 있어야 합니다. + +이러한 **프레임 할당**을 크게 두가지로 나눌수 있습니다. + +1. 정적 할당 방식 +2. 동적 할당 방식 + +
+
+ +## 정적 할당 방식 + +--- + +정적할당방식은 두가지로 나누어집니다. + +1. **균등할당** +2. **비례할당** + +
+ +### 균등할당 + +균등할당은 이름에서 알 수 있듯이 모든 프로세스에 프레임을 균등하게 할당하는 방식입니다. +프로세스가 3개가 있고, 프레임이 300개가 있다면 각 프로세스는 100개의 프레임을 할당받게 됩니다. + +이러한 방식은 프로세스 크기도 각자 다른 상황에서 합리적이지 못한 선택입니다. + +
+ +### 비례할당 + +크기가 큰 프로세스에 더 많은 프레임을 할당하는 방식을 비례할당이라고 부릅니다. +하지만 이러한 방식은 **정적**이라는 한계점을 가지고 있습니다. + +실제 프로세스를 실행해보면 크기와 상관없이 더 많은 프레임을 필요로 하거나 그렇지 않은 프로세스들이 존재합니다. +이러한 문제 떄문에 비례할당도 합리적이라고 할 수 없습니다. + +
+ +## 동적 할당 방식 + +--- + +동적할당방식에는 크게 두가지로 나누어집니다. + +1. 작업 직합 모델(working set model) +2. 페이지 폴트 빈도(PFF: page fault frequency) + +
+ +### 작업 집합 모델 + +작업 집합 모델에서는 '프로세스가 일정 기간 동안 참조한 페이지 집합'을 기억하며 빈번한 페이지 교체를 방지합니다. +예를 들어 프로세스가 3초동안 20개의 페이지를 집중적으로 참조했다면 20개의 프레임을 할당하면 효율적일 것입니다. + +이렇게 실행 중인 프로세스가 일정 시간 동안 참조한 페이지의 집합을 **작업 집합**이라고 합니다. + +
+
+ +### 페이지 폴트 빈도 + +![img.png](page_fault.png) + +페이지 폴트 빈도 방식은 해당 그래프를 통해 이루어 집니다. +가로축은 할당된 프레임을 나타내며 세로축은 페이지 폴트율을 나타냅니다. +할당된 프레임은 적으면 페이지 폴트가 많이 발생하는 형상이 됩니다. + +이러한 그래프에서 상한과 하한을 정한다음 해당 적정 구간에 들어올 수 있도록 프레임을 할당해주는 +방식을 **페이지 폴트 빈도**방식이라고 합니다. + + + + +## 출처 + +--- + +[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard) diff --git a/contents/posts/operation-system/jc23/lru.png b/contents/posts/operation-system/jc23/lru.png new file mode 100644 index 0000000..7dfa903 Binary files /dev/null and b/contents/posts/operation-system/jc23/lru.png differ diff --git a/contents/posts/operation-system/jc23/optimal_page_replace.png b/contents/posts/operation-system/jc23/optimal_page_replace.png new file mode 100644 index 0000000..6bff461 Binary files /dev/null and b/contents/posts/operation-system/jc23/optimal_page_replace.png differ diff --git a/contents/posts/operation-system/jc23/page_fault.png b/contents/posts/operation-system/jc23/page_fault.png new file mode 100644 index 0000000..9eb3ef9 Binary files /dev/null and b/contents/posts/operation-system/jc23/page_fault.png differ diff --git "a/contents/posts/operation-system/3/\354\235\264\354\244\221\353\252\250\353\223\234.png" b/contents/posts/operation-system/jc3/dual_mode.png similarity index 100% rename from "contents/posts/operation-system/3/\354\235\264\354\244\221\353\252\250\353\223\234.png" rename to contents/posts/operation-system/jc3/dual_mode.png diff --git a/contents/posts/operation-system/3/index.md b/contents/posts/operation-system/jc3/index.md similarity index 95% rename from contents/posts/operation-system/3/index.md rename to contents/posts/operation-system/jc3/index.md index 8364cbb..56caa2b 100644 --- a/contents/posts/operation-system/3/index.md +++ b/contents/posts/operation-system/jc3/index.md @@ -1,5 +1,5 @@ --- -title: "3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리" +title: "유저모드와 커널모드 전환, 시스템 콜의 동작 원리" description: "유저모드와 커널모드 전환, 시스템 콜의 동작 원리" date: 2025-09-06 update: 2025-09-06 @@ -21,7 +21,7 @@ series: "운영체제 기본 개념"
-![img.png](이중모드.png) +![img.png](dual_mode.png)
@@ -55,7 +55,7 @@ series: "운영체제 기본 개념"
-![img.png](시스템콜.png) +![img.png](system_call.png)
@@ -67,7 +67,7 @@ series: "운영체제 기본 개념"
-![img.png](시스템콜작동방식.png) +![img.png](system_call_method.png)
diff --git "a/contents/posts/operation-system/3/\354\213\234\354\212\244\355\205\234\354\275\234.png" b/contents/posts/operation-system/jc3/system_call.png similarity index 100% rename from "contents/posts/operation-system/3/\354\213\234\354\212\244\355\205\234\354\275\234.png" rename to contents/posts/operation-system/jc3/system_call.png diff --git "a/contents/posts/operation-system/3/\354\213\234\354\212\244\355\205\234\354\275\234\354\236\221\353\217\231\353\260\251\354\213\235.png" b/contents/posts/operation-system/jc3/system_call_method.png similarity index 100% rename from "contents/posts/operation-system/3/\354\213\234\354\212\244\355\205\234\354\275\234\354\236\221\353\217\231\353\260\251\354\213\235.png" rename to contents/posts/operation-system/jc3/system_call_method.png diff --git a/contents/posts/operation-system/4/index.md b/contents/posts/operation-system/jc4/index.md similarity index 92% rename from contents/posts/operation-system/4/index.md rename to contents/posts/operation-system/jc4/index.md index 0dd73dc..6c0eeed 100644 --- a/contents/posts/operation-system/4/index.md +++ b/contents/posts/operation-system/jc4/index.md @@ -1,5 +1,5 @@ --- -title: "4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념" +title: "멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념" description: "멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념" date: 2025-09-07 update: 2025-09-07 @@ -18,7 +18,7 @@ series: "운영체제 기본 개념"
-![img.png](단일프로세스.png) +![img.png](single_process.png)
CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 IO작업동안 CPU는 멈추게 @@ -28,7 +28,7 @@ CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 ## 멀티 프로그래밍 -![img.png](멀티프로그래밍.png) +![img.png](multiprograming.png) 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다. 이를 멀티 프로그래밍이라고 부르며 그림처럼 CPU 사용률을 높이기 위한 목적이었습니다. @@ -40,7 +40,7 @@ CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 ## 멀티 태스킹 -![img.png](멀티태스킹.png) +![img.png](multitasking.png) 멀티 프로그래밍 방식에서 더 나아가 모든 프로세스가 공정하게 특정 짧은 시간만 실행되게 반복한다면 길게 시행되는 프로세스 뒤에 오는 프로세스가 기다리는 문제가 없을 것이다. 이것이 멀티태스킹을 사용하는 이유입니다. @@ -58,7 +58,7 @@ CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 이전 방식은 하나의 **CPU**를 어떻게 쪼개서 사용할까라는 목적이였다면, **멀티 프로세싱**은 **CPU** 작업단위인 코어 자체를 늘려서 여러 CPU코어가 동시에 작업하는것을 멀티 프로세싱이라고 부르게 됩니다. -![img.png](멀티프로세싱.png) +![img.png](multiprocessing.png) 멀티 프로세싱은 CPU코어 수를 늘리는 방법이기 때문에, 이를 어떻게 처리할까에 대한 내용은 멀티 프로세싱 자체의 내용이 아니고 앞서 나왔던 방법론을 도입할 수 있습니다. 그림처럼 하나의 프로세스를 여러 코어가 담당하는 방법이나, 여러 프로세스를 여러 코어가 담당 할 수 도 있습니다. diff --git "a/contents/posts/operation-system/4/\353\251\200\355\213\260\355\224\204\353\241\234\354\204\270\354\213\261.png" b/contents/posts/operation-system/jc4/multiprocessing.png similarity index 100% rename from "contents/posts/operation-system/4/\353\251\200\355\213\260\355\224\204\353\241\234\354\204\270\354\213\261.png" rename to contents/posts/operation-system/jc4/multiprocessing.png diff --git "a/contents/posts/operation-system/4/\353\251\200\355\213\260\355\224\204\353\241\234\352\267\270\353\236\230\353\260\215.png" b/contents/posts/operation-system/jc4/multiprograming.png similarity index 100% rename from "contents/posts/operation-system/4/\353\251\200\355\213\260\355\224\204\353\241\234\352\267\270\353\236\230\353\260\215.png" rename to contents/posts/operation-system/jc4/multiprograming.png diff --git "a/contents/posts/operation-system/4/\353\251\200\355\213\260\355\203\234\354\212\244\355\202\271.png" b/contents/posts/operation-system/jc4/multitasking.png similarity index 100% rename from "contents/posts/operation-system/4/\353\251\200\355\213\260\355\203\234\354\212\244\355\202\271.png" rename to contents/posts/operation-system/jc4/multitasking.png diff --git "a/contents/posts/operation-system/4/\353\213\250\354\235\274\355\224\204\353\241\234\354\204\270\354\212\244.png" b/contents/posts/operation-system/jc4/single_process.png similarity index 100% rename from "contents/posts/operation-system/4/\353\213\250\354\235\274\355\224\204\353\241\234\354\204\270\354\212\244.png" rename to contents/posts/operation-system/jc4/single_process.png diff --git a/contents/posts/operation-system/5/DMA.png b/contents/posts/operation-system/jc5/DMA.png similarity index 100% rename from contents/posts/operation-system/5/DMA.png rename to contents/posts/operation-system/jc5/DMA.png diff --git a/contents/posts/operation-system/5/Interrupts.png b/contents/posts/operation-system/jc5/Interrupts.png similarity index 100% rename from contents/posts/operation-system/5/Interrupts.png rename to contents/posts/operation-system/jc5/Interrupts.png diff --git a/contents/posts/operation-system/5/index.md b/contents/posts/operation-system/jc5/index.md similarity index 97% rename from contents/posts/operation-system/5/index.md rename to contents/posts/operation-system/jc5/index.md index 7f9501e..13d4e3a 100644 --- a/contents/posts/operation-system/5/index.md +++ b/contents/posts/operation-system/jc5/index.md @@ -1,5 +1,5 @@ --- -title: "5. 인터럽트와 DMA를 통한 효율적 입출력 처리" +title: "인터럽트와 DMA를 통한 효율적 입출력 처리" description: "인터럽트와 DMA를 통한 효율적 입출력 처리" date: 2025-09-08 update: 2025-09-08 diff --git "a/contents/posts/operation-system/6/\353\271\204\353\217\231\352\270\260\354\213\235IO.png" b/contents/posts/operation-system/jc6/asynchronous_io.png similarity index 100% rename from "contents/posts/operation-system/6/\353\271\204\353\217\231\352\270\260\354\213\235IO.png" rename to contents/posts/operation-system/jc6/asynchronous_io.png diff --git a/contents/posts/operation-system/6/index.md b/contents/posts/operation-system/jc6/index.md similarity index 96% rename from contents/posts/operation-system/6/index.md rename to contents/posts/operation-system/jc6/index.md index 821b7fd..bdfce74 100644 --- a/contents/posts/operation-system/6/index.md +++ b/contents/posts/operation-system/jc6/index.md @@ -1,5 +1,5 @@ --- -title: "6. 동기식/비동기식 I/O의 차이와 활용 사례" +title: "동기식/비동기식 I/O의 차이와 활용 사례" description: "동기식/비동기식 I/O의 차이와 활용 사례" date: 2025-09-09 update: 2025-09-09 @@ -66,7 +66,7 @@ IO를 다루는 방법에는 동기, 비동기에 대한 개념이 등장합니 ## 동기식 I/O -![img.png](동기식IO.png) +![img.png](synchronous_io.png)
@@ -78,7 +78,7 @@ I/O작업이 완료되면 인터럽트를 통해 완료를 알리게 됩니다. ## 비동기식 I/O -![img.png](비동기식IO.png) +![img.png](asynchronous_io.png) 비동기식IO는 IO요청이 발생하였을 떄 이전 비동기 설명처럼 IO요청을 기다리지 않는 방식입니다. 프로그램이 IO 작업을 요청하고, 그 작업이 완료되기를 기다리지 않고 즉시 다음 작업으로 넘어가는 방식입니다. diff --git "a/contents/posts/operation-system/6/\353\217\231\352\270\260\354\213\235IO.png" b/contents/posts/operation-system/jc6/synchronous_io.png similarity index 100% rename from "contents/posts/operation-system/6/\353\217\231\352\270\260\354\213\235IO.png" rename to contents/posts/operation-system/jc6/synchronous_io.png diff --git a/contents/posts/operation-system/7/PCB.png b/contents/posts/operation-system/jc7/PCB.png similarity index 100% rename from contents/posts/operation-system/7/PCB.png rename to contents/posts/operation-system/jc7/PCB.png diff --git a/contents/posts/operation-system/7/index.md b/contents/posts/operation-system/jc7/index.md similarity index 97% rename from contents/posts/operation-system/7/index.md rename to contents/posts/operation-system/jc7/index.md index 2bcb74f..e8c172f 100644 --- a/contents/posts/operation-system/7/index.md +++ b/contents/posts/operation-system/jc7/index.md @@ -1,5 +1,5 @@ --- -title: "7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기" +title: "프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기" description: "프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기" date: 2025-09-10 update: 2025-09-10 @@ -19,7 +19,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기"

-![img.png](실행중인 프로세스.png) +![img.png](process_in_mac.png)
위 사진처럼 보이는 것보다 더 많은 프로세스가 작동하고 있는데, 여기서 사용자가 볼 수 있는 프로세스를 포그라운드 프로세스 라며 명하며, @@ -68,7 +68,7 @@ PCB는 커널 영역에 생성되고, 수많은 프로세스를 PCB를 통해 ### 프로세스 ID -![img.png](프로세스ID.png) +![img.png](process_id.png) 프로세스 ID(PID)는 프로세스를 식별하기 위해 존재하는 고유 ID입니다. 메모장을 두개 킨다고 할지라도 다른 프로세스ID가 만들어지는 것처럼 중복된 활동이여도 하나의 프로세스는 고유한 ID를 가지게 됩니다. @@ -109,7 +109,7 @@ PCB는 커널 영역에 생성되고, 수많은 프로세스를 PCB를 통해 프로세스가 생성되면 커널 영역에 PCB가 생성됩니다. 그렇다면 커널 영역이 아닌 사용자 영역에는 어떤 데이터가 들어갈까요? -![img.png](메모리구조.png) +![img.png](memory_model.png) [사진출처](https://www.programmersought.com/article/98613694619/) diff --git "a/contents/posts/operation-system/7/\353\251\224\353\252\250\353\246\254\352\265\254\354\241\260.png" b/contents/posts/operation-system/jc7/memory_model.png similarity index 100% rename from "contents/posts/operation-system/7/\353\251\224\353\252\250\353\246\254\352\265\254\354\241\260.png" rename to contents/posts/operation-system/jc7/memory_model.png diff --git "a/contents/posts/operation-system/7/\355\224\204\353\241\234\354\204\270\354\212\244ID.png" b/contents/posts/operation-system/jc7/process_id.png similarity index 100% rename from "contents/posts/operation-system/7/\355\224\204\353\241\234\354\204\270\354\212\244ID.png" rename to contents/posts/operation-system/jc7/process_id.png diff --git "a/contents/posts/operation-system/7/\354\213\244\355\226\211\354\244\221\354\235\270 \355\224\204\353\241\234\354\204\270\354\212\244.png" b/contents/posts/operation-system/jc7/process_in_mac.png similarity index 100% rename from "contents/posts/operation-system/7/\354\213\244\355\226\211\354\244\221\354\235\270 \355\224\204\353\241\234\354\204\270\354\212\244.png" rename to contents/posts/operation-system/jc7/process_in_mac.png diff --git "a/contents/posts/operation-system/8/\353\254\270\353\247\245\352\265\220\355\231\230.png" b/contents/posts/operation-system/jc8/context_switching.png similarity index 100% rename from "contents/posts/operation-system/8/\353\254\270\353\247\245\352\265\220\355\231\230.png" rename to contents/posts/operation-system/jc8/context_switching.png diff --git a/contents/posts/operation-system/8/exec.png b/contents/posts/operation-system/jc8/exec.png similarity index 100% rename from contents/posts/operation-system/8/exec.png rename to contents/posts/operation-system/jc8/exec.png diff --git a/contents/posts/operation-system/8/fork.png b/contents/posts/operation-system/jc8/fork.png similarity index 100% rename from contents/posts/operation-system/8/fork.png rename to contents/posts/operation-system/jc8/fork.png diff --git a/contents/posts/operation-system/8/index.md b/contents/posts/operation-system/jc8/index.md similarity index 96% rename from contents/posts/operation-system/8/index.md rename to contents/posts/operation-system/jc8/index.md index b131ffa..aab5ec4 100644 --- a/contents/posts/operation-system/8/index.md +++ b/contents/posts/operation-system/jc8/index.md @@ -1,5 +1,5 @@ --- -title: "8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기" +title: "문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기" description: "프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기" date: 2025-09-11 update: 2025-09-11 @@ -22,7 +22,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기"
-![img.png](문맥교환.png) +![img.png](context_switching.png) [사진출처](https://yoongrammer.tistory.com/53) 결국 프로세스 A에서 B로 프로세스가 넘어가는 순간에 프로세스 A정보를 백업하고 그작업이 끝난다면 @@ -45,7 +45,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기" 프로세스 상태는 크게 다섯가지로 나뉠 수 있습니다. -![img.png](프로세스 상태 전이도.png) +![img.png](process_state.png) [사진출처](https://thebook.io/080367/0021/)
@@ -100,7 +100,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기"
-![img.png](프로세스 계층 구조.png) +![img.png](process_layer.png) [사진 출처: 혼자 공부하는 운영체제 저자:강민철]
diff --git "a/contents/posts/operation-system/8/\355\224\204\353\241\234\354\204\270\354\212\244 \352\263\204\354\270\265 \352\265\254\354\241\260.png" b/contents/posts/operation-system/jc8/process_layer.png similarity index 100% rename from "contents/posts/operation-system/8/\355\224\204\353\241\234\354\204\270\354\212\244 \352\263\204\354\270\265 \352\265\254\354\241\260.png" rename to contents/posts/operation-system/jc8/process_layer.png diff --git "a/contents/posts/operation-system/8/\355\224\204\353\241\234\354\204\270\354\212\244 \354\203\201\355\203\234 \354\240\204\354\235\264\353\217\204.png" b/contents/posts/operation-system/jc8/process_state.png similarity index 100% rename from "contents/posts/operation-system/8/\355\224\204\353\241\234\354\204\270\354\212\244 \354\203\201\355\203\234 \354\240\204\354\235\264\353\217\204.png" rename to contents/posts/operation-system/jc8/process_state.png diff --git a/contents/posts/operation-system/9/TCB.png b/contents/posts/operation-system/jc9/TCB.png similarity index 100% rename from contents/posts/operation-system/9/TCB.png rename to contents/posts/operation-system/jc9/TCB.png diff --git a/contents/posts/operation-system/9/TCB2.png b/contents/posts/operation-system/jc9/TCB2.png similarity index 100% rename from contents/posts/operation-system/9/TCB2.png rename to contents/posts/operation-system/jc9/TCB2.png diff --git "a/contents/posts/operation-system/9/TCB\355\231\225\354\236\245.png" b/contents/posts/operation-system/jc9/TCB3.png similarity index 100% rename from "contents/posts/operation-system/9/TCB\355\231\225\354\236\245.png" rename to contents/posts/operation-system/jc9/TCB3.png diff --git a/contents/posts/operation-system/9/index.md b/contents/posts/operation-system/jc9/index.md similarity index 95% rename from contents/posts/operation-system/9/index.md rename to contents/posts/operation-system/jc9/index.md index e0e774a..8d44fc5 100644 --- a/contents/posts/operation-system/9/index.md +++ b/contents/posts/operation-system/jc9/index.md @@ -1,5 +1,5 @@ --- -title: "9. 쓰레드의 개념, 메모리 공유 구조 및 TCB" +title: "쓰레드의 개념, 메모리 공유 구조 및 TCB" description: "쓰레드의 개념, 메모리 공유 구조 및 TCB" date: 2025-09-12 update: 2025-09-12 @@ -12,7 +12,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기" --- -![img.png](스레드.png) +![img.png](thread.png)
@@ -34,7 +34,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기" 전통적인 CPU는 하나의 프로세스만 처리할 수 있었습니다. 메모장, 워드, 게임등 많은 프로세스가 하나의 실행 흐름을 가지고 한 번의 하나의 부분만 실행되는 프로세스입니다. -![img.png](단일스레드 프로세스.png) +![img.png](single_process.png) 이런 프로세스를 단일 스레드 프로세스라고 부릅니다. @@ -43,7 +43,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기" 하지만, 스레드라는 개념이 도입되면서 하나의 프로세스가 한 번에 여러가지 일을 동시에 처리하는 것이 가능해졌습니다. 프로세스를 구성하는 명령어를 동시에 처리하는것이 가능해졌습니다. -![img.png](멀티스레드 프로세스.png) +![img.png](multi_thread_process.png)
@@ -59,7 +59,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기" --- -![img.png](메모리구조.png) +![img.png](memory_model.png) 스레드의 메모리 구조를 이해하기 위해서는 이전 프로세서의 구조를 상기해봐야 합니다. @@ -74,7 +74,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기"
-![img.png](스레드자원공유.png) +![img.png](thread_resource.png) [사진출처](https://gmlwjd9405.github.io/2017/10/01/basic-concepts-of-development-os.html)
@@ -113,7 +113,7 @@ series: "프로세스와 쓰레드에 대해서 알아보기" -![img.png](TCB확장.png) +![img.png](TCB3.png)
diff --git "a/contents/posts/operation-system/9/\353\251\224\353\252\250\353\246\254\352\265\254\354\241\260.png" b/contents/posts/operation-system/jc9/memory_model.png similarity index 100% rename from "contents/posts/operation-system/9/\353\251\224\353\252\250\353\246\254\352\265\254\354\241\260.png" rename to contents/posts/operation-system/jc9/memory_model.png diff --git "a/contents/posts/operation-system/9/\353\251\200\355\213\260\354\212\244\353\240\210\353\223\234 \355\224\204\353\241\234\354\204\270\354\212\244.png" b/contents/posts/operation-system/jc9/multi_thread_process.png similarity index 100% rename from "contents/posts/operation-system/9/\353\251\200\355\213\260\354\212\244\353\240\210\353\223\234 \355\224\204\353\241\234\354\204\270\354\212\244.png" rename to contents/posts/operation-system/jc9/multi_thread_process.png diff --git "a/contents/posts/operation-system/9/\353\213\250\354\235\274\354\212\244\353\240\210\353\223\234 \355\224\204\353\241\234\354\204\270\354\212\244.png" b/contents/posts/operation-system/jc9/single_process.png similarity index 100% rename from "contents/posts/operation-system/9/\353\213\250\354\235\274\354\212\244\353\240\210\353\223\234 \355\224\204\353\241\234\354\204\270\354\212\244.png" rename to contents/posts/operation-system/jc9/single_process.png diff --git "a/contents/posts/operation-system/9/\354\212\244\353\240\210\353\223\234.png" b/contents/posts/operation-system/jc9/thread.png similarity index 100% rename from "contents/posts/operation-system/9/\354\212\244\353\240\210\353\223\234.png" rename to contents/posts/operation-system/jc9/thread.png diff --git "a/contents/posts/operation-system/9/\354\212\244\353\240\210\353\223\234\354\236\220\354\233\220\352\263\265\354\234\240.png" b/contents/posts/operation-system/jc9/thread_resource.png similarity index 100% rename from "contents/posts/operation-system/9/\354\212\244\353\240\210\353\223\234\354\236\220\354\233\220\352\263\265\354\234\240.png" rename to contents/posts/operation-system/jc9/thread_resource.png diff --git a/contents/posts/os/hs1/img.png b/contents/posts/os/hs1/img.png new file mode 100644 index 0000000..390a74c Binary files /dev/null and b/contents/posts/os/hs1/img.png differ diff --git a/contents/posts/os/hs1/img_1.png b/contents/posts/os/hs1/img_1.png new file mode 100644 index 0000000..12838a9 Binary files /dev/null and b/contents/posts/os/hs1/img_1.png differ diff --git a/contents/posts/os/hs1/img_3.png b/contents/posts/os/hs1/img_3.png new file mode 100644 index 0000000..f89bf16 Binary files /dev/null and b/contents/posts/os/hs1/img_3.png differ diff --git a/contents/posts/os/hs1/img_4.png b/contents/posts/os/hs1/img_4.png new file mode 100644 index 0000000..6e0c097 Binary files /dev/null and b/contents/posts/os/hs1/img_4.png differ diff --git a/contents/posts/os/hs1/index.md b/contents/posts/os/hs1/index.md new file mode 100644 index 0000000..cd70f96 --- /dev/null +++ b/contents/posts/os/hs1/index.md @@ -0,0 +1,93 @@ +--- +title: "1. 운영체제의 개념과 구조" +description: +date: 2025-09-03 +update: 2025-09-03 +tags: + - 운영체제 +series: "운영체제" +--- + +## 운영체제(OS, Operating System) + +[운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다.](https://en.wikipedia.org/wiki/Operating_system#:~:text=An%20operating%20system%20(OS)%20is%20system%20software%20that%20manages%20computer%20hardware%20and%20software%20resources%2C%20and%20provides%20common%20services%20for%20computer%20programs.) + +![](img.png) + +운영체제가 없으면 어떻게 될까? 꼭 필요할까? + +> _A computer is a machine that can be programmed to automatically carry out sequences of arithmetic or logical operations_ +> (컴퓨터는 산술적 또는 논리적 연산(계산)의 순서를 자동으로 수행하도록 프로그래밍할 수 있는 기계이다). +> [ - wikepedia](https://en.wikipedia.org/wiki/Computer#:~:text=A%20computer%20is%20a%20machine%20that%20can%20be%20programmed%20to%20automatically%20carry%20out%20sequences%20of%20arithmetic%20or%20logical%20operations%20(computation).) + +운영체제가 없다면 컴퓨터는 그저 하드웨어의 집합체에 불과하다. +사용자는 프로그램을 실행하기 위해서 매번 하드웨어를 직접 제어해야 하며, 이렇게 하는 것은 매우 비효율적일거다. +또한 직접 제어를 한다고 해도 하드웨어의 성능은 제한적이므로 이 환경에서 최대한의 성능을 끌어내기 위해 최적화라는 고통스러운 작업을 해야 할 것이다. +이러한 상황을 상상해보면 "배보다 배꼽이 더 크다"라는 말이 떠오른다. + +실제로 운영체제라는 개념이 있기 전에는 사용자들이 하나의 작업을 위해 펀치카드를 소지하며 관리해야 했다. +그리고 단순 하드웨어에 올려 실행하는 과정의 방식이기에 한 번에 하나의 프로그램만 실행할 수 있었고, 해당 프로그램이 끝나야 다른 프로그램을 수행할 수 있었다. +지금처럼 복잡한 방식의 프로그램은 꿈도 꿀 수 없었을 것이다. + +이러한 문제를 해결하기 위해 운영체제가 나왔고, 다음과 같은 목적을 지닌다. + +- 사용자에게 컴퓨터의 프로그램을 쉽고 효율적으로 실행할 수 있는 환경을 제공한다. +- 컴퓨터 시스템 하드웨어 및 소프트웨어 자원을 여러 사용자 간에 효율적 할당, 관리, 보호하는 것 +- 운영체제는 제어 프로그램으로서 사용자 프로그램의 오류나 잘못된 자원 사용을 감시하는 것과 입출력 장치 등의 자원에 대한 연산과 제어를 관리한다. + +운영체제은 위와 같은 목적을 위해 다양한 방식을 가지고 있다. + +### 일괄 처리 시스템 (Batch Operating System) + +사용자의 개입없이 비슷한 작업들을 모아서 순차적으로 처리하는 방식이다. +한 작업이 끝나야 다음 작업이 실행되기 때문에 모든 작업이 완료될 때까지 기다릴 수 있는 환경에서 사용된다. +주로 대용량 데이터를 처리하거나 시간이 많이 소요되는 작업에 활용되며, 사용자의 개입이 필요하지 않고 반복적인 작업을 일괄적으로 처리할 수 있다. + +### 다중 프로그래밍 시스템 (Multi Programming System) + +이 방식은 CPU을 최대한 사용하고 하는 방식으로, +여러 응용프로그램을 메모리에 동시에 올라가 CPU가 쉬지 않고 여러 작업을 번갈아서 실행하며 항상 연산을 수행하는 상태로 활용하는 방식이다. +하나의 프로그램을 실행하는 동안 다른 프로그램은 대기하거나 I/O 작업 등을 수행하며 메모리에 올라간 상태로 대기하게 된다. +운영 체제는 이런 과정에서 CPU를 배분하는 작업 스케줄링과 CPU 스케줄링을 진행하며, +이를 통해 시스템 자원을 효율적으로 활용하고 응용 프로그램들이 서로 영향을 주지 않으면서 병렬적으로 실행된다. + +### 시분할 시스템 (Time Sharing System) + +이 방식은 CPU에 대해 일정 시간을 할당 받아 짧은 간격으로 번갈아 실행하는 방식이다. +다중 프로그래밍 시스템에서는 Context Switching(CPU 점유 권한 전환)이 I/O작업에서만 발생한다. +이를 통해서만 스케줄링을 할 경우 하나의 프로세스가 아주 오래 CPU를 독점하고 있는 상태가 발생할 수 있다는 문제점이 있다. +이를 해결하기 위한 것이 시분할 시스템으로, 다중 프로그래밍과 비슷하지만 모든 프로세스가 특정 시간만 CPU를 점유하고 다른 프로세스에 권한을 넘겨주는 방식으로 +Context Switching 기준 시간으로 시분할을 구현해서 RR(Round-Robin) 알고리즘으로 스케줄링을 한다. + +### 대화형 시스템(Interactive System) + +앞서 설명한 일괄 처리 시스템은 처리해야할 작업들을 한번에 정의하고 일괄적으로 처리하는 방식이었다. +이러한 일괄 처리 시스템의 문제점은 처리가 이루어지는 중에 시스템의 상태를 확인하기가 힘들고, +작업이 끝나 결과가 도출되기 전까지는 작업을 수정할 수도 없다는 문제점이 있었다. +이를 보완하기위해 등장한 시스템이 대화형 시스템으로, +작업 중에도 사용자가 데이터, 명령 또는 작업을 입력하면 컴퓨터가 즉각적으로 해당 입력에 응답하는 사용자와 컴퓨터 간의 상호작용을 통해 작동하는 방식이다. + +## 커널(Kernel) + +그럼 우리들의 컴퓨터 속 운영체제는 어떻게 이러한 기능을 수행하고 있을까? + +[운영체제의 이러한 핵심적인 부분을 담당하고 수행하는 것이 바로 커널이다.](https://en.wikipedia.org/wiki/Kernel_(operating_system)#:~:text=A%20kernel%20is%20a%20computer%20program%20at%20the%20core%20of%20a%20computer%27s%20operating%20system%20that%20always%20has%20complete%20control%20over%20everything%20in%20the%20system.) + +![](img_3.png) +커널을 한글로 번역하면 핵심이다! 재밌지 아니한가? 아무튼 다시 돌아와서 커널은 어떻게 운영체제의 기능을 수행할까? + +[커널은 하드웨어를 인터페이스로 제공하여 여러 사용자 또는 여러 프로세스가 하드웨어 즉 리소스를 효율적으로 관리하며 작업을 수행할 수 있도록 해준다.](https://en.wikipedia.org/wiki/Kernel_(operating_system)#:~:text=The%20kernel%27s%20interface%20is%20a%20low%2Dlevel%20abstraction%20layer.%20When%20a%20process%20requests%20a%20service%20from%20the%20kernel%2C%20it%20must%20invoke%20a%20system%20call%2C%20usually%20through%20a%20wrapper%20function.) +여기서 중요한 점은 커널은 사용자가 직접 제어할 수는 없다. +그 이유는 보안상 유저 어플리케이션이 함부로 운영체제의 리소스를 건들지 못하게 하기 위해서다. +그래서 커널에는 하드웨어에 접근이 허가된 커널모드와 그렇지 못한 유저모드로 분리가 되어있다. + +![](img_1.png) + +커널의 구조는 위 사진과 같은데, 간단한 흐름을 설명하자면 사용자가 유저모드인 어플리케이션을 실행하면서 발생하는 요청이 시스템 콜을 통해 커널 모드로 전환이 된다. +애플리케이션은 커널모드로 전환되었다가 작업을 끝낸 후 응답을 반환하면서 다시 유저모드로 되돌아 가게 된다. +여기서 시스템 콜은 뭐지 싶을텐데 [어플리케이션의 요청이 커널에 접근해 시스템에 요청하는 것](https://en.wikipedia.org/wiki/System_call#:~:text=In%20computing%2C%20a%20system%20call%20(syscall)%20is%20the%20programmatic%20way%20in%20which%20a%20computer%20program%20requests%20a%20service%20from%20the%20operating%20system%5Ba%5D%20on%20which%20it%20is%20executed.)으로 간단히 유저모드에서 커널모드로 전환하는 것이라고 생각하면 된다. + +![](img_4.png) + +이러한 방식을 통해 사용자의 프로세스가 직접적으로 운영체제의 리소스를 함부로 변경하지 못하게 보호해준다. + diff --git a/contents/posts/os/hs2/img.png b/contents/posts/os/hs2/img.png new file mode 100644 index 0000000..8dfbbbb Binary files /dev/null and b/contents/posts/os/hs2/img.png differ diff --git a/contents/posts/os/hs2/img_1.png b/contents/posts/os/hs2/img_1.png new file mode 100644 index 0000000..ac1f74c Binary files /dev/null and b/contents/posts/os/hs2/img_1.png differ diff --git a/contents/posts/os/hs2/img_2.png b/contents/posts/os/hs2/img_2.png new file mode 100644 index 0000000..33e4d72 Binary files /dev/null and b/contents/posts/os/hs2/img_2.png differ diff --git a/contents/posts/os/hs2/img_3.png b/contents/posts/os/hs2/img_3.png new file mode 100644 index 0000000..934762f Binary files /dev/null and b/contents/posts/os/hs2/img_3.png differ diff --git a/contents/posts/os/hs2/img_4.png b/contents/posts/os/hs2/img_4.png new file mode 100644 index 0000000..f66afd8 Binary files /dev/null and b/contents/posts/os/hs2/img_4.png differ diff --git a/contents/posts/os/hs2/index.md b/contents/posts/os/hs2/index.md new file mode 100644 index 0000000..fb5e4c0 --- /dev/null +++ b/contents/posts/os/hs2/index.md @@ -0,0 +1,75 @@ +--- +title: "2. 커널의 작동 방식" +description: +date: 2025-09-04 +update: 2025-09-04 +tags: + - 운영체제 +series: "운영체제" +--- + +앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다. +이제 커널이 어떻게 작동하는지 제대로 알아보자. + +먼저 인터럽트(Interrupt)에 대해 알아야 한다. + +![img_3.png](img_3.png) + +컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데 +이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다. +이중 하나가 인터럽트이다. + +![](img.png) +인터럽트는 중단시키다라는 의미로 초인종과 같다고 할 수 있다. +즉, 인터럽트가 발생하면 잠깐 멈추고 다시 실행된다. + +![](img_1.png) + +실제 발생하는 대부분의 인터럽트는 I/O 인터럽트이다. +예를들면, 우리가 자바에서 print을 할 때 print라는 API를 파일이라는 인터페이스를 통해서 유저모드에서 커널 모드로 시스템 콜이 발생한다. +유저모드 API에서 커널모드 구성요소에서 시스템 콜이 이어지고 디바이스 드라이버를 제어하기 시작하는데 +[이때 디바이스 드라이버가 인터럽트를 CPU에 요청한다. 이 행위를 IRQ라고 한다.](https://en.wikipedia.org/wiki/Interrupt_request#:~:text=In%20a%20computer,or%20mouse%20movements.) +이러한 IRQ는 장치마다 다른 번호로 관리하게 된다. +아무튼 출력기기에 출력이 되면, 다시 역순으로 디바이스(하드웨어)에서 디바이스 드라이버로, +디바이스 드라이버에서 커널 모드로 해서 최종적으로 유저 모드로 다시 돌아오게 된다. + +![](img_4.png) +이때, 이러한 행위 도중 wait을 걸면 블라킹(동기) 안걸면 논블라킹(비동기)으로 동작하게 된다. + +인터럽트에는 우선순위가 있고 외부 인터럽트인지 내부 인터럽트인지에 따라 우선순위가 달라진다. + +먼저, 외부 인터럽트로 내부 인터럽트보다 우선 시 된다. + +그 중에서도 우선 순위가 있는데, 다음과 같다. +- 전원 이상 인터럽트: 말 그대로 정전 또는 파워 이상 +- 기계 착오 인터럽트: CPU의 기능적인 오류. +- 외부 신호 인터럽트: 타이머 또는, 키보드 인터럽트 키(Ctrl + Alt + Delete). 외부장치로부터 인터럽트 요청이 있는 경우. I/O 인터럽트와 다른 개념이다. +- 입출력 인터럽트: 입출력 장치가 데이터 전송을 요구하거나 전송이 끝나 다음 동작이 수행되어야 할 경우. 입출력 데이터에 이상이 있는 경우. 우리가 자주 다루게 될 인터럽트 부분이다. + +이제 내부 인터럽트인데, 사실 우리가 주로 다루게 될 것은 외부 인터럽트에 있어 내부 인터럽트는 뭐가 있는지만 대강 본다. + +- 명령어 잘못 인터럽트: 잘못된 명령어나 잘못된 데이터를 사용할 때 발생하며 Trap이라 부른다, +- 프로그램 검사 +- 소프트웨어 인터럽트(=SVC, SuperVisor Call) + +인터럽트 동작 순서에 대해 다시 살펴보면 다음과 같은데, + +1. 인터럽트 요청 +2. 프로그램 실행 중단 +3. 현재 프로그램 상태 보존 -> PCB(Process Control Block), PC(Program Counter) 등 +4. 인터럽트 서비스 루틴 실행: 인터럽트 처리 코드 +5. 상태 복구 +6. 중단 프로그램 실행 재개 + +![](img_2.png) + +이 과정에서 유저모드에서 커널모드로 넘어갈 떄 컨텍스트 스위칭이 되면서 오버헤드가 발생하는데 이로 인해 시스템 상 지연이 발생한다. +하지만 고성능 어플리케이션을 할 때 이 지연은 꽤나 치명적일 것이다. +그래서 위와 같이 DMA(Direct Memory Access)라는 기술을 사용하게 됐다. +예를들어, DirectX라는 것이 있는데 이는 게임을 할 때 이러한 컨텍스트 스위칭 되는 부분을 건너뛰어 직접 드라이버까지 가는 방식이 있다. +이렇듯 DirectX처럼 인터럽트 시 컨텍스트 스위칭으로 인한 오버헤드가 발생하면서 지연이 발생하는데 이걸 해소하는 것이 DMA인 것이다. +정리하자면, [DMA는 RAM에 일정 부분을 예약해 불필요한 컨텍스트 스위칭을 스킵해 오버헤드 방지 및 지연을 획기적으로 줄이는 방식이다.](https://en.wikipedia.org/wiki/Direct_memory_access#:~:text=DMA%20(%20Direct%20Memory%20Access%20)%EB%8A%94%20%ED%8A%B9%EC%A0%95%20%ED%95%98%EB%93%9C%EC%9B%A8%EC%96%B4%20%ED%95%98%EC%9C%84%20%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%B4%20%EC%A4%91%EC%95%99%20%EC%B2%98%EB%A6%AC%20%EC%9E%A5%EC%B9%98%20(CPU)%20%EC%99%80%20%EB%8F%85%EB%A6%BD%EC%A0%81%EC%9C%BC%EB%A1%9C%20%EC%A3%BC%20%EC%8B%9C%EC%8A%A4%ED%85%9C%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EC%97%90%20%EC%95%A1%EC%84%B8%EC%8A%A4%ED%95%A0%20%EC%88%98%20%EC%9E%88%EB%8F%84%EB%A1%9D%20%ED%95%98%EB%8A%94%20%EC%BB%B4%ED%93%A8%ED%84%B0%20%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98%20%EA%B8%B0%EB%8A%A5%EC%9E%85%EB%8B%88%EB%8B%A4%20.) + + + + diff --git a/contents/posts/os/hs3/img.png b/contents/posts/os/hs3/img.png new file mode 100644 index 0000000..61552c6 Binary files /dev/null and b/contents/posts/os/hs3/img.png differ diff --git a/contents/posts/os/hs3/img_1.png b/contents/posts/os/hs3/img_1.png new file mode 100644 index 0000000..59f1ceb Binary files /dev/null and b/contents/posts/os/hs3/img_1.png differ diff --git a/contents/posts/os/hs3/img_2.png b/contents/posts/os/hs3/img_2.png new file mode 100644 index 0000000..3c39dda Binary files /dev/null and b/contents/posts/os/hs3/img_2.png differ diff --git a/contents/posts/os/hs3/img_3.png b/contents/posts/os/hs3/img_3.png new file mode 100644 index 0000000..9da3b71 Binary files /dev/null and b/contents/posts/os/hs3/img_3.png differ diff --git a/contents/posts/os/hs3/index.md b/contents/posts/os/hs3/index.md new file mode 100644 index 0000000..69fda68 --- /dev/null +++ b/contents/posts/os/hs3/index.md @@ -0,0 +1,106 @@ +--- +title: "3. 프로세스" +description: +date: 2025-09-08 +update: 2025-09-08 +tags: + - 운영체제 +series: "운영체제" +--- + +## 프로세스란? + +![](img.png) + +컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 [인스턴스](https://ko.wikipedia.org/wiki/%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99)#:~:text=%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4(instance)%EB%8A%94%20%ED%95%B4%EB%8B%B9%20%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98%20%EA%B5%AC%EC%A1%B0%EB%A1%9C%20%EC%BB%B4%ED%93%A8%ED%84%B0%20%EC%A0%80%EC%9E%A5%EA%B3%B5%EA%B0%84%EC%97%90%EC%84%9C%20%ED%95%A0%EB%8B%B9%EB%90%9C%20%EC%8B%A4%EC%B2%B4%EB%A5%BC%20%EC%9D%98%EB%AF%B8%ED%95%9C%EB%8B%A4.)를 의미합니다. +여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다. + +## 프로세스의 메모리 공간 + +프로세스는 다음 4개의 메모리 영역으로 구성되고 [가상 메모리](https://ko.wikipedia.org/wiki/%EA%B0%80%EC%83%81_%EB%A9%94%EB%AA%A8%EB%A6%AC#:~:text=%EA%B0%80%EC%83%81%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EB%98%90%EB%8A%94%20%EA%B0%80%EC%83%81%20%EA%B8%B0%EC%96%B5%20%EC%9E%A5%EC%B9%98(%EB%AC%B8%ED%99%94%EC%96%B4%3A%20%EA%B0%80%EC%83%81%EA%B8%B0%EC%96%B5%EA%B8%B0%2C%20virtual%20memory%2C%20virtual%20storage)%EB%8A%94%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EA%B4%80%EB%A6%AC%20%EA%B8%B0%EB%B2%95%EC%9D%98%20%ED%95%98%EB%82%98%EB%A1%9C%2C%20%EC%BB%B4%ED%93%A8%ED%84%B0%20%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90%20%EC%8B%A4%EC%A0%9C%EB%A1%9C%20%EC%9D%B4%EC%9A%A9%20%EA%B0%80%EB%8A%A5%ED%95%9C%20%EA%B8%B0%EC%96%B5%20%EC%9E%90%EC%9B%90%EC%9D%84%20%EC%9D%B4%EC%83%81%EC%A0%81%EC%9C%BC%EB%A1%9C%20%EC%B6%94%EC%83%81%ED%99%94%ED%95%98%EC%97%AC%5B1%5D%20%EC%82%AC%EC%9A%A9%EC%9E%90%EB%93%A4%EC%97%90%EA%B2%8C%20%EB%A7%A4%EC%9A%B0%20%ED%81%B0%20(%EC%A3%BC)%20%EB%A9%94%EB%AA%A8%EB%A6%AC%EB%A1%9C%20%EB%B3%B4%EC%9D%B4%EA%B2%8C%20%EB%A7%8C%EB%93%9C%EB%8A%94%20%EA%B2%83%EC%9D%84%20%EB%A7%90%ED%95%9C%EB%8B%A4.%5B2%5D%20%EA%B0%81%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%97%90%20%EC%8B%A4%EC%A0%9C%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EC%A3%BC%EC%86%8C%EA%B0%80%20%EC%95%84%EB%8B%8C%20%EA%B0%80%EC%83%81%EC%9D%98%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EC%A3%BC%EC%86%8C%EB%A5%BC%20%EC%A3%BC%EB%8A%94%20%EB%B0%A9%EC%8B%9D%EC%9D%B4%EB%8B%A4.) 공간에 독립적으로 형성됩니다. + +- 코드 영역(Code) : 프로그램 실행 코드가 적재되는 영역입니다. 읽기 모드만 지원합니다. +- 데이터 영역(Data) : 프로세스의 초기화 된 데이터들인 전역 변수와 정적 변수들이 적재되는 영역입니다. +- 힙 영역(Heap) : 런타임 동안 생성된 데이터를 보관하기 위해 동적으로 할당받는 영역입니다. +- 스택 영역(Stack) : 지역변수, 매개변수, 리턴 값, 복귀 주소 등이 저장되는 영역입니다. + +이렇게 영역이 나눠진 이유는 최대한 중복적인 데이터를 방지하여 메모리 사용량을 줄이는데 목적이 있습니다. + +> 예를 들면, 코드에서 공통으로 사용하는 부분을 전역 변수로 지정하는 행위와 같다. + +## PCB(프로세스 제어 블록) + +커널은 시스템 전체에 대해 레지스터에 하나의 프로세스 테이블을 두고 모든 프로세스의 정보를 관리합니다. +여기서의 프로세스 정보는 해당 프로세스를 실행하기 위해 필요한 정보들로 컨텍스트라고 부릅니다. +여기서 프로세스의 상태에 따라 프로세스를 교체하는 작업인 컨텍스트 스위칭 작업 이루어 지는데, +이와 같은 상황에서 여러 프로세스를 관리하기 위해 각 프로세스들에 대해 식별이 가능해야 관리가 가능하기에 해당 프로세스의 정보가 필요합니다. + +예를 들어, 인터럽트가 발생해서 자원을 할당받은 프로세스가 대기 상태가 되고 다른 프로세스를 실행 상태로 올릴 때 +대기 중인 프로세스를 나중에 다시 수행하기 위해 대기 중인 프로세스의 상태와 같은 정보를 알아야 할 것입니다. + +운영체제의 커널은 이러한 이유로 활성된 프로세스를 관리하기 위해 해당 프로세스에 대한 정보를 PCB(프로세스 제어 블록)이라는 데이터 구조에 저장합니다. +("PCB는 운영 체제가 프로세스를 표현한 것이다."라는 말도 있습니다.) + +![](img_1.png) + +> PCB는 해당 프로세스가 실행되면 생성되어 종료 시 제거가 되는데 이 과정에서 PCB의 삽입 및 삭제가 용이한 연결 리스트(Linked List) 방식으로 관리됩니다. + +## Process Metadata + +그럼 PCB에는 어떤 정보가 담겨있을까요? +PCB에는 아래와 같은 프로세스의 메타데이터들이 담겨져 있습니다. + +- 프로세스 번호(PID, Process ID): 각 프로세스의 고유 식별 번호입니다.(PPID: 부모 프로세스 ID) +- 프로세스 상태(Process State): 프로세스가 현재 어떤 상태인지를 나타내는 정보(new, ready, running, waiting, end)입니다. +- 프로그램 카운터(PC, Program Counter): 이 프로세스에서 실행될 다음 명령어의 주소를 가리키는 포인터(주소)입니다. +- 레지스터 상태(Register State): 프로세스의 레지스터 값 세트로, 프로세스를 다시 실행할 때 현재 상태를 복원하는 데 사용됩니다. +- 스케줄링 정보(Scheduling Information): CPU 시간 스케줄링에 대한 정보입니다. +- 메모리 관리 정보 (Memory Management Information): 프로세스의 메모리 할당과 사용에 관한 정보입니다. +- 입출력 상태 (I/O Status): 프로세스가 입출력 작업을 수행 중인 경우, 해당 상태 정보 및 장치 정보입니다. + +## 프로세스 상태 + +운영체제의 커널은 프로세스를 관리하기 위해 프로세스 정보를 알아야 해서 PCB를 생성하는 것을 알았습니다. +여기서 커널의 프로세스 관리는 프로세스 상태를 관리하는 것이기도 합니다. + +프로세스 상태는 위에서 언급한대로 프로세스가 현재 어떤 상태인지를 나타내는 정보로, +프로세스의 상태에 따라 CPU를 할당하거나 대기 상태로 전환하는 등의 작업이 이루어집니다. +프로세스 상태는 일반적으로 다음과 같은 상태로 구분됩니다. + +![](img_2.png) + +- New(생성) : 프로세스는 저장장치에서 메모리로 로드되어 생성됩니다. 이후 커널은 메모리를 할당하고 PCB를 생성하고 프로세스 테이블에 등록합니다. 실행 준비를 마치면 ready 상태로 전이됩니다. +- Ready(준비) : 프로세스가 CPU를 사용하고 있지는 않지만 언제든지 사용할 수 있는 상태로, 해당 상태의 프로세스들은 커널에 있는 준비 큐([우선순위 큐](https://ko.wikipedia.org/wiki/%EB%B9%84%EC%9C%A8_%EB%8B%A8%EC%A1%B0_%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81))에 들어갑니다. 스케줄러가 컨텍스트 스위칭을 수행할 때, 준비 큐에서 우선순위가 높은 프로세스가 CPU 스케줄링에 따라 리소스를 할당받아 running 상태로 전이(디스패치)됩니다. +- Running(실행) : 프로세스가 CPU를 차지하여 명령어들이 실행되고 있는 상태입니다. 할당된 시간을 모두 사용(타임아웃)했다면 타이머 인터럽트가 발생되어 준비 상태로 전이되고, 입출력 요청이나 자원 요청 등으로 인해 대기 상태로 전이될 수도 있습니다. +- Waiting(대기) : 프로세스 실행 도중 입출력 완료(주된 원인)와 같은 수신 등을 대기하는 상태를 말합니다. +- End(=terminated, 종료) : 프로세스의 실행이 종료된 상태입니다. 이떄, PCB와 프로세스의 메모리를 해제 또는 정리합니다. + +## 프로세스 계층 구조 + +프로세스는 실행 도중 시스템 콜을 통해 다른 프로세스를 생성할 수 있습니다. +이때 시스템 콜을 호출한 프로세스를 부모 프로세스, 생성된 프로세스를 자식 프로세스라 합니다. + +> 서로 다른 프로세스라 서로 다른 PID를 가집니다. +> 일부 운영체제에서는 자식 프로세스의 PCB에 부모 프로세스의 PID (PPID)가 기록되기도 합니다. + +프로세스 생성 기법은 복제와 교체 과정을 통한 방식을 사용합니다. + +![](img_3.png) + +흐름의 시작인 부모 프로세스는 fork(복제) 시스템 콜을 통해 자신의 복사본을 자식 프로세스로 생성합니다. +자식 프로세스는 exec(교체) 시스템 콜을 통해 자신의 메모리 공간을 다른 프로그램으로 교체합니다. +이때, 자식 프로세스의 메모리 공간을 새로운 프로그램으로 덮어쓰게 합니다.(코드/데이터는 내용만 바꾸고, 나머지는 초기화) +자식 프로세스가 exec 시스템 콜을 호출하지 않을 경우, 부모 프로세스와 자식 프로세스는 같은 코드를 병행하여 실행하는 프로세스가 됩니다. +이러한 과정을 통해 프로세스는 계층 구조를 이루어 관리할 수 있습니다. + +많은 운영체제에서는 이처럼 프로세스를 낳는 계층적인 구조로써 프로세스들을 관리합니다. +컴퓨터가 부팅될 때 실행되는 최초의 프로세스가 자식 프로세스들을 생성하고, +생성된 자식 프로세스들이 새로운 프로세스들을 낳는 형식으로 여러 프로세스가 동시에 실행되는 것입니다. + +## 프로세스 간 통신 + +앞서 언급했던 것처럼 프로세스는 서로 독립된 메모리 공간을 가지므로, 프로세스끼리는 서로의 영역에 접근 또는 간섭할 수 없습니다. +이러한 이유로 통신이 필요할 경우, [IPC](https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4_%EA%B0%84_%ED%86%B5%EC%8B%A0#:~:text=%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%20%EA%B0%84%20%ED%86%B5%EC%8B%A0(Inter%2DProcess%20Communication%2C%20IPC)%EC%9D%B4%EB%9E%80%20%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%93%A4%20%EC%82%AC%EC%9D%B4%EC%97%90%20%EC%84%9C%EB%A1%9C%20%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC%20%EC%A3%BC%EA%B3%A0%EB%B0%9B%EB%8A%94%20%ED%96%89%EC%9C%84%20%EB%98%90%EB%8A%94%20%EA%B7%B8%EC%97%90%20%EB%8C%80%ED%95%9C%20%EB%B0%A9%EB%B2%95%EC%9D%B4%EB%82%98%20%EA%B2%BD%EB%A1%9C%EB%A5%BC%20%EB%9C%BB%ED%95%9C%EB%8B%A4.)를 통해 프로세스 간에 통신을 할 수 있습니다. +IPC에는 공유 메모리를 이용한 통신과 파일을 통한 프로세스 간 통신 이렇게 두 가지 방법이 있습니다. + +> IPC 통신 시, 프로세스 간 데이터를 동기화하고 보호하기 위해 [세마포어](https://ko.wikipedia.org/wiki/%EC%84%B8%EB%A7%88%ED%8F%AC%EC%96%B4)와 [뮤텍스](https://ko.wikipedia.org/wiki/%EC%83%81%ED%98%B8_%EB%B0%B0%EC%A0%9C)를 사용합니다. \ No newline at end of file diff --git a/contents/posts/os/hs4/img.png b/contents/posts/os/hs4/img.png new file mode 100644 index 0000000..c48a254 Binary files /dev/null and b/contents/posts/os/hs4/img.png differ diff --git a/contents/posts/os/hs4/img_1.png b/contents/posts/os/hs4/img_1.png new file mode 100644 index 0000000..8cdb98b Binary files /dev/null and b/contents/posts/os/hs4/img_1.png differ diff --git a/contents/posts/os/hs4/img_2.png b/contents/posts/os/hs4/img_2.png new file mode 100644 index 0000000..00c615c Binary files /dev/null and b/contents/posts/os/hs4/img_2.png differ diff --git a/contents/posts/os/hs4/img_3.png b/contents/posts/os/hs4/img_3.png new file mode 100644 index 0000000..3bdb369 Binary files /dev/null and b/contents/posts/os/hs4/img_3.png differ diff --git a/contents/posts/os/hs4/index.md b/contents/posts/os/hs4/index.md new file mode 100644 index 0000000..baca002 --- /dev/null +++ b/contents/posts/os/hs4/index.md @@ -0,0 +1,85 @@ +--- +title: "4. 쓰레드 " +description: +date: 2025-09-08 +update: 2025-09-08 +tags: + - 운영체제 +series: "운영체제" +--- + +## 쓰레드란? + +쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다. + +![](img.png) + +그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다. +이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다. + +> #### 사용자 수준 쓰레드와 커널 수준 쓰레드의 차이 +> 사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다. +> 쓰레드와 관련된 모든 행위를 사용자 영역에서 하기 때문에, +> 커널은 사용자 수준 쓰레드의 존재를 알지 못하고 쓰레드 교환에 개입하지 않습니다. +> 커널 수준 쓰레드란, 커널이 직접 생성하고 관리하는 쓰레드를 의미합니다. + +## 쓰레드의 메모리 공간 + +같은 프로세스의 쓰레드는 프로세스로부터 각각의 스택을 나눠갖지만 Code, Data, Heap 메모리 영역을 공유합니다. +하지만, 쓰레드 ID, 스택, PC나 레지스터 같은 쓰레드 컨텍스트에 대해서는 각기 다른 값을 가지고 있습니다. + +![](img_1.png) + +이렇게 각자의 PC, 레지스터, 스택을 가지고 있기에 쓰레드마다 독립적으로 실행할 수 있습니다. + +여기서 중요한 점은 프로세스의 쓰레드들은 실행에 필요한 최소한의 정보(PC, 레지스터, 스택)만을 유지한 채 +프로세스 자원을 공유하며 실행된다는 점입니다. + +## TCB(쓰레드 제어블록) + +쓰레드 또한 프로세스의 PCB(프로세스 제어 블록)처럼 TCB(쓰레드 제어 블록)을 통해 관리됩니다. +TCB는 각 쓰레드에 위치하고, 커널은 TCB를 통해 쓰레드를 관리합니다. + +그럼 TCB에는 어떤 정보가 담겨있을까요? +TCB에는 아래와 같은 쓰레드의 메타데이터들이 담겨져 있습니다. + +![](img_2.png) + +- 쓰레드 번호(TID, Thread ID): 각 쓰레드의 고유 식별 번호입니다. +- 스택 포인터 (Stack Pointer): 쓰레드가 존재하는 프로세스의 PCB에 대한 포인터 +- 프로그램 카운터(PC, Program Counter): 이 쓰레드에서 실행될 다음 명령어의 주소를 가리키는 포인터(주소)입니다. +- 쓰레드 상태(Thread State): 쓰레드가 현재 어떤 상태인지를 나타내는 정보(new, ready, running, waiting, end)입니다. +- 레지스터 상태(Register State): 쓰레드의 레지스터 값 세트입니다. + +각 프로세스에 대한 중요 정보를 강조하는 특정 정보가 쓰레드 제어 블록에 저장됩니다. + +## 프로세스와 쓰레드의 차이 + +프로세스는 각각 독립된 메모리 영역(Code, Data, Heap, Stack)을 할당받고 고유 프로세스 ID를 가지는 특성으로 인해, +프로세스끼리는 서로의 영역에 접근할 수 없습니다. +그래서 한 프로세스가 다른 프로세스의 자원에 접근하려면 IPC(inter-process communication)을 사용해야 합니다. + +하지만, 쓰레드는 IPC와 같은 별도의 통신 방법 없이도 앞서 언급한 것처럼 프로세스의 Code, Data, Heap 메모리 영역을 공유합니다. + +이처럼 프로세스들 사이의 통신에 대한 어려움 해소 및 빠른 컨텍스트 스위칭으로 인해 쓰레드가 프로세스보다 더 가벼운 실행 단위로 사용됩니다. +이로 인해 현대에 와서 운영체제의 실행단위는 프로세스에서 쓰레드로 바뀌어 가고 있습니다. + +## 동시성 환경에서의 차이 + +동시성 환경에서는 어떤지 알아볼까요? +여러 프로세스를 동시에 실행하는 멀티 프로세스와 한 프로세스에서 여러 쓰레드를 동시에 실행하는 멀티 쓰레드가 있습니다. + + +![](img_3.png) + +여기서 가장 큰 차이점은 프로세스끼리는 기본적으로 공유하지 않지만, 쓰레드끼리는 같은 프로세스 내의 자원을 공유한다는 점입니다. + +즉, 멀티 프로세스는 여러 프로세스를 동시에 실행해 각각의 독립적인 프로세스 간 자원을 공유하지 않기 때문에 프로세스 간 통신 (IPC) 방식을 써야 합니다. +또한, 메모리에 동일한 내용들이 중복해서 존재하기 때문에 메모리에도 부담이 될 수 있습니다. +그러나 한편으로는 자원을 공유하지 않는 덕분에 하나의 프로세스에 문제가 생겨도 다른 프로세스들에는 문제가 발생하지 않는다는 장점이 있기도 합니다. + +반면, 멀티 쓰레드는 실행에 필요한 최소한의 정보(PC, 레지스터, 스택)만을 유지한 채 프로세스 자원을 공유하며 실행되기에 +커널의 개입 없이 쓰레드간 통신을 할 수 있고, 메모리에도 부담이 덜합니다. +또한 fork로 인한 생성이 공유하는 부분을 제외한 부분만 복사하면 되기 때문에 프로세스보다 빠릅니다.(쓰레드가 접근하는 공유 데이터에 대해 동기화 작업을 수행해야 합니다) +
+하지만, 하나의 쓰레드에 문제가 생기면 같은 프로세스 내의 다른 쓰레드들에도 문제가 발생할 수 있다는 단점이 있습니다. diff --git a/contents/posts/os/hs5/index.md b/contents/posts/os/hs5/index.md new file mode 100644 index 0000000..c8206bb --- /dev/null +++ b/contents/posts/os/hs5/index.md @@ -0,0 +1,134 @@ +--- +title: "5. CPU 스케줄링" +description: +date: 2025-09-12 +update: 2025-09-12 +tags: + - 운영체제 +series: "운영체제" +--- + +## 기아 상태와 CPU 스케줄링 + +프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다. +그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나, +너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고 +이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다. +이를 컴퓨팅에서는 기아 현상이라고 하는데, +이로 인해 프로세스들에게 CPU 자원 할당을 배분해주는 CPU 스케줄링이 개발되었고, +운영체제에 반드시 필요로 하게 되었습니다. + +> 기아 현상에 대한 대표적인 해결 방법은 에이징 기법을 이용하는 것입니다. +> 오랫동안 대기한 프로세스의 우선순위에 대해 가중치를 주어, +> 처음에 우선순위가 낮아도 언젠가는 우선순위가 높아져 기아 현상을 막을 수 있습니다. +> 이와 같이 CPU 스케줄링에서는 이러한 문제 해결을 위한 다양한 방식들이 있습니다. + +## 프로세스 우선 순위 + +스케줄링을 지정하는 것은 순서를 지정하는 것과 같습니다. +그런데 어떻게 프로세스들 간의 순위를 공정하게 지원하고 있을까요? + +### 순차방식 + +가장 단순하게 생각해보면 요청이 들어온 순서대로 할당하는 방식입니다. +그러나 이 방식은 빨리 처리해야 하는 프로세스가 있을 수 있는 상황에서 대응하지 못한다는 것입니다. + +예시로 CPU를 많이 사용하는 프로세스가 I/O 작업을 하는 프로세스 보다 늦게 들어올 경우, +순서상으로는 뒤에 있어야 하지만, CPU 자원을 할당한다는 측면에서 볼 떄에는 앞 순위로 두는 것이 효울적일 것입니다. + +### 우선순위 지정 방식 + +위 순차적인 방식이 아닌, 별도의 우선순위를 지정하는 방식도 있습니다. +이때, 우선순위에 대한 정보는 PCB에 저장이 됩니다. + +이로 인해 프로세스의 중요도에 맞게 프로세스가 CPU를 이용할 수 있도록 운영체제가 부여하는 것이 우선순위이며, +운영체제는 PCB를 기반으로 어떤 프로세스가 CPU를 얼마나 사용하게 될 것인지 등을 결정합니다. + +프로세스 우선순위는 간단한 명령어나 프로그램 등으로 확인이 가능한데, +일부 우선순위의 경우에는 사용자가 직접 설정 가능한 것도 있습니다. + +### 스케줄링 큐 + +프로세스가 여러 개일 경우, 다음 CPU 자원을 이용할 프로세스를 선택하기 위해 매번 모든 프로세스들의 PCB를 다 뒤져보는 것은 매우 비효율적일 것입니다. +또한, CPU 말고도, 메모리, 입출력 장치를 사용하고자 하는 경우에도 비슷한 상황을 겪을 것입니다. + +때문에 운영체제는 어떤 자원을 이용하고자 할 때 대기 하는 스케줄링 큐를 활용하고 있습니다. + +이때, 큐라고 해서 반드시 선입선출(FIFO)에 국한되지 않습니다. + +## 선점형 스케줄링과 비선점형 스케줄링 + +스케줄링 방식에는 선점형 스케줄링과 비선점형 스케줄링 방식이 있습니다. + +### 선점형 스케줄링 + +선점형 스케줄링은 현재 CPU를 사용 중인 프로세스로부터 CPU 자원을 뺴앗아 요청한 프로세스에 할당하는 방법입니다. +어느 한 프로세스의 자원 독점을 막고 프로세스에 골고루 자원을 배분할 수 있으나, 그 만큼 컨텍스트 스위칭 과정에서 오버헤드가 발생할 수 있습니다. + +### 비선점형 스케줄링 + +비선점형 스케줄링은 현재 CPU를 사용 중인 프로세스의 작업이 끝날 때까지 기다리는 방식입니다. + +선점형 스케줄링과 반대되는 개념으로, 컨텍스트 스위칭에서 발생하는 오버헤드가 적지만, 한편으로는 모든 프로세스가 골고루 자원을 이용하기 어렵습니다. + +## CPU 스케줄링 알고리즘 + +선점형 스케줄링과 비선점형 스케줄링을 기반으로 다양한 CPU 스케줄링 알고리즘이 있습니다. + +### 선입 선처리 스케줄링 + +FCFS(First Come First Served) 스케줄링으로, 준비 큐에 삽입된 순서대로 처리하는 비선점 스케줄링 방식입니다. +CPU를 먼저 요청한 프로세스부터 CPU를 할당합니다. +이로 인해 프로세스들이 기다리는 시간이 매우 길어질 수 있는 부작용이 있으며, +이를 convoy effect, 호위 효과라고 합니다. + +### 최단 작업 우선 스케줄링 + +SJF(Shortest Job First) 스케줄링으로, +사용 시간이 긴 프로세스를 나중에 실행하고, +시간이 짧은 프로세스를 먼저 실행함으로써 평균 대기 시간을 줄일 수 있습니다. +이 알고리즘은 기본적으로는 비선점형 스케줄링 방식에 속하지만, +선점형과 비선점형 스케줄링 방식으로 모두 가능합니다. + +### 라운드 로빈 스케줄링 + +RR(Round Robin) 스케줄링으로, +선입 선처리 스케줄링과 시분할 시스템의 타임 슬라이스(time slice) 개념이 결합된 방식입니디. +정해진 타임 슬라이스만큼의 시간 동안 돌아가며 CPU를 이용하게 하는 선점형 스케줄링입니다. + +### 최소 잔여 시간 우선 스케줄링 + +SRT(Shortest Remaining Time) 스케줄링으로, +최단 작업 우선 스케줄링과 라운드 로빈 스케줄링이 결합된 형태입니다. +정해진 시간만큼 CPU를 이용하되, +다음으로 CPU를 사용할 프로세스로는 남은 작업 시간이 가장 적은 프로세스를 선택합니다. + +### 우선순위 스케줄링 + +프로세스들에 우선순위를 부여하고, 우선순위가 높은 프로세스부터 실행하는 방식입니다. +우선순위가 같은 프로세스들은 선입 선처리 스케줄링으로 돌아가고, +최단 작업 우선 스케줄링이나 최소 잔여 시간 스케줄링은 포괄적인 의미에서 우선순위 스케줄링에 속한다고 할 수 있습니다. + +### 다단계 큐 스케줄링 + +멀티 레벨 큐 스케줄링으로도 불리는데, 우선순위 스케줄링의 발전된 형태입니다. +우선순위 별로 준비 큐를 여러 개 사용하고, 우선순위가 높은 큐에 있는 프로세스를 먼저 실행합니다. +우선순위가 높은 큐가 비어 있다면, 그 다음 우선순위 큐에 있는 프로세스를 처리합니다. +이러한 방식은 프로세스 유형별로 우선순위를 구별하게 하여 관리가 쉬워집니다. +큐 별로 타임 슬라이스를 여러 개 지정할 수도 있고, 큐마다 다른 스케줄링 알고리즘을 사용할 수도 있습니다. +기본적으로 큐 간 이동이 불가능하기 때문에, 우선순위가 낮은 프로세스는 계속해서 우선순위가 낮을 수 밖에 없고, +그로 인해 기아 현상을 겪을 수도 있습니다. + +### 다단계 피드백 큐 스케줄링 + +멀티 레벨 피드백 큐 스케줄링으로도 불리는 이 방식은 다단계 큐 스케줄링의 발전된 형태로, +큐 간 이동이 가능합니다. +새로 준비 상태로 된 프로세스가 있으면 가장 우선순위가 높은 큐에 삽입합니다. +일정 시간 즉, 타임 슬라이스 만큼 CPU를 사용할 수 있는데, +만약 작업이 끝나지 않았다면, +그때 우선순위가 다음으로 높은 곳에 삽입을 합니다. +작업을 많이 있는 프로세스일수록 우선순위가 점점 낮아지게 되고, +따라서 CPU 집중 프로세스는 상대적으로 우선순위가 낮아지고, 입출력 집중 프로세스는 높아지게 될 겁니다. +일정 시간 이상 낮은 우선순위에서 기다리고 있던 프로세스가 있었다면 이 프로세스의 우선순위를 점차 높임으로써 기아 현상을 방지할 수 있습니다. +다단계 피드백 큐 스케줄링은 CPU 사용 시간이 길면 우선순위가 점점 낮아지고, 동시에 어떤 프로세스가 낮은 우선순위 큐에서 너무 오래 기다리면 우선순위를 높일 수도 있습니다. +다단계 피드백 큐 스케줄링은 복잡하지만, CPU 스케줄링의 가장 일반적인 형태로 알려져 있습니다. diff --git a/public/1/index.html b/public/1/index.html deleted file mode 100644 index e2649ff..0000000 --- a/public/1/index.html +++ /dev/null @@ -1,348 +0,0 @@ -1. 운영체제의 역할과 커널의 기능

1. 운영체제의 역할과 커널의 기능

@jc, 023· September 04, 2025 · 5 min read

운영체제란 무엇일까?

-
-

운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원관리하고, -
프로세스를 관리하는 등 여러가지 일을 수행합니다.

-

이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다.

-

운영체제의 역할

-
-

하드웨어 관리

-
-

운영체제는 CPU, 메모리, 입출력 장치 등 컴퓨터 하드웨어 자원을 관리합니다. -
여기서 말하는 관리란 자원의 충돌을 방지하고 사용자가 하드웨어를 효율적으로 -사용하도록 처리하는것을 의미하게 됩니다.

-
-
-
-

프로세스 관리

-
-

프로세스의 생성과 종료 그리고 CPU 스케줄링을 통해 프로세스의 실행 시간을 관리합니다. -
멀티 태스킹환경에서 프로세스 전환을 관리합니다.

-
-
-
-

메모리 관리

-
-

각 애플리케이션에 충분한 메모리 공간을 할당하는 기능을 합니다. -
또한 가상 메모리를 통해 실제 메모리보다 큰 주소 공간을 제공합니다.

-
-

커널이란 무엇일까?

-
-

커널이란 운영체제의 핵심 기능을 담당하며, 커널은 하드웨어와 소프트웨어 애플리케이션 간 통신을 관리합니다. 커널의 대표적인 기능으로는 -
프로세스 관리, 메모리 관리, 파일 시스템, 입 출력 관리의 역할을 수행하게 됩니다.

-

위 설명 처럼 운영체제의 핵심기능을 커널이 많은 부분을 담당하기 때문에 이전에 설명한 운영체제의 기능이 커널의 기능이라고 생각하면 됩니다.

-

커널이 자원을 관리하는 이유

-
-
-

커널은 어떻게 충돌 없이 자원을 관리할까요?

-
-

이 질문에 대한 대답은 자원을 관리하는 지점을 커널을 통한 단일 진입점으로 만들게 되면서 해결 하게 됩니다. -

-
-

왜 자원을 커널을 통해서만 관리하게 설게 했을까요?

-
-

커널이 자원을 혼자 관리해야 하는 이유를 예시를 들어서 설명하겠습니다.

-

유치원 수업시간에 하나의 바구니에 테이프, 연필, 지우개와 같은 문구용품을 담아두고 선생님이 학생들에게 자율적으로 사용해도 된다고 하게 된다면 어떤일이 벌어질까요?

-

처음에는 아이들이 각자 필요한 문구 용품을 사용하겠지만 얼마 가지 않아서 연필을 찾는 학생, -
테이프를 가지고 누가먼저 쓸지 싸우는 학생, -
혹은 지우개를 망가뜨린 학생등 많은 사고가 있을 것입니다.

-

이러한 문제가 벌어지는 이유는 공용 문구를 사용할때 통제권이 모두에게 있기 떄문입니다. 그렇다면 이를 해결하기 위해서 -모두에게 있는 통제권을 하나로 합쳐서 해결하면 되는 문제이고 이것이 자원을 사용하기 위해 커널의 관리를 받아야 하는 이유입니다.

@jc, 023
CATCH NPE tech blog
- - \ No newline at end of file diff --git a/public/10/index.html b/public/10/index.html deleted file mode 100644 index cd83bf8..0000000 --- a/public/10/index.html +++ /dev/null @@ -1,398 +0,0 @@ -10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점

10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점

@jc, 023· September 13, 2025 · 8 min read

img.png

-

멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술이다. -보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해 -여러개의 프로세스를 생성하는 것이다.

-
-
-

어떻게 멀티 프로세스를 생성할까?

-

멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부모 프로세스가 -여러개의 자식 프로세스를 생성한다.

-

부모 프로세스는 자식 프로세스의 PID를 알고있으며 자식또한 PID와 PPID를 알고있어 -서로 통신이 가능하다.

-

이런 성질은 각각 독립적이지만 통신이 가능하게 만들었고 멀티 프로세스의 대표적인 예가 -브라우저의 탭이라고 할 수 있다.

-

브라우저 탭은 문제가 발생해서 닫아야 하는 상황이여도 다른 탭까지 닫히지 않고 개별적으로 -운용을 할 수 있는걸 기억해보면 독립적이란 말을 더 잘 이해할 수 있을것이다.

-
-
-

멀티 프로세스의 장점

-
-
    -
  1. 안정성
  2. -
-

멀티 프로세스의 안정성은 각각의 프로세스가 독립적이기 떄문에 가능하다. -대표적인 예로 좀전에 설명을 했던 특정 브라우저 탭이 문제가 발생하여 닫아야 하는 상황에서 -같은 브라우저의 다른 탭까지 닫히지는 않는다. -이런것이 독립적인 성격에 의한 안정성이라고 할 수 있다.

-
-
-

멀티 프로세스의 단점

-
-
    -
  1. 문맥교환 (Context Switching) Overhead
  2. -
-

멀티 태스킹을 이루는 기술인 문맥 교환 과정에서 성능 저하가 발생할 수 있다. -프로세스를 컨텍스트 스위칭 하면, CPU는 다음 프로세스의 정보를 불러오기 위해 -메모리를 검색하고, CPU 캐시 메모리를 초기화하며, 프로세스 상태를 저장하고, -불러올 데이터를 준비해야 하기 떄문에, 빈번한 문맥교환이 발생하고 이 비용은 곧 오버헤드로 발생할 수 있다.

-
-
-
    -
  1. 자원 공유 비효율성
  2. -
-

프로세스는 독립적인 메모리를 가지고, 멀티 프로세스는 독립적인 메모리 공간의 합일 것이다. -그렇기 때문에 메모리 비효율성을 초래한다.

-
-
-

멀티 스레드

-
-

img.png

-
-

이전에 보았던 것처럼 스레드는 하나의 프로세스 내에 있는 실행 흐름이다. -멀티 스레드는 하나의 프로세스 안에 여러개의 실행흐름을 가지는 것이다. -멀티 스레드 또한 멀티 프로세스 처럼 여러개의 작업을 동시 실행 할 수 있다.

-

이전에 보았던 것처럼 멀티 프로세스는 브라우저의 여러개의 탭을 통해 예시를 들었다. -하지만, 멀티 스레드는 같은 브라우저라 할지라도 동일탭에 여러 실행 흐름을 말하게 되고 -예를들어 네트워크 처리 스레드, 검색 스레드 와 같이 동일한 프로세스 내 기능들을 말하게 된다.

-
-
-

멀티 스레드의 장점

-
-

프로세스보다 스레드가 가벼움

-

스레드는 프로세스보다 용량이 가볍다. 이유는 데이터, 코드, 힙 영역을 -프로세스와 공유해서 사용하기 때문에 내장된 정보다 프로세스보다 작기 떄문이다. -그렇기 때문에 스레드를 제거하는 작업이 프로세스를 제거하는 작업보다 가볍다.

-
-
-

자원의 효율성

-

멀티 스레드는 하나의 프로세스 내에서 스택영역을 제외한 영역을 공유하기 때문에 -프로세스 간 통신을 사용하지 않고도 자원의 공유가 가능하여 자원을 효율적으로 사용할 수 있다.

-
-
-

Context Switching 비용 감소

-

스레드 문맥 교환 또한 오버헤드가 존재하지만, 프로세스 문맥교환과 비교했을 때, -상대적으로 오버헤드가 적다.

-

이유는 프로세스 컨텍스트 스위칭 비용은 스위칭할 때마다 CPU 캐시에 있는 내용을 모두 초기화하고, -새로운 프로세스 정보를 CPU 캐시에 적재해야 하기 떄문이다. -하지만, 스레드 문맥교환은 스레드 개별적인 정보만 교체하면 되기 떄문에 비용이 상대적으로 낮다.

-
-
-

멀티 스레드의 단점

-

멀티 프로세스는 개별적인 작업으로 인해 독집적이고, 각자의 문제를 전파하지 않는다고 하였다.

-

하지만, 멀티 스레드는 하나의 스레드가 문제가 발생하면 다른 스레드들고 영향을 받아 전체가 종료가 될 수 있다.

-
-
-

데드락

-

데드락이란 하나의 자원을 사용하기위해 여러 곳에서 접근했고, 그상황에서 교착상태가 일어났을때 -여러대의 스레드가 서로 대기하면서 무한정 기다리는 현상을 데드락이라고 한다.

-

예를들어, 스레드 1 은 자원 A을 점유하고 있는 상태에서 자원 B가 필요한 상황이다. -그리고 스레드 2 는 자원 B를 점유하고 있는 상태에서 자원 A이 필요한 상황이다. -하지만 스레드 1은 자원 B가 필요한 상황에서 자원 A을 빌려줄 수 있는 상황이 아니고, -스레드 2또한 자원 A이 필요한 상태에서 자원 B를 빌려줄 수 없는 상황인 것이다. -이처럼 다수의 쓰레드가 같은 lock을 동시에, -다른 명령에 의해 획득하려 할 때 서로 절대 불가능한 일을 계속적으로 기다리는 상황을 이야기 한다.

@jc, 023
CATCH NPE tech blog
- - \ No newline at end of file diff --git a/public/11/index.html b/public/11/index.html deleted file mode 100644 index dfe7f40..0000000 --- a/public/11/index.html +++ /dev/null @@ -1,369 +0,0 @@ -11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법

11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법

@jc, 023· September 14, 2025 · 4 min read

동시성 이슈란?

-
-
-

img.png

-
-

동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다.

-

예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다. -스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때 -스레드 a가 좋아요 카운트를 늘리면 11가 됩니다. 하지만 스레드 a와 b는 좋아요 카운트에 동시에 접근해서 초기값 10을 받은 상태라면 -스레드 b는 늘어난 11라는 숫자대신 10을 기준으로 값을 줄이게 됩니다. 그럼 최종 결과는 10이 아닌 9라는 값으로 나오게 됩니다.

-

이처럼 멀티 스레드 환경에서는 하나의 자원에 동시에 접근하게 되면 이러한 문제가 발생할 수 있다.

-
-
-

스레드 안전

-
-

그럼 우리가 추구해야 할 문제는 스레드 안전한 멀티 스레드 프로그래밍을 구현할 수 있어야 한다. 이것을 구현하는 -방법에 대해 이야기 하려고 한다.

-
-
-

스레드 안전 여부 판단

-
-
    -
  1. 전역 변수나 힙, 파일과 같이 여러 스레드가 동시 접근 가능한 자원을 사용하는가
  2. -
  3. 핸들과 포인터를 통한 데이터의 간접 접근이 가능한가?
  4. -
  5. 부수 효과를 가져오는 코드가 있는가?
  6. -
-
-
-

스레드 안전을 지키기 위한 4가지 방법

-
-
    -
  1. 상호 배제(Mutual Exclusion)
  2. -
-
-
    -
  • 공유 자원에 하나의 Thread만 접근할 수 있도록 세마포어/ 뮤텍스락을 통제하는 방법이다.
  • -
-
-
    -
  1. 원자 연산(Atomic Operation)
  2. -
-
-
    -
  • 공유 자원에 접근할 때 원자 연산을 이용하거나 원자적으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현하는 방법이다.
  • -
  • Atomic -
      -
    • 공유 자원 변경에 필요한 연산을 원자적으로 분리한 뒤에 실제로 데이터의 변경이 이루어지는 시점에 Lock을 걸고,
    • -
    -데이터를 변경하는 시간 동안 다른 쓰레드의 접근이 불가능하도록 하는 방법이다.
  • -
-
-
    -
  1. Thread-Local Storage (스레드 지역 저장소)
  2. -
-
-
    -
  • 공유 자원의 사용을 최대한 줄이고 각가의 쓰레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는 방법이다.
  • -
  • 일반적으로 공유 상태를 피할 수 없을 때 사용하는 방식이며, 전역 변수 사용을 자제하라는 뜻으로 생각하면 된다.
  • -
-
-
    -
  1. Re-entrancy (재진입성)
  2. -
-
-
    -
  • 쓰레드 호출과 상관 없이 프로그램에 문제가 없도록 작성하는 방법이다.
  • -
  • 어떤 함수가 한 스레드에 의해 호출되어 실행 중이라면 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 옳바르게 주어져야 한다.
  • -
  • 쓰레드끼리 독립적으로 동작할 수 있도록 코드를 작성하는 것으로 생각하면 된다.
  • -
-
-
@jc, 023
CATCH NPE tech blog
- - \ No newline at end of file diff --git a/public/1a48c3c1-c2fd3dc9064c347aaab6.js b/public/1a48c3c1-c2fd3dc9064c347aaab6.js old mode 100644 new mode 100755 diff --git a/public/1a48c3c1-c2fd3dc9064c347aaab6.js.map b/public/1a48c3c1-c2fd3dc9064c347aaab6.js.map old mode 100644 new mode 100755 diff --git a/public/1bfc9850-6e903d2bfdffa51fa660.js b/public/1bfc9850-6e903d2bfdffa51fa660.js old mode 100644 new mode 100755 diff --git a/public/1bfc9850-6e903d2bfdffa51fa660.js.map b/public/1bfc9850-6e903d2bfdffa51fa660.js.map old mode 100644 new mode 100755 diff --git a/public/2/index.html b/public/2/index.html deleted file mode 100644 index 937df18..0000000 --- a/public/2/index.html +++ /dev/null @@ -1,334 +0,0 @@ -2. CPU 스케줄링, 시스템 자원 관리

2. CPU 스케줄링, 시스템 자원 관리

@jc, 023· September 05, 2025 · 2 min read

CPU 스케줄링

-
-

CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며, -
모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다.

-

CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다. -

-

CPU 스케줄링 원칙

-
-

CPU는 스케줄링을 하면서 두가지 원칙을 중요시 하게 됩니다. -

-
    -
  1. 공정함: 특정 프로세스 실행이 무한정 대기하지 않도록 기간을 보장합니다.
  2. -
  3. 우선순위: 우선순위가 높은 작업에 우선권을 제공 합니다.
  4. -
-
-

CPU 스케줄링 평가 기준

-
-

CPU는 객관적인 스케줄링을 위해 아래와 같은 평가 기준을 사용합니다.

-
-
    -
  1. CPU 사용률 - CPU가 작업을 수행하는데 사용하는 시간의 비율
  2. -
  3. 처리량 - 시스템이 단위 시간당 완료할 수 있는 작업의 양
  4. -
  5. 응답 시간 - 시스템이 사용자의 요청에 반응하여 첫 번째 응답을 생성하기 시작하는데 걸리는 시간
  6. -
  7. 대기 시간 - 프로세스가 실행되기 위해 CPU를 할당받아 준비 상태에서 대기하는 시간의 총합
  8. -
  9. 처리 시간 - 특정 작업이 시작되었을 때부터 그 작업이 완전히 끝나는데 걸리는 시간의 총합
  10. -
@jc, 023
CATCH NPE tech blog
- - \ No newline at end of file diff --git a/public/2225c71e739ae8cdf958f1f099a38c1b2a6a6adc-50bc4bd76b411b925587.js b/public/2225c71e739ae8cdf958f1f099a38c1b2a6a6adc-50bc4bd76b411b925587.js old mode 100644 new mode 100755 diff --git a/public/2225c71e739ae8cdf958f1f099a38c1b2a6a6adc-50bc4bd76b411b925587.js.map b/public/2225c71e739ae8cdf958f1f099a38c1b2a6a6adc-50bc4bd76b411b925587.js.map old mode 100644 new mode 100755 diff --git a/public/3/index.html b/public/3/index.html deleted file mode 100644 index 650231f..0000000 --- a/public/3/index.html +++ /dev/null @@ -1,352 +0,0 @@ -3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리

3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리

@jc, 023· September 06, 2025 · 4 min read

이중모드

-
-

운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다.

-
-

그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요?

-
-

이에 대한 답은 이중 모드 입니다.

-
-

img.png

-
-

위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드커널 모드로 나누어 사용하게 됩니다.

-
-

사용자 모드

-

사용자 모드는 운영체제 서비스를 제공받을 수 없는 실행 모드입니다. -
CPU가 해당 모드인 경우, 입출력 명령어와 같은 하드웨어 자원 접근 명령을 실행할 수 없습니다. 일반 프로그램은 기본적으로 사용자 모드로 실행됩니다.

-
-

커널 모드

-

커널모드는 운영체제 서비스를 제공받을 수 있는 실행 모드로 커널 영역의 코드를 실행할 수 있습니다. -
CPU가 커널 모드로 명령어를 실행하면 자원에 접근하는 명령어를 비롯한 모든 명령어를 실행할 수 있으며, 운영체제는 커널 모드로 실행됩니다.

-
-

요약 하자면 일반 응용프로그램은 평소에 사용자 모드를 통해서 실행 되다가 실제 운영체제의 코드를 실행하여야 하는 순간이 오면 커널 모드로 전환하여 실행하다가 -운영체제의 코드 실행 지점이 끝난다면 다시 사용자 모드로 전환되게 됩니다.

-

이러한 방식으로 자원을 운영 체제로 하여금 독자적으로 관리할 수 있게 합니다.

-
-
-

사용자 모드에서 어떻게 커널모드로 전환할까?

-
-

사용자 모드에서 커널모드로 전환하는 방식은 시스템 콜에 의해서 발생합니다.

-
-

img.png

-
-

그림처럼 사용자 모드로 실행되는 프로그램이 자원에 접근해야 할때 운영체제에 커널 모드로 요청을 보내게 되고 이것을 시스템 콜이라고 부르게 됩니다.

-

시스템 호출소프트 웨어 인터럽트에 속합니다. 이러한 특징 때문에 CPU시스템 호출을 처리하는 순서가 인터럽트 처리 순서와 비슷합니다.

-

시스템 호출이 발생하면 지금까지의 작업을 백업 하고, 커널 영역 내의 호출 하여야 하는 코드를 실행 한 뒤 다시 돌아와 기존 프로그램을 계속 실행합니다.

-
-

img.png

-
-

그림을 통해서 이해를 하게 되면,

-
    -
  1. 응용 프로그램은 일반적인 작업을 수행중 운영체제 코드를 실행 하여야 하는 작업에 도달하게 됩니다.
  2. -
  3. 그러면 응용프로그램은 운영체제에게 자원 접근에 대한 시스템 콜을 날리게 된다.
  4. -
  5. 현재 작업을 백업하게 됩니다.
  6. -
  7. 이후 응용프로그램은 운영체제의 코드를 실행합니다.
  8. -
  9. 작업이 끝나면 다시 사용자 영역으로 돌아와 멈춰둔 작업을 진행합니다.
  10. -
-

이런 세부적인 순서를 진행하게 됩니다.

-

출처

-

사진출처

@jc, 023
CATCH NPE tech blog
- - \ No newline at end of file diff --git a/public/4/index.html b/public/4/index.html deleted file mode 100644 index 491ad76..0000000 --- a/public/4/index.html +++ /dev/null @@ -1,343 +0,0 @@ -4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념

4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념

@jc, 023· September 07, 2025 · 4 min read

단일 프로세스

-
-

초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다. -이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나, -끝날때 까지 기다려야 합니다.

-
-

img.png

-
-CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 IO작업동안 CPU는 멈추게 -될것이고 그 상황에서 CPU가 놀고 있게 되는 시간이 늘어나는 것입니다. -
-

멀티 프로그래밍

-

img.png

-

이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다. -이를 멀티 프로그래밍이라고 부르며 그림처럼 CPU 사용률을 높이기 위한 목적이었습니다.

-

하지만 이러한 방식의 문제는 앞선 프로세스가 길어질 수록 즉 IO사용처럼 비는 시간없이 순수하게 많은 시간을 -쓰게 된다면 이후 프로세스가 계속 기다려야 하는 문제가 있었습니다.

-
-

멀티 태스킹

-

img.png

-

멀티 프로그래밍 방식에서 더 나아가 모든 프로세스가 공정하게 특정 짧은 시간만 실행되게 반복한다면 길게 시행되는 -프로세스 뒤에 오는 프로세스가 기다리는 문제가 없을 것이다. 이것이 멀티태스킹을 사용하는 이유입니다.

-

프로세스1에서 프로세스2로 작업을 스위칭 하는것을 문맥 교환(Context Switching)이라고 -부르게 되는데 이러한 문맥교환은 값싼 작업이 아니고 이러한 작업이 자주 일어나게 된다면 비효율 적인 단점이 부각되다 보니 -새로운 방식을 사용하게 됩니다.

-
-

멀티 프로세싱

-

멀티 프로세싱이란 이전 멀티 태스킹과 이름은 비슷 하지만 완전히 다른 방식입니다.

-

이전 방식은 하나의 CPU를 어떻게 쪼개서 사용할까라는 목적이였다면, 멀티 프로세싱CPU 작업단위인 -코어 자체를 늘려서 여러 CPU코어가 동시에 작업하는것을 멀티 프로세싱이라고 부르게 됩니다.

-

img.png

-

멀티 프로세싱은 CPU코어 수를 늘리는 방법이기 때문에, 이를 어떻게 처리할까에 대한 내용은 멀티 프로세싱 자체의 내용이 아니고 앞서 나왔던 방법론을 도입할 수 있습니다. -그림처럼 하나의 프로세스를 여러 코어가 담당하는 방법이나, 여러 프로세스를 여러 코어가 담당 할 수 도 있습니다.

-

출처

-

사진출처

@jc, 023
CATCH NPE tech blog
- - \ No newline at end of file diff --git a/public/404.html b/public/404.html old mode 100644 new mode 100755 index bb609b2..9320b2e --- a/public/404.html +++ b/public/404.html @@ -1,4 +1,4 @@ -CATCH NPECATCH NPE5. 인터럽트와 DMA를 통한 효율적 입출력 처리

5. 인터럽트와 DMA를 통한 효율적 입출력 처리

@jc, 023· September 08, 2025 · 4 min read

인터럽트 기반 입출력

-
-

인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한 -방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다.

-

인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트를 발생시킨 -주체가 무엇인가에 따라 나뉘게 된다.

-

대표적인 하드웨어 인터럽트는 I/O완료, 대표적인 소프트웨어 인터럽트는 시스템 콜이 있다.

-
-
-

- - - - img.png - - -
img.png
-

-

이러한 인터럽트 기반 입출력의 순서를 설명하자면

-
    -
  1. CPU가 입출력 장치에 대해 입출력 요청을 보낸다.
  2. -
  3. CPU는 요청이후 다른 작업을 수행한다.
  4. -
  5. 입출력 장치가 준비되면 인터럽트를 발생시킨다.
  6. -
  7. CPU는 현재 실행 중인 작업을 중단하고 인터럽트 서비스 루틴(ISR)을 실행한다.
  8. -
  9. 데이터를 처리한 후 , CPU는 원래 수행하던 작업을 계속 실행한다.
  10. -
-

이러한 인터럽트 기반 입출력의 단점은 인터럽트가 많이 발생하는 상황에서 CPU가 부하될 수 있다는 단점이 있다.

-
-
-

DMA(Direct Memory Access 직접 메모리 접근)

-
-

DMA방식은 이름에서 볼 수 있듯이 CPU를 사용하지 않고 입출력 장치가 직접 메로리와 데이터를 교환합니다.

-

이것이 가능한 이유는 DMA 컨트롤러가 존재해, 메모리와 입출력 장치 사이의 데이터를 관리하기 때문입니다.

-

DMA에서는 CPU가 전송할 데이터의 위치, 포인터, 바이트 크기만 DMA 컨트롤러에 전달하면, -DMA가 입출력 작업을 대신 처리하고 전체 작업이 완료될 때만 CPU에 인터럽트를 보냅니다. -이로 인해 CPU와 여러 입출력 장치가 직접 연결되던 기존 구조에서 CPU-DMA-입출력 장치 구조로 변화했고, -CPU의 가용 시간이 현저히 증가하는 효과를 얻었습니다. -이는 교수가 조교에게 학생 관리를 맡기고 최종 결과만 확인하는 것에 비유할 수 있으며, -현재 DMA는 많은 컴퓨터 장치에서 보편적으로 사용되는 기술이 되었습니다.

-
-
-

- - - - img.png - - -
img.png
-

-
-DMA 방식을 순서로 설명하자면 -
    -
  1. CPU가 DMA 컨트롤러에게 입출력 요청합니다.
  2. -
  3. DMA 컨트롤러가 메모리와 입출력 장치 간의 데이터 전송을 직접 수행합니다.
  4. -
  5. 데이터 전송이 완료되면 DMA 컨트롤러가 인터럽트를 발생 시켜 CPU에게 완료를 알립니다.
  6. -
  7. CPU는 인터럽트를 받아서 필요한 후처리 수행합니다.
  8. -
@jc, 023
CATCH NPE tech blog
- - \ No newline at end of file diff --git a/public/6/index.html b/public/6/index.html deleted file mode 100644 index a67ce05..0000000 --- a/public/6/index.html +++ /dev/null @@ -1,356 +0,0 @@ -6. 동기식/비동기식 I/O의 차이와 활용 사례

6. 동기식/비동기식 I/O의 차이와 활용 사례

@jc, 023· September 09, 2025 · 5 min read

IO란

-

개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를 -주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다.

-

예시를 들어서

-
    -
  • 파일 읽기/쓰기 (문서를 열거나 저장하는 행위)
  • -
  • 네트워크 통신(웹사이트 접속, 이메일 전송)
  • -
  • 데이터베이스 조회(회원 정보 검색)
  • -
-

이런 일련의 행위는 공통적인 특징이 있는데, 물리적인 시간이 걸린다는 점입니다. -그렇기 떄문에 IO를 어떻게 다룰까에 대한 방법또한 여러가지 존재합니다.

-
-
-

동기와 비동기란

-

IO를 다루는 방법에는 동기, 비동기에 대한 개념이 등장합니다. -이러한 개념을 사전에 정의 하고 내려가겠습니다.

-

동기 (Synchronous)

-

프로그램에서 말하는 동기란 하나의 작업에 대해서 요청과 응답 과정을 기다리는 행위입니다. -예를들어, WAS가 데이터베이스에 조회 요청을 하고 데이터베이스는 요청받은 데이터를 돌려줄것입니다. -이 과정에서 WAS는 요청직후 부터 응답을 받을때 까지 과정에서 데이터베이스의 응답을 기다리게 됩니다. 이것이 동기입니다.

-
-

동기의 특징

-

순차적 실행: 한 작업이 완료되어야 다음 작업이 시작 -블로킹: 현재 작업이 끝날 때까지 다른 작업은 대기 -예측 가능: 코드가 위에서 아래로 순서대로 실행

-
-
-

비동기 (Asynchronous)

-

그렇다면 비동기는 하나의 작업에 대해서 요청과 응답 과정을 기다리지 않는 행위입니다. -예를들어, WAS가 데이터베이스에 조회 요청을 하게 되면 데이터베이스가 이를 수행하고 응답할것입니다. -이 과정 사이에 시간동안 WAS는 본인의 다른 작업을 수행하다가 데이터베이스의 응답을 받게 됩니다. -즉 요청과 응답 사이 기간동안 WAS는 본인의 일을 하며 무작정 기다리지 않는 것입니다.

-
-

비동기의 특징

-

동시 실행: 여러 작업을 동시에 시작 가능 -논블로킹: 작업 완료를 기다리지 않고 다른 작업 진행 -콜백/Promise: 작업 완료 시 결과를 알려주는 방식

-
-

동기식 I/O

-

img.png

-
-

동기식IO는 IO요청이 발생하였을 때 이전 동기 설명처럼 IO요청이 끝날때 까지 기다리는 방식입니다. -프로그램이 IO작업을 요청하게 되면, 다른 동작을 수행하지 않고 멈춰서 IO작업이 리턴되기 까지 기다립니다. -I/O작업이 완료되면 인터럽트를 통해 완료를 알리게 됩니다. 이후 CPU 제어권이 기존 프로그램에게 넘어가게 됩니다.

-

이러한 방식의 특징은 구현이 쉽다는 특징이 있지만, 연산에 대한 기다림으로 인해 자원 낭비를 하는 특징이 있습니다.

-

비동기식 I/O

-

img.png

-

비동기식IO는 IO요청이 발생하였을 떄 이전 비동기 설명처럼 IO요청을 기다리지 않는 방식입니다. -프로그램이 IO 작업을 요청하고, 그 작업이 완료되기를 기다리지 않고 즉시 다음 작업으로 넘어가는 방식입니다.

-

이러한 방식의 특징은 구현의 복잡성이 높다는 것이지만, 대용량 데이터를 처리하는데 여러 IO작업을 동시에 처리해야 할 떄 유용합니다.

@jc, 023
CATCH NPE tech blog
- - \ No newline at end of file diff --git a/public/7/index.html b/public/7/index.html deleted file mode 100644 index a01f942..0000000 --- a/public/7/index.html +++ /dev/null @@ -1,401 +0,0 @@ -7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기

7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기

@jc, 023· September 10, 2025 · 9 min read

프로세스란 무엇일까?

-
-

우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다.

-

여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다.

-
-
-

![img.png](실행중인 프로세스.png)

-
-위 사진처럼 보이는 것보다 더 많은 프로세스가 작동하고 있는데, 여기서 사용자가 볼 수 있는 프로세스를 포그라운드 프로세스 라며 명하며, -보이지 않는 프로세스를 백그라운드 프로세스라고 부르게 됩니다. -

백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는 다는 뜻은 아닌데 백그라운드 프로세스 중에서 사용자와 상호작용 하지 않고 자신의 일만을 수행하기 위해 존재하는 -프로세스를 데몬(daemon) 프로세스라고 명합니다.

-
-

프로세스 제어 블록(PCB)

-
-

CPU자원이 한정되어 있는 반면에, 모든 프로세스는 실행을 위해 CPU를 사용하여야 합니다. -그렇기 떄문에 프로세스들은 한정된 시간 만 CPU를 사용하며 자신의 차례를 기다립니다.

-

운영체제는 빠르게 번갈아 수행되는 프로세스의 실행 순서를 관리하고, 프로세스에 CPU와 여러가지 자원을 배분합니다. -이를 위해 운영체제는 프로세스 제어 블록(PCB)를 이용합니다.

-
-

PCB는 커널 영역에 생성되고, 수많은 프로세스를 PCB를 통해 태그처럼 사용해 특정 프로세스를 식별하며 해당 프로세스를 처리하는데 필요한 정보를 판단합니다.

-

즉, 가게 주인이 물건을 태그를 통해 판단하고 가격을 알 수 있고, 생산지를 알 수 있는 것처럼 PCB는 운영체제가 수 많은 프로세스를 식별하고 그 프로세스의 정보를 판단하게 돕습니다.

-
-
-

PCB의 구조

-
-
-

- - - - img.png - - -
img.png
-

-

사진 출처

-
-

위 그림처럼 PCB는 프로세스를 식별하기 위해 여러가지 정보를 담고 있습니다. 프로세스의 ID나, -레지스터의 값 혹은 상태같이 많은 정보를 담고있으며 이를 알아보고자 합니다.

-
-

프로세스 ID

-

img.png

-

프로세스 ID(PID)는 프로세스를 식별하기 위해 존재하는 고유 ID입니다. 메모장을 두개 킨다고 할지라도 다른 프로세스ID가 -만들어지는 것처럼 중복된 활동이여도 하나의 프로세스는 고유한 ID를 가지게 됩니다.

-
-

레지스터 값

-

프로세스는 자신의 실행 차례가 돌아오면 이전까지 사용했던 레지스터의 중간값들을 모두 복원합니다. -여기에는 프로그램 카운터가 속하게 됩니다.

-
-

프로세스 상태

-

현재 프로세스가 어떤 상태인 기록합니다. 입출력장치를 사용하기 위해 기다리는지 혹은 CPU를 사용하고 있는 상태인지 와 같은 -상태를 기록하며 자세한 상태는 다음장에서 설명합니다.

-
-

CPU 스케줄링 정보

-

프로세스가 언제, 어떤 순서로 CPU를 할당받을지에 대한 정보도 PCB에 기록됩니다.

-
-

메모리 관리 정보

-

프로세스마다 메모리에 저장된 위치가 다릅니다. 그렇기 떄문에 PCB에는 해당 프로세스가 저장된 메모리 위치를 기록해야 합니다.

-
-
-

프로세스의 메모리 영역

-
-

프로세스가 생성되면 커널 영역에 PCB가 생성됩니다. 그렇다면 커널 영역이 아닌 사용자 영역에는 어떤 데이터가 들어갈까요?

-

img.png

-

사진출처

-

위 그림처럼 하나의 프로세스는 크게 코드영역(Text), 데이터 영역(Bss,Gvar), 힙 영역(Heap), 스택 영역(Stack) 4가지로 나뉩니다.

-

차례대로 설명하자면,

-
-
-

코드영역 or 텍스트영역(Text)

-

이곳에는 실행할 수 있는 기계어로 이루어진 명령어가 저장됩니다. 가공할 수 있는 데이터가 아닌 -CPU가 실행해야 하는 명령어가 담겨있기 때문에 읽기모드만 지원합니다.

-
-

데이터 영역

-

프로그램을 실행하는 동안 유지되어야 하는 데이터가 저장되는 공간입니다. 대표적은 전역 변수가 이곳에 해당합니다.

-
-

코드영역 & 데이터 영역 공통점

-

위 두 영역은 크기가 변하지 않습니다. 프로그램을 구성하는 명령어가 작동중에 코드 양이 늘어나는 경우가 없으니 -이 두가지 영역을 정적 할당 영역이라고 부릅니다.

-
-

힙 영역

-

프로그래머가 직접 할당할 수 있는 공간입니다. 프로그래밍 과정에서 힙 영역에 데이터를 할당했다면 언젠가는 이 영역에 -데이터를 반환해야 합니다. 그렇지 않다면 메모리 용량은 점점 줄어들어 장애가 발생할 수 있습니다.

-

이런 문제를 메모리를 할당받고 해제 하지 않았다고 하여 누수가 발생했다. 즉 메모리 누수라고 부릅니다.

-
-

스택 영역

-

스택 영역은 데이터를 일시적으로 저장하는 공간입니다. -데이터 영역에 담기는 값과는 다르게 잠깐 쓸 데이터를 담아두는 공간입니다. -함수를 실행하는 동안 필요한 지역변수, 매개 변수가 이곳에 해당합니다. -그렇기 떄문에 함수가 종료되면 스택 영역에서 해당 함수에 쓰였던 변수들도 같이 없어지게 됩니다.

-
-
-

힙 영역 & 스택 영역 공통점

-

위 두 영역은 실시간으로 그 크기가 변할 수 있고 그렇기 떄문에 동적 할당 영역이라고 부르게 됩니다.

-

그림을 보면 unused memory영역이 있는데, 스택 영역과 힙 영역이 동적이기 떄문에 힙은 아래에서 위로, 스택은 -위에서 아래로 주소를 할당하게 됩니다. 그렇게 되면 서로 충돌없이 동적으로 값을 할당할 수 있기 때문입니다.

-

여기서 만약에 힙이나 스택에 많은 정보가 담겨서 서로의 지점을 충돌 할 수 있는데, 그럴때 각각 stack overflow, -heap overflow라고 부르게 됩니다.

@jc, 023
CATCH NPE tech blog
- - \ No newline at end of file diff --git a/public/8/index.html b/public/8/index.html deleted file mode 100644 index 9675d41..0000000 --- a/public/8/index.html +++ /dev/null @@ -1,409 +0,0 @@ -8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기

8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기

@jc, 023· September 11, 2025 · 8 min read

문맥교환(Context Switching)

-
-

하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요?

-

프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를 -저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야 -이후 자신의 차례가 왔을 때 이 과정을 이어받아 작업을 수행할 수 있습니다.

-

여기서 하나의 프로세스를 실행하기 위해 필요한 정보들을 문맥(Context)라고 부르게 됩니다. -이러한 문맥값들은 PCB속에 저장됩니다.환

-
-

img.png -사진출처

-

결국 프로세스 A에서 B로 프로세스가 넘어가는 순간에 프로세스 A정보를 백업하고 그작업이 끝난다면 -프로세스 B의 문맥을 불러오게 되며 이 것이 프로세스를 교대하는 방법입니다.

-

문맥교환을 통해 여러개의 프로세스가 병렬적으로 시행되는 것 처럼 보이게 하지만 이러한 문맥교환은 -오버헤드가 발생할 수 있기 때문에 문맥교환이 자주일어나면 오버헤드를 신경써야 합니다.

-
-
-

프로세스 상태

-
-

이전에 PCB에 기록되는 정보 중 프로세스 상태가 있다고 합니다. 여기서 말하는 프로세스 상태는 생성이 되었는지 -혹은 CPU를 사용하는지와 같은 정보를 통칭해서 프로세스 상태라고 부르게 됩니다.

-
-

프로세스 상태는 크게 다섯가지로 나뉠 수 있습니다.

-

![img.png](프로세스 상태 전이도.png) -사진출처

-
-

1. 생성 상태

-

프로세스를 생성 중인 상태를 생성 상태라고 부릅니다. 메모리에 적재되어 PCB를 할당받은 상태를 생성상태라고 부르게 됩니다. -생성 상태가 끝난다고 곧바로 실행되는 것이 아닌 준비 상태가 되어 실행되기를 기다리게 됩니다.

-
-

2. 준비 상태

-

준비 상태는 당장 CPU를 할당받아 실행될 수 있지만, 차례가 오지않아 기다리고 있는 상태입니다. -이 상태에서 준비가 되면 실행 상태로 넘어 갑니다. 그리고 다른 상태에서 다시 준비 상태로도 전환이 가능합니다.

-

준비 상태인 프로세스를 실행 상태로 전환하는 것을 디스패치 라고 부릅니다.

-
-

3. 실행 상태

-

실행 상태는 CPU를 할당받아 실행 중인 상태를 지칭 합니다. 실행 상태인 프로세스는 할당된 시간 동안 CPU를 사용할 수 있습니다. -이때 제한된 시간내 프로세스를 완료하지 못한경우 준비 상태로 전환이 되며, I/O입력처럼 대기해야 하는 상황이 생기면 -대기 상태로 넘어가게 됩니다.

-
-

4. 대기 상태

-

실행 상태에서 I/O입력과 같이 프로세스가 대기해야 하는 상황이 온다면 대기 상태로 진입하게 됩니다. -대기 상태가 끝난다고 해도 실행 상태가 되는것이 아닌 준비 상태로 넘어가게 됩니다.

-
-

5. 종료 상태

-

프로세스가 종료된 상태입니다. 이 상태에 도달하면 운영체제는 PCB와 프로세스가 사용한 메모리를 정리합니다.

-
-
-

프로세스 계층 구조

-
-

프로세스는 실행 도중 시스템 호출을 통해 다른 프로세스를 생성할 수 있습니다.

-

이때 새 프로세스를 생성한 프로세스를 부모 프로세스라고 부르게 되며, 생성 된 프로세스를 자식 프로세스라고 -부르게 됩니다. -부모의 프로세스와 자식의 프로세스는 각각 고유한 PID를 가지며 자식프로세스에서 부모프로세스 PID를 PPID로 가지고 있기도 합니다.

-
-

![img.png](프로세스 계층 구조.png) -[사진 출처: 혼자 공부하는 운영체제 저자:강민철]

-
-
-

프로세스 생성기법

-
-

그렇다면 부모 프로세스가 어떻게 자식 프로세스를 생성 할까요?

-

그 방법은 fork, exec라는 명령어를 통해서 생성하게 됩니다.

-

부모 프로세스는 fork를 통해 자신의 복사본을 자식 프로세스로 생성해내고, 그 복사본은 exec명령어를 통해 -자신의 메모리 공간을 다른 프로그램으로 교체합니다.

-
-

- - - - img.png - - -
img.png
-

-
-

좀더 자세히 설명하면 fork, exec 모두 시스템 호출로 분류 됩니다. -부모 프로세스는 fork 시스템 호출을 통해 자신의 복사본을 자식으로써 생성합니다.

-

여기서 자식은 부모의 복사본이기 때문에 부모 프로세스의 자원들, 예를들면 메모리의 내용, 열린 파일의 목록등을 -상속하게 됩니다. 그렇다고 해서 모든 정보가 같지는 않습니다.

-

왜냐하면, PID나 메모리 저장구조는 고유한 정보이기 때문에 fork로 만들어진 자식은 PID, 메모리 저장위치 -처럼 고유한 정보에 대해서는 개별적인 값을 가지고 있습니다.

-
-

- - - - img.png - - -
img.png
-

-
-

fork만 사용한 프로세스는 완전한 자식 프로세스라고 명하기는 조금 어렵습니다. -PID와 같은 고유한 값을 제외한다면 부모가 가진 리소스를 동일하게 사용하는 대체품이기 때문입니다.

-

그렇기 때문에 자식 프로세스는 자신의 프로세스를 가지기 위해 exec 시스템 호출을 하게 됩니다.

-

exec 호출을 진행하게 되면 자신의 메모리 공간을 새로운 프로그램으로 덮어쓰게 됩니다.

-

코드 영역과 데이터 영역의 내용이 실행한 프로그램으로 바뀌게 되고, 나머지 영역은 초기화 됩니다.

@jc, 023
CATCH NPE tech blog
- - \ No newline at end of file diff --git a/public/9/index.html b/public/9/index.html deleted file mode 100644 index 63e1aff..0000000 --- a/public/9/index.html +++ /dev/null @@ -1,431 +0,0 @@ -9. 쓰레드의 개념, 메모리 공유 구조 및 TCB

9. 쓰레드의 개념, 메모리 공유 구조 및 TCB

@jc, 023· September 12, 2025 · 8 min read

스레드란?

-
-

img.png

-
-

스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다.

-

또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면 -하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다.

-

마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과 -같이 여러 기능을 수행할 수 있습니다.

-
-

프로세스와 스레드

-
-

스레드를 이해하기 위해서는 프로세스와 엮어서 설명하고자 합니다. -전통적인 CPU는 하나의 프로세스만 처리할 수 있었습니다. 메모장, 워드, 게임등 많은 프로세스가 하나의 실행 -흐름을 가지고 한 번의 하나의 부분만 실행되는 프로세스입니다.

-

![img.png](단일스레드 프로세스.png)

-

이런 프로세스를 단일 스레드 프로세스라고 부릅니다.

-
-

하지만, 스레드라는 개념이 도입되면서 하나의 프로세스가 한 번에 여러가지 일을 동시에 처리하는 것이 가능해졌습니다. -프로세스를 구성하는 명령어를 동시에 처리하는것이 가능해졌습니다.

-

![img.png](멀티스레드 프로세스.png)

-
-

그림을 통해 스레드를 보게 되면 스레드는 '프로세스를 구성하는 실행의 흐름 단위'라고 표현 가능 할 것입니다.

-

왜냐하면, 하나의 프로세스 안에 여러가지 스레드가 있고 각각의 작업 흐름을 가지며 프로세스가 하는 일을 병렬적으로 만들어 -주기 때문입니다.

-
-
-

스레드 메모리 구조

-
-

img.png

-

스레드의 메모리 구조를 이해하기 위해서는 이전 프로세서의 구조를 상기해봐야 합니다.

-

프로세스는 스택, 힙, 데이터, 코드 영역을 각자 가진다고 합니다. -스레드는 '프로세스를 구성하는 실행 흐름의 단위'라고 했고, 이 떄문에 스레드는 프로세스의 메모리 구조의 대부분을 공유해서 -사용한다. 그렇기 때문에 여러 스레드의 작업이 하나의 프로세스 안에서 이루어져도 동시작업이 가능한 이유입니다.

-
-

그렇다면 어떻게 스레드는 프로세스와 스레드간 데이터를 공유하는 것일까? -아래 그림을 통해서 보게되면

-
-

img.png -사진출처

-
-

우선 하나의 프로세스안에 코드, 데이터, 힙, 스택 영역이 존재합니다. 그리고 프로세스 내부의 개별적인 스레드가 존재합니다.

-

스레드가 레지스터, 프로그램 카운터, 스택을 개별적으로 가지는 핵심 이유는 독립적인 실행 흐름을 보장하기 위해서입니다.

-

프로그램 카운터는 각 스레드가 서로 다른 코드 위치에서 실행될 수 있도록 현재 실행 지점을 개별 추적하고,

-

레지스터는 각 스레드의 작업 데이터를 독립적으로 저장합니다. -이를 통해 CPU가 스레드 간 전환할 때 현재 상태를 저장하고 복원하여 중단된 지점에서 정확히 재개할 수 있습니다. -스택 영역을 따로 가지는 이유는 각 스레드가 독립적인 함수 호출 흐름을 가져야 하기 때문입니다.

-

스택은 함수 호출 시 지역 변수, 매개변수, 리턴 주소를 저장하는데, 만약 스레드들이 스택을 공유한다면 한 스레드의 -함수 호출이 다른 스레드의 함수 실행에 영향을 주어 실행 흐름이 꼬이게 됩니다. 따라서 각 스레드는 독립적인 스택을 가져 서로 다른 함수를 안전하게 호출하고 실행할 수 있습니다. -결과적으로 이런 구조를 통해 스레드들은 힙과 데이터 영역은 공유하면서도 각자 독립적인 실행 흐름을 유지할 수 있어 -, 하나의 프로세스 내에서 여러 작업을 동시에 효율적으로 처리할 수 있게 됩니다.

-
-
-

TCB란

-
-

- - - - img.png - - -
img.png
-

-

스레드 제어 블록은 운영체제가 각 스레드를 관리하기 위해 유지하는 데이터 구조체입니다. -프로세스 제어 블록(PCB)과 유사하지만 스레드 수준에서 필요한 정보들을 담고 있습니다. -링크드 리스트 형태로 구현되어 PCB안에 해당 스레드의 TCB를 내포하고 있는 형태로 저장됩니다.

-
-

- - - - img.png - - -
img.png
-

-

img.png

-
-
-

TCB는 사진과 같은 형태로 저장되며, 아래와 같은 정보를 가진다.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
정보설명
스레드 식별자각 스레드를 식별하는 고유한 식별자
스레드 상태실행 준비 대기 등 스레드의 현재 상태
프로그램 카운터스레드가 다음에 실행할 명령어의 주소
레지스터스레드가 현재 사용하고 있는 CPU 레지스터의 값을 저장
스레드 우선순위스케줄링 결정에 사용되는 스레드의 우선순위
스레드 스택 포인터스택 내에서 현재 작업의 위치를 가리키는 레지스터
스레드 문맥 정보문맥 교환 시 저장되고 복원되어야 할 정보
@jc, 023
CATCH NPE tech blog
- - \ No newline at end of file diff --git a/public/98746260b83f1504b91525807bb027b2132b1e06-8ce7b094e042d4aab2f5.js b/public/98746260b83f1504b91525807bb027b2132b1e06-8ce7b094e042d4aab2f5.js old mode 100644 new mode 100755 diff --git a/public/98746260b83f1504b91525807bb027b2132b1e06-8ce7b094e042d4aab2f5.js.map b/public/98746260b83f1504b91525807bb027b2132b1e06-8ce7b094e042d4aab2f5.js.map old mode 100644 new mode 100755 diff --git a/public/_gatsby/slices/_gatsby-scripts-1.html b/public/_gatsby/slices/_gatsby-scripts-1.html old mode 100644 new mode 100755 index f112892..16a9105 --- a/public/_gatsby/slices/_gatsby-scripts-1.html +++ b/public/_gatsby/slices/_gatsby-scripts-1.html @@ -4,4 +4,4 @@ > window.___chunkMapping="{\"app\":[\"/app-bb1d8a42d75dd621fb85.js\"],\"component---src-pages-404-jsx\":[\"/component---src-pages-404-jsx-9350a586e1c084e4c88f.js\"],\"component---src-pages-about-jsx\":[\"/component---src-pages-about-jsx-92fbfcae63aaaeb1edb1.js\"],\"component---src-pages-index-jsx\":[\"/component---src-pages-index-jsx-2d43b52b97322dc30f96.js\"],\"component---src-pages-search-jsx\":[\"/component---src-pages-search-jsx-3521770e1444c679d03f.js\"],\"component---src-pages-series-jsx\":[\"/component---src-pages-series-jsx-f8d1242931c09ef32982.js\"],\"component---src-pages-tags-jsx\":[\"/component---src-pages-tags-jsx-f16d4a3f7da1f29cdbc3.js\"],\"component---src-templates-post-jsx\":[\"/component---src-templates-post-jsx-704f90f8a716eb8709d2.js\"],\"component---src-templates-series-jsx\":[\"/component---src-templates-series-jsx-3d5bf71e7c068278237d.js\"]}"; - \ No newline at end of file + \ No newline at end of file diff --git a/public/_redirects b/public/_redirects old mode 100644 new mode 100755 diff --git a/public/about/index.html b/public/about/index.html old mode 100644 new mode 100755 index 2d879bf..5182334 --- a/public/about/index.html +++ b/public/about/index.html @@ -1,4 +1,4 @@ -CATCH NPE"},this.getStyleTags=function(){return e.sealed?x(2):e._emitSheetCSS()},this.getStyleElement=function(){var t;if(e.sealed)return x(2);var n=((t={})[E]="",t["data-styled-version"]="5.3.11",t.dangerouslySetInnerHTML={__html:e.instance.toString()},t),r=H();return r&&(n.nonce=r),[o.createElement("style",h({},n,{key:"sc-0-0"}))]},this.seal=function(){e.sealed=!0},this.instance=new G({isServer:!0}),this.sealed=!1}var t=e.prototype;return t.collectStyles=function(e){return this.sealed?x(2):o.createElement(pe,{sheet:this.instance},e)},t.interleaveWithNodeStream=function(e){return x(3)},e}(),We=function(e){var t=o.forwardRef(function(t,n){var r=(0,o.useContext)(Ne),a=e.defaultProps,i=Ee(t,r,a);return o.createElement(e,h({},t,{theme:i,ref:n}))});return d()(t,e),t.displayName="WithTheme("+w(e)+")",t},qe=function(){return(0,o.useContext)(Ne)},Be={StyleSheet:G,masterSheet:se},ze=Le},2799:function(e,t){"use strict";var n="function"==typeof Symbol&&Symbol.for,r=n?Symbol.for("react.element"):60103,o=n?Symbol.for("react.portal"):60106,a=n?Symbol.for("react.fragment"):60107,i=n?Symbol.for("react.strict_mode"):60108,s=n?Symbol.for("react.profiler"):60114,c=n?Symbol.for("react.provider"):60109,u=n?Symbol.for("react.context"):60110,l=n?Symbol.for("react.async_mode"):60111,p=n?Symbol.for("react.concurrent_mode"):60111,f=n?Symbol.for("react.forward_ref"):60112,d=n?Symbol.for("react.suspense"):60113,h=n?Symbol.for("react.suspense_list"):60120,m=n?Symbol.for("react.memo"):60115,g=n?Symbol.for("react.lazy"):60116,y=n?Symbol.for("react.block"):60121,v=n?Symbol.for("react.fundamental"):60117,b=n?Symbol.for("react.responder"):60118,w=n?Symbol.for("react.scope"):60119;function S(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case l:case p:case a:case s:case i:case d:return e;default:switch(e=e&&e.$$typeof){case u:case f:case g:case m:case c:return e;default:return t}}case o:return t}}}function E(e){return S(e)===p}t.AsyncMode=l,t.ConcurrentMode=p,t.ContextConsumer=u,t.ContextProvider=c,t.Element=r,t.ForwardRef=f,t.Fragment=a,t.Lazy=g,t.Memo=m,t.Portal=o,t.Profiler=s,t.StrictMode=i,t.Suspense=d,t.isAsyncMode=function(e){return E(e)||S(e)===l},t.isConcurrentMode=E,t.isContextConsumer=function(e){return S(e)===u},t.isContextProvider=function(e){return S(e)===c},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===r},t.isForwardRef=function(e){return S(e)===f},t.isFragment=function(e){return S(e)===a},t.isLazy=function(e){return S(e)===g},t.isMemo=function(e){return S(e)===m},t.isPortal=function(e){return S(e)===o},t.isProfiler=function(e){return S(e)===s},t.isStrictMode=function(e){return S(e)===i},t.isSuspense=function(e){return S(e)===d},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===a||e===p||e===s||e===i||e===d||e===h||"object"==typeof e&&null!==e&&(e.$$typeof===g||e.$$typeof===m||e.$$typeof===c||e.$$typeof===u||e.$$typeof===f||e.$$typeof===v||e.$$typeof===b||e.$$typeof===w||e.$$typeof===y)},t.typeOf=S},2833:function(e){e.exports=function(e,t,n,r){var o=n?n.call(r,e,t):void 0;if(void 0!==o)return!!o;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var a=Object.keys(e),i=Object.keys(t);if(a.length!==i.length)return!1;for(var s=Object.prototype.hasOwnProperty.bind(t),c=0;c(null==e?void 0:e.forward)||[])}},3662:function(e,t,n){"use strict";function r(e,t){return r=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},r(e,t)}n.d(t,{A:function(){return r}})},3697:function(e,t,n){"use strict";n.r(t),n.d(t,{onClientEntry:function(){return c}});var r=n(4794),o=n(382),a=n.n(o);const i=e=>"/"===e[0]?e:`/${e}`,s=(e,t)=>n=>{if(window.___failedResources)return!0;if((e=>0!==e.button||e.altKey||e.ctrlKey||e.metaKey||e.shiftKey)(n))return!0;if((e=>e.defaultPrevented)(n))return!0;const o=(e=>{for(;e.parentNode;e=e.parentNode)if("a"===e.nodeName.toLowerCase())return e;return null})(n.target);if(null==o)return!0;if(!0===(s=o).hasAttribute("download")||!1===(e=>!1===e.hasAttribute("target")||null==e.target||["_self",""].includes(e.target)||"_parent"===e.target&&(!e.ownerDocument.defaultView.parent||e.ownerDocument.defaultView.parent===e.ownerDocument.defaultView)||"_top"===e.target&&(!e.ownerDocument.defaultView.top||e.ownerDocument.defaultView.top===e.ownerDocument.defaultView))(s))return!0;var s;const c=document.createElement("a");""!==o.href&&(c.href=o.href),"SVGAnimatedString"in window&&o.href instanceof SVGAnimatedString&&(c.href=o.href.animVal);const u=document.createElement("a");if(u.href=window.location.href,!1===((e,t)=>e.protocol===t.protocol&&e.host===t.host)(u,c))return!0;const l=new RegExp(`^${a()((0,r.withPrefix)("/"))}`);if(((e,t)=>!1===t.test(i(e.pathname))||-1!==e.pathname.search(/^.*\.((?!htm)[a-z0-9]{1,5})$/i))(c,l))return!0;if(((e,t)=>""!==t.hash&&(""===t.pathname||t.pathname===e.pathname))(u,c))return!0;if(t.excludePattern){if(new RegExp(t.excludePattern).test(c.pathname))return!0}n.preventDefault();const p=i(c.pathname).replace(l,"/");return e(`${p}${c.search}${c.hash}`),!1};const c=function(e,t){void 0===t&&(t={}),function(e,t,n){const r=s(n,t);e.addEventListener("click",r)}(window,t,e=>{(0,r.navigate)(e)})}},3721:function(e,t,n){"use strict";t.__esModule=!0,t.useScrollRestoration=function(e){var t=(0,a.useLocation)(),n=(0,o.useContext)(r.ScrollContext),i=(0,o.useRef)(null);return(0,o.useLayoutEffect)(function(){if(i.current){var r=n.read(t,e);i.current.scrollTo(0,r||0)}},[t.key]),{ref:i,onScroll:function(){i.current&&n.save(t,e,i.current.scrollTop)}}};var r=n(3215),o=n(6540),a=n(6462)},3785:function(e,t,n){"use strict";var r=n(4994);t.__esModule=!0,t.onInitialClientRender=t.wrapRootElement=void 0;var o=r(n(6540)),a=n(134),i=r(n(6305)),s=n(8919);t.wrapRootElement=function(e,t){var n,r=e.element;void 0===t&&(t={});var c=window[null!==(n=t.windowKey)&&void 0!==n?n:s.DEFAULT_OPTIONS.windowKey],u=(0,i.default)(c);return o.default.createElement(a.Provider,{store:u},r)};t.onInitialClientRender=function(e,t){var n;if(void 0===t&&(t={}),Boolean(null!==(n=t.cleanupOnClient)&&void 0!==n?n:s.DEFAULT_OPTIONS.cleanupOnClient)){var r,o=null!==(r=t.windowKey)&&void 0!==r?r:s.DEFAULT_OPTIONS.windowKey;delete window[o];var a=document.getElementById(s.SCRIPT_ELEMENT_ID);a&&a.parentNode.removeChild(a)}}},4146:function(e,t,n){"use strict";var r=n(4363),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function c(e){return r.isMemo(e)?i:s[e.$$typeof]||o}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[r.Memo]=i;var u=Object.defineProperty,l=Object.getOwnPropertyNames,p=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,d=Object.getPrototypeOf,h=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(h){var o=d(n);o&&o!==h&&e(t,o,r)}var i=l(n);p&&(i=i.concat(p(n)));for(var s=c(t),m=c(n),g=0;ge.length)&&(t=e.length);for(var n=0,r=Array(t);n((e,t)=>{const{forward:n=[],...r}=e||{},o=JSON.stringify(r,(e,t)=>("function"==typeof t&&(t=String(t)).startsWith(e+"(")&&(t="function "+t),t));return["!(function(w,p,f,c){",Object.keys(r).length>0?`c=w[p]=Object.assign(w[p]||{},${o});`:"c=w[p]=w[p]||{};","c[f]=(c[f]||[])",n.length>0?`.concat(${JSON.stringify(n)})`:"","})(window,'partytown','forward');",t].join("")})(e,'/* Partytown 0.7.6 - MIT builder.io */\n!function(t,e,n,i,r,o,a,d,s,c,p,l){function u(){l||(l=1,"/"==(a=(o.lib||"/~partytown/")+(o.debug?"debug/":""))[0]&&(s=e.querySelectorAll(\'script[type="text/partytown"]\'),i!=t?i.dispatchEvent(new CustomEvent("pt1",{detail:t})):(d=setTimeout(f,1e4),e.addEventListener("pt0",w),r?h(1):n.serviceWorker?n.serviceWorker.register(a+(o.swPath||"partytown-sw.js"),{scope:a}).then((function(t){t.active?h():t.installing&&t.installing.addEventListener("statechange",(function(t){"activated"==t.target.state&&h()}))}),console.error):f())))}function h(t){c=e.createElement(t?"script":"iframe"),t||(c.setAttribute("style","display:block;width:0;height:0;border:0;visibility:hidden"),c.setAttribute("aria-hidden",!0)),c.src=a+"partytown-"+(t?"atomics.js?v=0.7.6":"sandbox-sw.html?"+Date.now()),e.body.appendChild(c)}function f(n,r){for(w(),i==t&&(o.forward||[]).map((function(e){delete t[e.split(".")[0]]})),n=0;n{let{sliceId:t,children:n}=e;const r=[h.createElement("slice-start",{id:`${t}-1`}),h.createElement("slice-end",{id:`${t}-1`})];return n&&(r.push(n),r.push(h.createElement("slice-start",{id:`${t}-2`}),h.createElement("slice-end",{id:`${t}-2`}))),r},v=e=>{let{sliceName:t,allowEmpty:n,children:r,...o}=e;const a=(0,h.useContext)(g.Jr),i=(0,h.useContext)(g.hr),s=a[t];if(!s){if(n)return null;throw new Error(`Slice "${s}" for "${t}" slot not found`)}const c=((e,t)=>Object.keys(t).length?`${e}-${(0,m.U)(t)}`:e)(s,o);let u=i[c];return u?r&&(u.hasChildren=!0):i[c]=u={props:o,sliceName:s,hasChildren:!!r},h.createElement(y,{sliceId:c},r)},b=e=>{let{sliceName:t,allowEmpty:n,children:r,...o}=e;const a=(0,h.useContext)(g.Jr),i=(0,h.useContext)(g.dd),s=a[t],c=i.get(s);if(!c){if(n)return null;throw new Error(`Slice "${s}" for "${t}" slot not found`)}return h.createElement(c.component,Object.assign({sliceContext:c.sliceContext,data:c.data},o),r)};function w(e){{const t={...e,sliceName:e.alias};delete t.alias,delete t.__renderedByLocation;const n=(0,h.useContext)(g.j$),r=E(e);if(Object.keys(r).length)throw new S("browser"===n.renderEnvironment,t.sliceName,r,e.__renderedByLocation);if("server"===n.renderEnvironment)return h.createElement(v,t);if("browser"===n.renderEnvironment)return h.createElement(b,t);if("engines"===n.renderEnvironment||"dev-ssr"===n.renderEnvironment)return h.createElement(b,t);if("slices"===n.renderEnvironment){let t="";try{t=`\n\nSlice component "${n.sliceRoot.name}" (${n.sliceRoot.componentPath}) tried to render `}catch{}throw new Error(`Nested slices are not supported.${t}\n\nSee https://gatsbyjs.com/docs/reference/built-in-components/gatsby-slice#nested-slices`)}throw new Error(`Slice context "${n.renderEnvironment}" is not supported.`)}}let S=function(e){function t(n,r,o,a){var i;const s=Object.entries(o).map(e=>{let[t,n]=e;return`not serializable "${n}" type passed to "${t}" prop`}).join(", "),c="SlicePropsError";let u="",l="";if(n){const e=h.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactDebugCurrentFrame.getCurrentStack().trim().split("\n").slice(1);e[0]=e[0].trim(),u="\n"+e.join("\n"),l=`Slice "${r}" was passed props that are not serializable (${s}).`}else{l=`${c}: Slice "${r}" was passed props that are not serializable (${s}).`;u=`${l}\n${(new Error).stack.trim().split("\n").slice(2).join("\n")}`}return(i=e.call(this,l)||this).name=c,u?i.stack=u:Error.captureStackTrace(i,t),a&&(i.forcedLocation={...a,functionName:"Slice"}),i}return(0,u.A)(t,e),t}(d(Error));const E=function(e,t,n,r){void 0===t&&(t={}),void 0===n&&(n=[]),void 0===r&&(r=null);for(const[o,a]of Object.entries(e)){if(null==a||!r&&"children"===o)continue;const e=r?`${r}.${o}`:o;"function"==typeof a?t[e]=typeof a:"object"==typeof a&&n.indexOf(a)<=0&&(n.push(a),E(a,t,n,e))}return t};var C=n(5535);const P=r.Ay.enqueue;function k(){throw new Error("It appears like Gatsby is misconfigured. Gatsby related `graphql` calls are supposed to only be evaluated at compile time, and then compiled away. Unfortunately, something went wrong and the query was left in the compiled code.\n\nUnless your site has a complex or custom babel/Gatsby configuration this is likely a bug in Gatsby.")}},4994:function(e){e.exports=function(e){return e&&e.__esModule?e:{default:e}},e.exports.__esModule=!0,e.exports.default=e.exports},5535:function(e,t,n){"use strict";n.r(t),n.d(t,{Script:function(){return h},ScriptStrategy:function(){return u},collectedScriptsByPage:function(){return s},scriptCache:function(){return f},scriptCallbackCache:function(){return d}});var r=n(6540),o=n(6462);function a(){return a=Object.assign?Object.assign.bind():function(e){for(var t=1;ti.get(e)||[],set(e,t){const n=i.get(e)||[];n.push(t),i.set(e,n)},delete(e){i.delete(e)}},c="undefined"!=typeof self&&self.requestIdleCallback&&self.requestIdleCallback.bind(window)||function(e){const t=Date.now();return setTimeout(function(){e({didTimeout:!1,timeRemaining:function(){return Math.max(0,50-(Date.now()-t))}})},1)};var u,l;(l=u||(u={})).postHydrate="post-hydrate",l.idle="idle",l.offMainThread="off-main-thread";const p=new Set(["src","strategy","dangerouslySetInnerHTML","children","onLoad","onError"]),f=new Set,d=new Map;function h(e){return r.createElement(o.Location,null,()=>r.createElement(m,e))}function m(e){const{src:t,strategy:n=u.postHydrate}=e||{},{pathname:i}=(0,o.useLocation)();if((0,r.useEffect)(()=>{let t;switch(n){case u.postHydrate:t=g(e);break;case u.idle:c(()=>{t=g(e)});break;case u.offMainThread:{const t=v(e);s.set(i,t)}}return()=>{const{script:e,loadCallback:n,errorCallback:r}=t||{};n&&(null==e||e.removeEventListener("load",n)),r&&(null==e||e.removeEventListener("error",r)),null==e||e.remove()}},[]),n===u.offMainThread){const o=y(e),c=v(e);return"undefined"==typeof window&&s.set(i,c),r.createElement("script",o?a({type:"text/partytown","data-strategy":n,crossOrigin:"anonymous"},c,{dangerouslySetInnerHTML:{__html:y(e)}}):a({type:"text/partytown",src:b(t),"data-strategy":n,crossOrigin:"anonymous"},c))}return null}function g(e){const{id:t,src:n,strategy:r=u.postHydrate,onLoad:o,onError:i}=e||{},s=t||n,c=["load","error"],l={load:o,error:i};if(s){for(const e of c)if(null!=l&&l[e]){var p;const t=d.get(s)||{},{callbacks:n=[]}=(null==t?void 0:t[e])||{};var h,m;n.push(null==l?void 0:l[e]),null!=t&&null!=(p=t[e])&&p.event?null==l||null==(h=l[e])||h.call(l,null==t||null==(m=t[e])?void 0:m.event):d.set(s,a({},t,{[e]:{callbacks:n}}))}if(f.has(s))return null}const g=y(e),b=v(e),S=document.createElement("script");t&&(S.id=t),S.dataset.strategy=r;for(const[a,u]of Object.entries(b))S.setAttribute(a,u);g&&(S.textContent=g),n&&(S.src=n);const E={};if(s){for(const e of c){const t=t=>w(t,s,e);S.addEventListener(e,t),E[`${e}Callback`]=t}f.add(s)}return document.body.appendChild(S),{script:S,loadCallback:E.loadCallback,errorCallback:E.errorCallback}}function y(e){const{dangerouslySetInnerHTML:t,children:n=""}=e||{},{__html:r=""}=t||{};return r||n}function v(e){const t={};for(const[n,r]of Object.entries(e))p.has(n)||(t[n]=r);return t}function b(e){if(e)return`/__third-party-proxy?url=${encodeURIComponent(e)}`}function w(e,t,n){const r=d.get(t)||{};for(const a of(null==r||null==(o=r[n])?void 0:o.callbacks)||[]){var o;a(e)}d.set(t,{[n]:{event:e}})}},5616:function(e,t,n){"use strict";var r=n(7688),o=r.DEFAULT_OPTIONS,a=r.imageClass,i=r.imageBackgroundClass,s=r.imageWrapperClass;t.onRouteUpdate=function(e,t){for(var n=Object.assign({},o,t),r=document.querySelectorAll("."+s),c=function(){var e=r[u],t=e.querySelector("."+i),o=e.querySelector("."+a),s=function(){t.style.transition="opacity 0.5s 0.5s",o.style.transition="opacity 0.5s",c()},c=function e(){t.style.opacity=0,o.style.opacity=1,o.style.color="inherit",o.style.boxShadow="inset 0px 0px 0px 400px "+n.backgroundColor,o.removeEventListener("load",s),o.removeEventListener("error",e)};o.style.opacity=0,o.addEventListener("load",s),o.addEventListener("error",c),o.complete&&c()},u=0;u{n()}),t}const d=["link","meta","style","title","base","noscript","script","html","body"];function h(e){0}function m(e,t){if(e instanceof HTMLElement&&t instanceof HTMLElement){const n=t.getAttribute("nonce");if(n&&!e.getAttribute("nonce")){const r=t.cloneNode(!0);return r.setAttribute("nonce",""),r.nonce=n,n===e.nonce&&e.isEqualNode(r)}}return e.isEqualNode(t)}function g(e,t){void 0===t&&(t={html:{},body:{}});const n=new Map,r=[];for(const u of e.childNodes){var o,a;const e=u.nodeName.toLowerCase(),l=null===(o=u.attributes)||void 0===o||null===(a=o.id)||void 0===a?void 0:a.value;if(b(u)){if(v(e))if("html"===e||"body"===e)for(const n of u.attributes){const r="style"===n.name;var i;if(t[e]={...t[e]},r||(t[e][n.name]=n.value),r)t[e].style=`${null!==(i=t[e])&&void 0!==i&&i.style?t[e].style:""}${n.value} `}else{let e=u.cloneNode(!0);if(e.setAttribute("data-gatsby-head",!0),"script"===e.nodeName.toLowerCase()&&(e=y(e)),l)if(n.has(l)){var s;const t=n.get(l);null===(s=r[t].parentNode)||void 0===s||s.removeChild(r[t]),r[t]=e}else r.push(e),n.set(l,r.length-1);else r.push(e)}else h();u.childNodes.length&&r.push.apply(r,(0,c.A)(g(u,t).validHeadNodes))}}return{validHeadNodes:r,htmlAndBodyAttributes:t}}function y(e){const t=document.createElement("script");for(const n of e.attributes)t.setAttribute(n.name,n.value);return t.innerHTML=e.innerHTML,t}function v(e){return d.includes(e)}function b(e){return 1===e.nodeType}const w=document.createElement("div"),S={html:[],body:[]},E=()=>{var e;const{validHeadNodes:t,htmlAndBodyAttributes:n}=g(w);S.html=Object.keys(n.html),S.body=Object.keys(n.body),function(e){if(!e)return;const{html:t,body:n}=e,r=document.querySelector("html");r&&Object.entries(t).forEach(e=>{let[t,n]=e;r.setAttribute(t,n)});const o=document.querySelector("body");o&&Object.entries(n).forEach(e=>{let[t,n]=e;o.setAttribute(t,n)})}(n);const r=document.querySelectorAll("[data-gatsby-head]");var o;if(0===r.length)return void(o=document.head).append.apply(o,(0,c.A)(t));const a=[];!function(e){let{oldNodes:t,newNodes:n,onStale:r,onNew:o}=e;for(const a of t){const e=n.findIndex(e=>m(e,a));-1===e?r(a):n.splice(e,1)}for(const a of n)o(a)}({oldNodes:r,newNodes:t,onStale:e=>e.parentNode.removeChild(e),onNew:e=>a.push(e)}),(e=document.head).append.apply(e,a)};function C(e){let{pageComponent:t,staticQueryResults:n,pageComponentProps:o}=e;(0,r.useEffect)(()=>{if(null!=t&&t.Head){!function(e){if("function"!=typeof e)throw new Error(`Expected "Head" export to be a function got "${typeof e}".`)}(t.Head);const{render:a}=(0,p.n)(),s=r.createElement(t.Head,{location:{pathname:(e=o).location.pathname},params:e.params,data:e.data||{},serverData:e.serverData,pageContext:e.pageContext}),c=(0,i.N)("wrapRootElement",{element:s},s,e=>{let{result:t}=e;return{element:t}}).pop();a(r.createElement(f,{callback:E},r.createElement(u.StaticQueryContext.Provider,{value:n},r.createElement(l.LocationProvider,null,c))),w)}var e;return()=>{!function(){const e=document.querySelectorAll("[data-gatsby-head]");for(const t of e)t.parentNode.removeChild(t)}(),function(e){if(!e)return;const{html:t,body:n}=e;if(t){const e=document.querySelector("html");t.forEach(t=>{e&&e.removeAttribute(t)})}if(n){const e=document.querySelector("body");n.forEach(t=>{e&&e.removeAttribute(t)})}}(S)}})}function P(e){const t={...e,params:{...(0,s.UA)(e.location.pathname),...e.pageResources.json.pageContext.__params}};let n;var o;n=e.pageResources.partialHydration?e.pageResources.partialHydration:(0,r.createElement)((o=e.pageResources.component)&&o.default||o,{...t,key:e.path||e.pageResources.page.path});C({pageComponent:e.pageResources.head,staticQueryResults:e.pageResources.staticQueryResults,pageComponentProps:t});return(0,i.N)("wrapPageElement",{element:n,props:t},n,e=>{let{result:n}=e;return{element:n,props:t}}).pop()}P.propTypes={location:a().object.isRequired,pageResources:a().object.isRequired,data:a().object,pageContext:a().object.isRequired};var k=P},6221:function(e,t,n){var r=n(5636);e.exports=function(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,r(e,t)},e.exports.__esModule=!0,e.exports.default=e.exports},6305:function(e,t,n){e.exports=n(8417)},6395:function(e,t){"use strict";t.T=void 0;const n=[".html",".json",".js",".map",".txt",".xml",".pdf"];t.T=(e,t="always")=>{if("/"===e)return e;const r=e.endsWith("/");return((e,t)=>{for(const n of e)if(t.endsWith(n))return!0;return!1})(n,e)?e:"always"===t?r?e:`${e}/`:"never"===t&&r?e.slice(0,-1):e}},6462:function(e,t,n){"use strict";var r;n.r(t),n.d(t,{BaseContext:function(){return g},Link:function(){return V},Location:function(){return X},LocationContext:function(){return y},LocationProvider:function(){return K},Match:function(){return ee},Redirect:function(){return P},Router:function(){return se},ServerLocation:function(){return Z},createHistory:function(){return l},createMemorySource:function(){return p},globalHistory:function(){return d},insertParams:function(){return O},isRedirect:function(){return S},match:function(){return x},navigate:function(){return h},pick:function(){return _},redirectTo:function(){return E},resolve:function(){return R},shallowCompare:function(){return H},startsWith:function(){return k},useBaseContext:function(){return v},useLocation:function(){return ue},useLocationContext:function(){return b},useMatch:function(){return fe},useNavigate:function(){return le},useParams:function(){return pe},validateRedirect:function(){return A}});var o=n(6540),a=n(5556),i=n(311);function s(){return s=Object.assign?Object.assign.bind():function(e){for(var t=1;t=0||(o[n]=e[n]);return o}const u=e=>{const{search:t,hash:n,href:r,origin:o,protocol:a,host:i,hostname:s,port:c}=e.location;let{pathname:u}=e.location;return!u&&r&&f&&(u=new URL(r).pathname),{pathname:encodeURI(decodeURI(u)),search:t,hash:n,href:r,origin:o,protocol:a,host:i,hostname:s,port:c,state:e.history.state,key:e.history.state&&e.history.state.key||"initial"}},l=(e,t)=>{let n=[],r=u(e),o=!1,a=()=>{};return{get location(){return r},get transitioning(){return o},_onTransitionComplete(){o=!1,a()},listen(t){n.push(t);const o=()=>{r=u(e),t({location:r,action:"POP"})};return e.addEventListener("popstate",o),()=>{e.removeEventListener("popstate",o),n=n.filter(e=>e!==t)}},navigate(t,{state:i,replace:c=!1}={}){if("number"==typeof t)e.history.go(t);else{i=s({},i,{key:Date.now()+""});try{o||c?e.history.replaceState(i,null,t):e.history.pushState(i,null,t)}catch(n){e.location[c?"replace":"assign"](t)}}r=u(e),o=!0;const l=new Promise(e=>a=e);return n.forEach(e=>e({location:r,action:"PUSH"})),l}}},p=(e="/")=>{const t=e.indexOf("?"),n={pathname:t>-1?e.substr(0,t):e,search:t>-1?e.substr(t):""};let r=0;const o=[n],a=[null];return{get location(){return o[r]},addEventListener(e,t){},removeEventListener(e,t){},history:{get entries(){return o},get index(){return r},get state(){return a[r]},pushState(e,t,n){const[i,s=""]=n.split("?");r++,o.push({pathname:i,search:s.length?`?${s}`:s}),a.push(e)},replaceState(e,t,n){const[i,s=""]=n.split("?");o[r]={pathname:i,search:s},a[r]=e},go(e){const t=r+e;t<0||t>a.length-1||(r=t)}}}},f=!("undefined"==typeof window||!window.document||!window.document.createElement),d=l(f?window:p()),{navigate:h}=d;function m(e,t){return o.createServerContext?((e,t=null)=>(globalThis.__SERVER_CONTEXT||(globalThis.__SERVER_CONTEXT={}),globalThis.__SERVER_CONTEXT[e]||(globalThis.__SERVER_CONTEXT[e]=o.createServerContext(e,t)),globalThis.__SERVER_CONTEXT[e]))(e,t):o.createContext(t)}const g=m("Base",{baseuri:"/",basepath:"/"}),y=m("Location"),v=()=>o.useContext(g),b=()=>o.useContext(y);function w(e){this.uri=e}const S=e=>e instanceof w,E=e=>{throw new w(e)};function C(e){const{to:t,replace:n=!0,state:r,noThrow:a,baseuri:i}=e;o.useEffect(()=>{Promise.resolve().then(()=>{const o=R(t,i);h(O(o,e),{replace:n,state:r})})},[]);const s=R(t,i);return a||E(O(s,e)),null}const P=e=>{const t=b(),{baseuri:n}=v();return o.createElement(C,s({},t,{baseuri:n},e))};P.propTypes={from:a.string,to:a.string.isRequired};const k=(e,t)=>e.substr(0,t.length)===t,_=(e,t)=>{let n,r;const[o]=t.split("?"),a=M(o),s=""===a[0],c=D(e);for(let u=0,l=c.length;u dynamic segment "${r[1]}" is a reserved name. Please use a different name in path "${o.path}".`);const t=decodeURIComponent(n);p[r[1]]=t}else if(t!==n){e=!0;break}}if(!e){n={route:o,params:p,uri:"/"+a.slice(0,d).join("/")};break}}return n||r||null},x=(e,t)=>_([{path:e}],t),R=(e,t)=>{if(k(e,"/"))return e;const[n,r]=e.split("?"),[o]=t.split("?"),a=M(n),i=M(o);if(""===a[0])return L(o,r);if(!k(a[0],".")){const e=i.concat(a).join("/");return L(("/"===o?"":"/")+e,r)}const s=i.concat(a),c=[];for(let u=0,l=s.length;u{const[n,r=""]=e.split("?");let o="/"+M(n).map(e=>{const n=T.exec(e);return n?t[n[1]]:e}).join("/");const{location:{search:a=""}={}}=t,i=a.split("?")[1]||"";return o=L(o,r,i),o},A=(e,t)=>{const n=e=>N(e);return M(e).filter(n).sort().join("/")===M(t).filter(n).sort().join("/")},T=/^:(.+)/,N=e=>T.test(e),j=e=>e&&"*"===e[0],I=(e,t)=>({route:e,score:e.default?0:M(e.path).reduce((e,t)=>(e+=4,(e=>""===e)(t)?e+=1:N(t)?e+=2:j(t)?e-=5:e+=3,e),0),index:t}),D=e=>e.map(I).sort((e,t)=>e.scoret.score?-1:e.index-t.index),M=e=>e.replace(/(^\/+|\/+$)/g,"").split("/"),L=(e,...t)=>e+((t=t.filter(e=>e&&e.length>0))&&t.length>0?`?${t.join("&")}`:""),$=["uri","path"],H=(e,t)=>{const n=Object.keys(e);return n.length===Object.keys(t).length&&n.every(n=>t.hasOwnProperty(n)&&e[n]===t[n])},F=e=>e.replace(/(^\/+|\/+$)/g,""),U=e=>t=>{if(!t)return null;if(t.type===o.Fragment&&t.props.children)return o.Children.map(t.props.children,U(e));if(i(t.props.path||t.props.default||t.type===P,`: Children of must have a \`path\` or \`default\` prop, or be a \`\`. None found on element type \`${t.type}\``),i(!!(t.type!==P||t.props.from&&t.props.to),` requires both "from" and "to" props when inside a .`),i(!(t.type===P&&!A(t.props.from,t.props.to)),` has mismatched dynamic segments, ensure both paths have the exact same dynamic segments.`),t.props.default)return{value:t,default:!0};const n=t.type===P?t.props.from:t.props.path,r="/"===n?e:`${F(e)}/${F(n)}`;return{value:t,default:t.props.default,path:t.props.children?`${F(r)}/*`:r}},W=["innerRef"],q=["to","state","replace","getProps"],B=["key"];let{forwardRef:z}=r||(r=n.t(o,2));void 0===z&&(z=e=>e);const G=()=>{},V=z((e,t)=>{let{innerRef:n}=e,r=c(e,W);const{baseuri:a}=v(),{location:i}=b(),{to:u,state:l,replace:p,getProps:f=G}=r,d=c(r,q),m=R(u,a),g=encodeURI(m),y=i.pathname===g,w=k(i.pathname,g);return o.createElement("a",s({ref:t||n,"aria-current":y?"page":void 0},d,f({isCurrent:y,isPartiallyCurrent:w,href:m,location:i}),{href:m,onClick:e=>{if(d.onClick&&d.onClick(e),(e=>!e.defaultPrevented&&0===e.button&&!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey))(e)){e.preventDefault();let t=p;if("boolean"!=typeof p&&y){const e=c(s({},i.state),B);t=H(s({},l),e)}h(m,{state:l,replace:t})}}}))});V.displayName="Link",V.propTypes={to:a.string.isRequired};class J extends o.Component{constructor(...e){super(...e),this.displayName="ReactUseErrorBoundary"}componentDidCatch(...e){this.setState({}),this.props.onError(...e)}render(){return this.props.children}}const Q=o.createContext({componentDidCatch:{current:void 0},error:void 0,setError:()=>!1});function Y({children:e}){const[t,n]=o.useState(),r=o.useRef(),a=o.useMemo(()=>({componentDidCatch:r,error:t,setError:n}),[t]);return o.createElement(Q.Provider,{value:a},o.createElement(J,{error:t,onError:(e,t)=>{n(e),null==r.current||r.current(e,t)}},e))}Y.displayName="ReactUseErrorBoundaryContext";const K=function(e){var t,n;function r(t){return o.createElement(Y,null,o.createElement(e,s({key:"WrappedComponent"},t)))}return r.displayName=`WithErrorBoundary(${null!=(t=null!=(n=e.displayName)?n:e.name)?t:"Component"})`,r}(({history:e=d,children:t})=>{const{location:n}=e,[r,a]=o.useState({location:n}),[i]=function(){const e=o.useContext(Q);e.componentDidCatch.current=void 0;const t=o.useCallback(()=>{e.setError(void 0)},[]);return[e.error,t]}();if(o.useEffect(()=>{e._onTransitionComplete()},[r.location]),o.useEffect(()=>{let t=!1;const n=e.listen(({location:e})=>{Promise.resolve().then(()=>{requestAnimationFrame(()=>{t||a({location:e})})})});return()=>{t=!0,n()}},[]),i){if(!S(i))throw i;h(i.uri,{replace:!0})}return o.createElement(y.Provider,{value:r},"function"==typeof t?t(r):t||null)}),X=({children:e})=>{const t=b();return t?e(t):o.createElement(K,null,e)},Z=({url:e,children:t})=>{const n=e.indexOf("?");let r,a="";return n>-1?(r=e.substring(0,n),a=e.substring(n)):r=e,o.createElement(y.Provider,{value:{location:{pathname:r,search:a,hash:""}}},t)},ee=({path:e,children:t})=>{const{baseuri:n}=v(),{location:r}=b(),o=R(e,n),a=x(o,r.pathname);return t({location:r,match:a?s({},a.params,{uri:a.uri,path:e}):null})},te=["uri","location","component"],ne=["children","style","component","uri","location"],re=e=>{let{uri:t,location:n,component:r}=e,a=c(e,te);return o.createElement(ae,s({},a,{component:r,uri:t,location:n}))};let oe=0;const ae=e=>{let{children:t,style:n,component:r="div",uri:a,location:i}=e,u=c(e,ne);const l=o.useRef(),p=o.useRef(!0),f=o.useRef(a),d=o.useRef(i.pathname),h=o.useRef(!1);o.useEffect(()=>(oe++,m(),()=>{oe--,0===oe&&(p.current=!0)}),[]),o.useEffect(()=>{let e=!1,t=!1;a!==f.current&&(f.current=a,e=!0),i.pathname!==d.current&&(d.current=i.pathname,t=!0),h.current=e||t&&i.pathname===a,h.current&&m()},[a,i]);const m=o.useCallback(()=>{var e;p.current?p.current=!1:(e=l.current,h.current&&e&&e.focus())},[]);return o.createElement(r,s({style:s({outline:"none"},n),tabIndex:"-1",ref:l},u),t)},ie=["location","primary","children","basepath","baseuri","component"],se=e=>{const t=v(),n=b();return o.createElement(ce,s({},t,n,e))};function ce(e){const{location:t,primary:n=!0,children:r,basepath:a,component:i="div"}=e,u=c(e,ie),l=o.Children.toArray(r).reduce((e,t)=>{const n=U(a)(t);return e.concat(n)},[]),{pathname:p}=t,f=_(l,p);if(f){const{params:e,uri:r,route:c,route:{value:l}}=f,p=c.default?a:c.path.replace(/\*$/,""),d=s({},e,{uri:r,location:t}),h=o.cloneElement(l,d,l.props.children?o.createElement(se,{location:t,primary:n},l.props.children):void 0),m=n?re:i,y=n?s({uri:r,location:t,component:i},u):u;return o.createElement(g.Provider,{value:{baseuri:r,basepath:p}},o.createElement(m,y,h))}return null}const ue=()=>{const e=b();if(!e)throw new Error("useLocation hook was used but a LocationContext.Provider was not found in the parent tree. Make sure this is used in a component that is a child of Router");return e.location},le=()=>{throw new Error("useNavigate is removed. Use import { navigate } from 'gatsby' instead")},pe=()=>{const e=v();if(!e)throw new Error("useParams hook was used but a LocationContext.Provider was not found in the parent tree. Make sure this is used in a component that is a child of Router");const t=ue(),n=x(e.basepath,t.pathname);return n?n.params:null},fe=e=>{if(!e)throw new Error("useMatch(path: string) requires an argument of a string to match against");const t=v();if(!t)throw new Error("useMatch hook was used but a LocationContext.Provider was not found in the parent tree. Make sure this is used in a component that is a child of Router");const n=ue(),r=R(e,t.baseuri),o=x(r,n.pathname);return o?s({},o.params,{uri:o.uri,path:e}):null}},6491:function(e,t,n){"use strict";n.d(t,{X:function(){return a}});const r=new Map,o=new Map;function a(e){let t=r.get(e);return t||(t=o.get(e.toLowerCase())),t}[].forEach(e=>{e.ignoreCase?o.set(e.fromPath,e):r.set(e.fromPath,e)})},6498:function(e,t,n){"use strict";var r=n(7387),o=n(20),a=n(6540),i=n(6462),s=n(7035),c=n(7231),u=n(2024),l=n(6814),p=n(6491),f=n(9369);const d={id:"gatsby-announcer",style:{position:"absolute",top:0,width:1,height:1,padding:0,overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",border:0},"aria-live":"assertive","aria-atomic":"true"};var h=n(7078);function m(e){const t=(0,p.X)(e),{hash:n,search:r}=window.location;return null!=t&&(window.___replace(t.toPath+r+n),!0)}let g="";window.addEventListener("unhandledrejection",e=>{/loading chunk \d* failed./i.test(e.reason)&&g&&(window.location.pathname=g)});const y=(e,t)=>{m(e.pathname)||(g=e.pathname,(0,o.N)("onPreRouteUpdate",{location:e,prevLocation:t}))},v=(e,t)=>{m(e.pathname)||(0,o.N)("onRouteUpdate",{location:e,prevLocation:t})},b=function(e,t){if(void 0===t&&(t={}),"number"==typeof e)return void i.globalHistory.navigate(e);const{pathname:n,search:r,hash:a}=(0,h.Rr)(e),s=(0,p.X)(n);if(s&&(e=s.toPath+r+a),window.___swUpdated)return void(window.location=n+r+a);const c=setTimeout(()=>{f.A.emit("onDelayedLoadPageResources",{pathname:n}),(0,o.N)("onRouteUpdateDelayed",{location:window.location})},1e3);l.Ay.loadPage(n+r).then(o=>{if(!o||o.status===l.Wi.Error)return window.history.replaceState({},"",location.href),window.location=n,void clearTimeout(c);o&&o.page.webpackCompilationHash!==window.___webpackCompilationHash&&("serviceWorker"in navigator&&null!==navigator.serviceWorker.controller&&"activated"===navigator.serviceWorker.controller.state&&navigator.serviceWorker.controller.postMessage({gatsbyApi:"clearPathResources"}),window.location=n+r+a),(0,i.navigate)(e,t),clearTimeout(c)})};function w(e,t){let{location:n}=t;const{pathname:r,hash:a}=n,i=(0,o.N)("shouldUpdateScroll",{prevRouterProps:e,pathname:r,routerProps:{location:n},getSavedScrollPosition:e=>[0,this._stateStorage.read(e,e.key)]});if(i.length>0)return i[i.length-1];if(e){const{location:{pathname:t}}=e;if(t===r)return a?decodeURI(a.slice(1)):[0,0]}return!0}let S=function(e){function t(t){var n;return(n=e.call(this,t)||this).announcementRef=a.createRef(),n}(0,r.A)(t,e);var n=t.prototype;return n.componentDidUpdate=function(e,t){requestAnimationFrame(()=>{let e=`new page at ${this.props.location.pathname}`;document.title&&(e=document.title);const t=document.querySelectorAll("#gatsby-focus-wrapper h1");t&&t.length&&(e=t[0].textContent);const n=`Navigated to ${e}`;if(this.announcementRef.current){this.announcementRef.current.innerText!==n&&(this.announcementRef.current.innerText=n)}})},n.render=function(){return a.createElement("div",Object.assign({},d,{ref:this.announcementRef}))},t}(a.Component);const E=(e,t)=>{var n,r;return e.href!==t.href||(null==e||null===(n=e.state)||void 0===n?void 0:n.key)!==(null==t||null===(r=t.state)||void 0===r?void 0:r.key)};let C=function(e){function t(t){var n;return n=e.call(this,t)||this,y(t.location,null),n}(0,r.A)(t,e);var n=t.prototype;return n.componentDidMount=function(){v(this.props.location,null)},n.shouldComponentUpdate=function(e){return!!E(this.props.location,e.location)&&(y(e.location,this.props.location),!0)},n.componentDidUpdate=function(e){E(e.location,this.props.location)&&v(this.props.location,e.location)},n.render=function(){return a.createElement(a.Fragment,null,this.props.children,a.createElement(S,{location:location}))},t}(a.Component);var P=n(6017),k=n(6877);function _(e,t){for(var n in e)if(!(n in t))return!0;for(var r in t)if(e[r]!==t[r])return!0;return!1}var x=function(e){function t(t){var n;n=e.call(this)||this;const{location:r,pageResources:o}=t;return n.state={location:{...r},pageResources:o||l.Ay.loadPageSync(r.pathname+r.search,{withErrorDetails:!0})},n}(0,r.A)(t,e),t.getDerivedStateFromProps=function(e,t){let{location:n}=e;if(t.location.href!==n.href){return{pageResources:l.Ay.loadPageSync(n.pathname+n.search,{withErrorDetails:!0}),location:{...n}}}return{location:{...n}}};var n=t.prototype;return n.loadResources=function(e){l.Ay.loadPage(e).then(t=>{t&&t.status!==l.Wi.Error?this.setState({location:{...window.location},pageResources:t}):(window.history.replaceState({},"",location.href),window.location=e)})},n.shouldComponentUpdate=function(e,t){return t.pageResources?this.state.pageResources!==t.pageResources||(this.state.pageResources.component!==t.pageResources.component||(this.state.pageResources.json!==t.pageResources.json||(!(this.state.location.key===t.location.key||!t.pageResources.page||!t.pageResources.page.matchPath&&!t.pageResources.page.path)||function(e,t,n){return _(e.props,t)||_(e.state,n)}(this,e,t)))):(this.loadResources(e.location.pathname+e.location.search),!1)},n.render=function(){return this.props.children(this.state)},t}(a.Component),R=n(8797),O=n(9732);const A=new l.N5(k,[],window.pageData);(0,l.iC)(A),A.setApiRunner(o.N);const{render:T,hydrate:N}=(0,O.n)();window.asyncRequires=k,window.___emitter=f.A,window.___loader=l.Zf,i.globalHistory.listen(e=>{e.location.action=e.action}),window.___push=e=>b(e,{replace:!1}),window.___replace=e=>b(e,{replace:!0}),window.___navigate=(e,t)=>b(e,t);const j="gatsby-reload-compilation-hash-match";(0,o.v)("onClientEntry").then(()=>{(0,o.N)("registerServiceWorker").filter(Boolean).length>0&&n(626);const e=e=>a.createElement(i.BaseContext.Provider,{value:{baseuri:"/",basepath:"/"}},a.createElement(P.A,e)),t=a.createContext({}),p={renderEnvironment:"browser"};let f=function(e){function n(){return e.apply(this,arguments)||this}return(0,r.A)(n,e),n.prototype.render=function(){const{children:e}=this.props;return a.createElement(i.Location,null,n=>{let{location:r}=n;return a.createElement(x,{location:r},n=>{let{pageResources:r,location:o}=n;const i=(0,l.LE)(),s=(0,l.Rh)();return a.createElement(c.G.Provider,{value:i},a.createElement(u.j$.Provider,{value:p},a.createElement(u.dd.Provider,{value:s},a.createElement(u.Jr.Provider,{value:r.page.slicesMap},a.createElement(t.Provider,{value:{pageResources:r,location:o}},e)))))})})},n}(a.Component),d=function(n){function o(){return n.apply(this,arguments)||this}return(0,r.A)(o,n),o.prototype.render=function(){return a.createElement(t.Consumer,null,t=>{let{pageResources:n,location:r}=t;return a.createElement(C,{location:r},a.createElement(s.z_,{location:r,shouldUpdateScroll:w},a.createElement(i.Router,{basepath:"/npe",location:r,id:"gatsby-focus-wrapper"},a.createElement(e,Object.assign({path:"/404.html"===n.page.path||"/500.html"===n.page.path?(0,R.A)(r.pathname,"/npe"):encodeURI((n.page.matchPath||n.page.path).split("?")[0])},this.props,{location:r,pageResources:n},n.json)))))})},o}(a.Component);const{pagePath:h,location:m}=window;h&&"/npe"+h!==m.pathname+(h.includes("?")?m.search:"")&&!(A.findMatchPath((0,R.A)(m.pathname,"/npe"))||h.match(/^\/(404|500)(\/?|.html)$/)||h.match(/^\/offline-plugin-app-shell-fallback\/?$/))&&(0,i.navigate)("/npe"+h+(h.includes("?")?"":m.search)+m.hash,{replace:!0});const g=()=>{try{return sessionStorage}catch{return null}};l.Zf.loadPage(m.pathname+m.search).then(e=>{var t;const n=g();if(null!=e&&null!==(t=e.page)&&void 0!==t&&t.webpackCompilationHash&&e.page.webpackCompilationHash!==window.___webpackCompilationHash&&("serviceWorker"in navigator&&null!==navigator.serviceWorker.controller&&"activated"===navigator.serviceWorker.controller.state&&navigator.serviceWorker.controller.postMessage({gatsbyApi:"clearPathResources"}),n)){if(!("1"===n.getItem(j)))return n.setItem(j,"1"),void window.location.reload(!0)}if(n&&n.removeItem(j),!e||e.status===l.Wi.Error){const t=`page resources for ${m.pathname} not found. Not rendering React`;if(e&&e.error)throw console.error(t),e.error;throw new Error(t)}const r=(0,o.N)("wrapRootElement",{element:a.createElement(d,null)},a.createElement(d,null),e=>{let{result:t}=e;return{element:t}}).pop(),i=function(){const e=a.useRef(!1);return a.useEffect(()=>{e.current||(e.current=!0,performance.mark&&performance.mark("onInitialClientRender"),(0,o.N)("onInitialClientRender"))},[]),a.createElement(f,null,r)},s=document.getElementById("gatsby-focus-wrapper");let c=T;s&&s.children.length&&(c=N);const u=(0,o.N)("replaceHydrateFunction",void 0,c)[0];function p(){const e="undefined"!=typeof window?document.getElementById("___gatsby"):null;u(a.createElement(i,null),e)}const h=document;if("complete"===h.readyState||"loading"!==h.readyState&&!h.documentElement.doScroll)setTimeout(function(){p()},0);else{const e=function(){h.removeEventListener("DOMContentLoaded",e,!1),window.removeEventListener("load",e,!1),p()};h.addEventListener("DOMContentLoaded",e,!1),window.addEventListener("load",e,!1)}})})},6774:function(e,t){"use strict";var n=0,r=function(e){var t=window.decodeURI(e.replace("#",""));if(""!==t){var r=document.getElementById(t);if(r){var o=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop,a=document.documentElement.clientTop||document.body.clientTop||0,i=window.getComputedStyle(r),s=i.getPropertyValue("scroll-margin-top")||i.getPropertyValue("scroll-snap-margin-top")||"0px";return r.getBoundingClientRect().top+o-parseInt(s,10)-a-n}}return null};t.onInitialClientRender=function(e,t){t.offsetY&&(n=t.offsetY),requestAnimationFrame(function(){var e=r(window.location.hash);null!==e&&window.scrollTo(0,e)})},t.shouldUpdateScroll=function(e){var t=e.routerProps.location,n=r(t.hash);return null===n||[0,n]}},6814:function(e,t,n){"use strict";n.d(t,{Wi:function(){return p},N5:function(){return S},Ay:function(){return P},Rh:function(){return _},LE:function(){return k},Zf:function(){return C},iC:function(){return E}});var r=n(7387),o=n(4506),a=n(8163);const i=function(e){if("undefined"==typeof document)return!1;const t=document.createElement("link");try{if(t.relList&&"function"==typeof t.relList.supports)return t.relList.supports(e)}catch(n){return!1}return!1}("prefetch")?function(e,t){return new Promise((n,r)=>{if("undefined"==typeof document)return void r();const o=document.createElement("link");o.setAttribute("rel","prefetch"),o.setAttribute("href",e),Object.keys(t).forEach(e=>{o.setAttribute(e,t[e])}),o.onload=n,o.onerror=r;(document.getElementsByTagName("head")[0]||document.getElementsByName("script")[0].parentNode).appendChild(o)})}:function(e){return new Promise((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.onload=()=>{200===r.status?t():n()},r.send(null)})},s={};var c=function(e,t){return new Promise(n=>{s[e]?n():i(e,t).then(()=>{n(),s[e]=!0}).catch(()=>{})})},u=n(9369),l=n(8990);const p={Error:"error",Success:"success"},f=e=>{const[t,n]=e.split("?");var r;return`/npe/page-data/${"/"===t?"index":(r="/"===(r=t)[0]?r.slice(1):r).endsWith("/")?r.slice(0,-1):r}/page-data.json${n?`?${n}`:""}`},d=e=>e.startsWith("//");function h(e,t){return void 0===t&&(t="GET"),new Promise(n=>{const r=new XMLHttpRequest;r.open(t,e,!0),r.onreadystatechange=()=>{4==r.readyState&&n(r)},r.send(null)})}const m=/bot|crawler|spider|crawling/i,g=function(e,t,n){var r;void 0===t&&(t=null);const o={componentChunkName:e.componentChunkName,path:e.path,webpackCompilationHash:e.webpackCompilationHash,matchPath:e.matchPath,staticQueryHashes:e.staticQueryHashes,getServerDataError:e.getServerDataError,slicesMap:null!==(r=e.slicesMap)&&void 0!==r?r:{}};return{component:t,head:n,json:e.result,page:o}};function y(e){return new Promise(t=>{try{const n=e.readRoot();t(n)}catch(n){if(!Object.hasOwnProperty.call(n,"_response")||!Object.hasOwnProperty.call(n,"_status"))throw n;setTimeout(()=>{y(e).then(t)},200)}})}let v=function(){function e(e,t){this.inFlightNetworkRequests=new Map,this.pageDb=new Map,this.inFlightDb=new Map,this.staticQueryDb={},this.pageDataDb=new Map,this.partialHydrationDb=new Map,this.slicesDataDb=new Map,this.sliceInflightDb=new Map,this.slicesDb=new Map,this.isPrefetchQueueRunning=!1,this.prefetchQueued=[],this.prefetchTriggered=new Set,this.prefetchCompleted=new Set,this.loadComponent=e,(0,l.QX)(t)}var t=e.prototype;return t.memoizedGet=function(e){let t=this.inFlightNetworkRequests.get(e);return t||(t=h(e,"GET"),this.inFlightNetworkRequests.set(e,t)),t.then(t=>(this.inFlightNetworkRequests.delete(e),t)).catch(t=>{throw this.inFlightNetworkRequests.delete(e),t})},t.setApiRunner=function(e){this.apiRunner=e,this.prefetchDisabled=e("disableCorePrefetching").some(e=>e)},t.fetchPageDataJson=function(e){const{pagePath:t,retries:n=0}=e,r=f(t);return this.memoizedGet(r).then(r=>{const{status:o,responseText:a}=r;if(200===o)try{const n=JSON.parse(a);if(void 0===n.path)throw new Error("not a valid pageData response");const r=t.split("?")[1];return r&&!n.path.includes(r)&&(n.path+=`?${r}`),Object.assign(e,{status:p.Success,payload:n})}catch(i){}return 404===o||200===o?"/404.html"===t||"/500.html"===t?Object.assign(e,{status:p.Error}):this.fetchPageDataJson(Object.assign(e,{pagePath:"/404.html",notFound:!0})):500===o?this.fetchPageDataJson(Object.assign(e,{pagePath:"/500.html",internalServerError:!0})):n<3?this.fetchPageDataJson(Object.assign(e,{retries:n+1})):Object.assign(e,{status:p.Error})})},t.fetchPartialHydrationJson=function(e){const{pagePath:t,retries:n=0}=e,r=f(t).replace(".json","-rsc.json");return this.memoizedGet(r).then(r=>{const{status:o,responseText:a}=r;if(200===o)try{return Object.assign(e,{status:p.Success,payload:a})}catch(i){}return 404===o||200===o?"/404.html"===t||"/500.html"===t?Object.assign(e,{status:p.Error}):this.fetchPartialHydrationJson(Object.assign(e,{pagePath:"/404.html",notFound:!0})):500===o?this.fetchPartialHydrationJson(Object.assign(e,{pagePath:"/500.html",internalServerError:!0})):n<3?this.fetchPartialHydrationJson(Object.assign(e,{retries:n+1})):Object.assign(e,{status:p.Error})})},t.loadPageDataJson=function(e){const t=(0,l.Hh)(e);if(this.pageDataDb.has(t)){const e=this.pageDataDb.get(t);return Promise.resolve(e)}return this.fetchPageDataJson({pagePath:t}).then(e=>(this.pageDataDb.set(t,e),e))},t.loadPartialHydrationJson=function(e){const t=(0,l.Hh)(e);if(this.partialHydrationDb.has(t)){const e=this.partialHydrationDb.get(t);return Promise.resolve(e)}return this.fetchPartialHydrationJson({pagePath:t}).then(e=>(this.partialHydrationDb.set(t,e),e))},t.loadSliceDataJson=function(e){if(this.slicesDataDb.has(e)){const t=this.slicesDataDb.get(e);return Promise.resolve({sliceName:e,jsonPayload:t})}return h(`/npe/slice-data/${e}.json`,"GET").then(t=>{const n=JSON.parse(t.responseText);return this.slicesDataDb.set(e,n),{sliceName:e,jsonPayload:n}})},t.findMatchPath=function(e){return(0,l.Yl)(e)},t.loadPage=function(e){const t=(0,l.Hh)(e);if(this.pageDb.has(t)){const e=this.pageDb.get(t);return e.error?Promise.resolve({error:e.error,status:e.status}):Promise.resolve(e.payload)}if(this.inFlightDb.has(t))return this.inFlightDb.get(t);const n=[this.loadAppData(),this.loadPageDataJson(t)];const r=Promise.all(n).then(e=>{const[n,r,i]=e;if(r.status===p.Error||(null==i?void 0:i.status)===p.Error)return{status:p.Error};let s=r.payload;const{componentChunkName:c,staticQueryHashes:l=[],slicesMap:f={}}=s,d={},h=Array.from(new Set(Object.values(f))),m=e=>{if(this.slicesDb.has(e.name))return this.slicesDb.get(e.name);if(this.sliceInflightDb.has(e.name))return this.sliceInflightDb.get(e.name);const t=this.loadComponent(e.componentChunkName).then(t=>{return{component:(n=t,n&&n.default||n),sliceContext:e.result.sliceContext,data:e.result.data};var n});return this.sliceInflightDb.set(e.name,t),t.then(t=>{this.slicesDb.set(e.name,t),this.sliceInflightDb.delete(e.name)}),t};return Promise.all(h.map(e=>this.loadSliceDataJson(e))).then(e=>{const f=[],h=(0,o.A)(l);for(const{jsonPayload:t,sliceName:n}of Object.values(e)){f.push({name:n,...t});for(const e of t.staticQueryHashes)h.includes(e)||h.push(e)}const v=[Promise.all(f.map(m)),this.loadComponent(c,"head")];v.push(this.loadComponent(c));const b=Promise.all(v).then(e=>{const[t,o,c]=e;d.createdAt=new Date;for(const n of t)(!n||n instanceof Error)&&(d.status=p.Error,d.error=n);let u;if((!c||c instanceof Error)&&(d.status=p.Error,d.error=c),d.status!==p.Error){if(d.status=p.Success,!0!==r.notFound&&!0!==(null==i?void 0:i.notFound)||(d.notFound=!0),s=Object.assign(s,{webpackCompilationHash:n?n.webpackCompilationHash:""}),"string"==typeof(null==i?void 0:i.payload)){u=g(s,null,o),u.partialHydration=i.payload;const e=new ReadableStream({start(e){const t=new TextEncoder;e.enqueue(t.encode(i.payload))},pull(e){e.close()},cancel(){}});return y((0,a.createFromReadableStream)(e)).then(e=>(u.partialHydration=e,u))}u=g(s,c,o)}return u}),w=Promise.all(h.map(e=>{if(this.staticQueryDb[e]){const t=this.staticQueryDb[e];return{staticQueryHash:e,jsonPayload:t}}return this.memoizedGet(`/npe/page-data/sq/d/${e}.json`).then(t=>{const n=JSON.parse(t.responseText);return{staticQueryHash:e,jsonPayload:n}}).catch(()=>{throw new Error(`We couldn't load "/npe/page-data/sq/d/${e}.json"`)})})).then(e=>{const t={};return e.forEach(e=>{let{staticQueryHash:n,jsonPayload:r}=e;t[n]=r,this.staticQueryDb[n]=r}),t});return Promise.all([b,w]).then(e=>{let n,[r,o]=e;return r&&(n={...r,staticQueryResults:o},d.payload=n,u.A.emit("onPostLoadPageResources",{page:n,pageResources:n})),this.pageDb.set(t,d),d.error?{error:d.error,status:d.status}:n}).catch(e=>({error:e,status:p.Error}))})});return r.then(()=>{this.inFlightDb.delete(t)}).catch(e=>{throw this.inFlightDb.delete(t),e}),this.inFlightDb.set(t,r),r},t.loadPageSync=function(e,t){void 0===t&&(t={});const n=(0,l.Hh)(e);if(this.pageDb.has(n)){var r;const e=this.pageDb.get(n);if(e.payload)return e.payload;if(null!==(r=t)&&void 0!==r&&r.withErrorDetails)return{error:e.error,status:e.status}}},t.shouldPrefetch=function(e){return!!(()=>{if("connection"in navigator&&void 0!==navigator.connection){if((navigator.connection.effectiveType||"").includes("2g"))return!1;if(navigator.connection.saveData)return!1}return!0})()&&((!navigator.userAgent||!m.test(navigator.userAgent))&&!this.pageDb.has(e))},t.prefetch=function(e){if(!this.shouldPrefetch(e))return{then:e=>e(!1),abort:()=>{}};if(this.prefetchTriggered.has(e))return{then:e=>e(!0),abort:()=>{}};const t={resolve:null,reject:null,promise:null};t.promise=new Promise((e,n)=>{t.resolve=e,t.reject=n}),this.prefetchQueued.push([e,t]);const n=new AbortController;return n.signal.addEventListener("abort",()=>{const t=this.prefetchQueued.findIndex(t=>{let[n]=t;return n===e});-1!==t&&this.prefetchQueued.splice(t,1)}),this.isPrefetchQueueRunning||(this.isPrefetchQueueRunning=!0,setTimeout(()=>{this._processNextPrefetchBatch()},3e3)),{then:(e,n)=>t.promise.then(e,n),abort:n.abort.bind(n)}},t._processNextPrefetchBatch=function(){(window.requestIdleCallback||(e=>setTimeout(e,0)))(()=>{const e=this.prefetchQueued.splice(0,4),t=Promise.all(e.map(e=>{let[t,n]=e;return this.prefetchTriggered.has(t)||(this.apiRunner("onPrefetchPathname",{pathname:t}),this.prefetchTriggered.add(t)),this.prefetchDisabled?n.resolve(!1):this.doPrefetch((0,l.Hh)(t)).then(()=>{this.prefetchCompleted.has(t)||(this.apiRunner("onPostPrefetchPathname",{pathname:t}),this.prefetchCompleted.add(t)),n.resolve(!0)})}));this.prefetchQueued.length?t.then(()=>{setTimeout(()=>{this._processNextPrefetchBatch()},3e3)}):this.isPrefetchQueueRunning=!1})},t.doPrefetch=function(e){const t=f(e);return c(t,{crossOrigin:"anonymous",as:"fetch"}).then(()=>this.loadPageDataJson(e))},t.hovering=function(e){this.loadPage(e)},t.getResourceURLsForPathname=function(e){const t=(0,l.Hh)(e),n=this.pageDataDb.get(t);if(n){const e=g(n.payload);return[].concat((0,o.A)(b(e.page.componentChunkName)),[f(t)])}return null},t.isPageNotFound=function(e){const t=(0,l.Hh)(e),n=this.pageDb.get(t);return!n||n.notFound},t.loadAppData=function(e){return void 0===e&&(e=0),this.memoizedGet("/npe/page-data/app-data.json").then(t=>{const{status:n,responseText:r}=t;let o;if(200!==n&&e<3)return this.loadAppData(e+1);if(200===n)try{const e=JSON.parse(r);if(void 0===e.webpackCompilationHash)throw new Error("not a valid app-data response");o=e}catch(a){}return o})},e}();const b=e=>(window.___chunkMapping[e]||[]).map(e=>"/npe"+e);let w,S=function(e){function t(t,n,r){var o;return o=e.call(this,function(e,n){if(void 0===n&&(n="components"),!t[n="components"][e])throw new Error(`We couldn't find the correct component chunk with the name "${e}"`);return t[n][e]().catch(e=>e)},n)||this,r&&o.pageDataDb.set((0,l.Hh)(r.path),{pagePath:r.path,payload:r,status:"success"}),o}(0,r.A)(t,e);var n=t.prototype;return n.doPrefetch=function(t){return e.prototype.doPrefetch.call(this,t).then(e=>{if(e.status!==p.Success)return Promise.resolve();const t=e.payload,n=t.componentChunkName,r=b(n);return Promise.all(r.map(c)).then(()=>t)})},n.loadPageDataJson=function(t){return e.prototype.loadPageDataJson.call(this,t).then(e=>e.notFound?d(t)?e:h(t,"HEAD").then(t=>200===t.status?{status:p.Error}:e):e)},n.loadPartialHydrationJson=function(t){return e.prototype.loadPartialHydrationJson.call(this,t).then(e=>e.notFound?d(t)?e:h(t,"HEAD").then(t=>200===t.status?{status:p.Error}:e):e)},t}(v);const E=e=>{w=e},C={enqueue:e=>w.prefetch(e),getResourceURLsForPathname:e=>w.getResourceURLsForPathname(e),loadPage:e=>w.loadPage(e),loadPageSync:function(e,t){return void 0===t&&(t={}),w.loadPageSync(e,t)},prefetch:e=>w.prefetch(e),isPageNotFound:e=>w.isPageNotFound(e),hovering:e=>w.hovering(e),loadAppData:()=>w.loadAppData()};var P=C;function k(){return w?w.staticQueryDb:{}}function _(){return w?w.slicesDb:{}}},6877:function(e,t,n){t.components={"component---src-pages-404-jsx":()=>Promise.all([n.e(379),n.e(223),n.e(415)]).then(n.bind(n,3729)),"component---src-pages-about-jsx":()=>Promise.all([n.e(593),n.e(379),n.e(602),n.e(351),n.e(453),n.e(223),n.e(951),n.e(150),n.e(96)]).then(n.bind(n,2470)),"component---src-pages-index-jsx":()=>Promise.all([n.e(379),n.e(602),n.e(223),n.e(951),n.e(529),n.e(279)]).then(n.bind(n,7352)),"component---src-pages-search-jsx":()=>Promise.all([n.e(379),n.e(223),n.e(765)]).then(n.bind(n,7392)),"component---src-pages-series-jsx":()=>Promise.all([n.e(379),n.e(223),n.e(951),n.e(529),n.e(126)]).then(n.bind(n,5144)),"component---src-pages-tags-jsx":()=>Promise.all([n.e(379),n.e(223),n.e(951),n.e(529),n.e(898)]).then(n.bind(n,7989)),"component---src-templates-post-jsx":()=>Promise.all([n.e(593),n.e(379),n.e(602),n.e(351),n.e(453),n.e(223),n.e(951),n.e(150),n.e(240)]).then(n.bind(n,4256)),"component---src-templates-series-jsx":()=>Promise.all([n.e(379),n.e(223),n.e(249)]).then(n.bind(n,4689))}},7035:function(e,t,n){"use strict";t.RV=t.z_=void 0;var r=n(3215);t.z_=r.ScrollHandler;var o=n(3721);t.RV=o.useScrollRestoration},7078:function(e,t,n){"use strict";n.d(t,{Fe:function(){return d},N_:function(){return E},Rr:function(){return c},Zf:function(){return v},oo:function(){return C}});var r=n(5556),o=n(6540),a=n(6462),i=n(6395);function s(){return s=Object.assign?Object.assign.bind():function(e){for(var t=1;t{if("string"==typeof e)return!(e=>u.test(e))(e)},p=()=>"/npe",f=()=>"/npe";function d(e,t=p()){var n;if(!l(e))return e;if(e.startsWith("./")||e.startsWith("../"))return e;const r=null!=(n=null!=t?t:f())?n:"/";return`${null!=r&&r.endsWith("/")?r.slice(0,-1):r}${e.startsWith("/")?e:`/${e}`}`}const h=e=>null==e?void 0:e.startsWith("/");function m(e,t){const{pathname:n,search:r,hash:o}=c(e);return`${(0,i.T)(n,t)}${r}${o}`}const g=(e,t)=>"number"==typeof e?e:l(e)?h(e)?function(e){const t=d(e),n="always";return m(t,n)}(e):function(e,t){if(h(e))return e;const n="always",r=(0,a.resolve)(e,t);return m(r,n)}(e,t):e,y=["to","getProps","onClick","onMouseEnter","activeClassName","activeStyle","innerRef","partiallyActive","state","replace","_location"];function v(e){return d(e,f())}const b={activeClassName:r.string,activeStyle:r.object,partiallyActive:r.bool};function w(e){return o.createElement(a.Location,null,({location:t})=>o.createElement(S,s({},e,{_location:t})))}class S extends o.Component{constructor(e){super(e),this.defaultGetProps=({isPartiallyCurrent:e,isCurrent:t})=>(this.props.partiallyActive?e:t)?{className:[this.props.className,this.props.activeClassName].filter(Boolean).join(" "),style:s({},this.props.style,this.props.activeStyle)}:null;let t=!1;"undefined"!=typeof window&&window.IntersectionObserver&&(t=!0),this.state={IOSupported:t},this.abortPrefetch=null,this.handleRef=this.handleRef.bind(this)}_prefetch(){let e=window.location.pathname+window.location.search;this.props._location&&this.props._location.pathname&&(e=this.props._location.pathname+this.props._location.search);const t=c(g(this.props.to,e)),n=t.pathname+t.search;if(e!==n)return ___loader.enqueue(n)}componentWillUnmount(){if(!this.io)return;const{instance:e,el:t}=this.io;this.abortPrefetch&&this.abortPrefetch.abort(),e.unobserve(t),e.disconnect()}handleRef(e){this.props.innerRef&&Object.prototype.hasOwnProperty.call(this.props.innerRef,"current")?this.props.innerRef.current=e:this.props.innerRef&&this.props.innerRef(e),this.state.IOSupported&&e&&(this.io=((e,t)=>{const n=new window.IntersectionObserver(n=>{n.forEach(n=>{e===n.target&&t(n.isIntersecting||n.intersectionRatio>0)})});return n.observe(e),{instance:n,el:e}})(e,e=>{e?this.abortPrefetch=this._prefetch():this.abortPrefetch&&this.abortPrefetch.abort()}))}render(){const e=this.props,{to:t,getProps:n=this.defaultGetProps,onClick:r,onMouseEnter:i,state:u,replace:p,_location:f}=e,d=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,y),h=g(t,f.pathname);return l(h)?o.createElement(a.Link,s({to:h,state:u,getProps:n,innerRef:this.handleRef,onMouseEnter:e=>{i&&i(e);const t=c(h);___loader.hovering(t.pathname+t.search)},onClick:e=>{if(r&&r(e),!(0!==e.button||this.props.target||e.defaultPrevented||e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)){e.preventDefault();let t=p;const n=encodeURI(h)===f.pathname;"boolean"!=typeof p&&n&&(t=!0),window.___navigate(h,{state:u,replace:t})}return!0}},d)):o.createElement("a",s({href:h},d))}}S.propTypes=s({},b,{onClick:r.func,to:r.string.isRequired,replace:r.bool,state:r.object});const E=o.forwardRef((e,t)=>o.createElement(w,s({innerRef:t},e))),C=(e,t)=>{window.___navigate(g(e,window.location.pathname),t)}},7231:function(e,t,n){"use strict";n.d(t,{de:function(){return c},G:function(){return o},GR:function(){return u}});var r=n(6540);const o=(a="StaticQuery",i={},r.createServerContext?function(e,t){return void 0===t&&(t=null),globalThis.__SERVER_CONTEXT||(globalThis.__SERVER_CONTEXT={}),globalThis.__SERVER_CONTEXT[e]||(globalThis.__SERVER_CONTEXT[e]=r.createServerContext(e,t)),globalThis.__SERVER_CONTEXT[e]}(a,i):r.createContext(i));var a,i;function s(e){let{staticQueryData:t,data:n,query:o,render:a}=e;const i=n?n.data:t[o]&&t[o].data;return r.createElement(r.Fragment,null,i&&a(i),!i&&r.createElement("div",null,"Loading (StaticQuery)"))}const c=e=>{const{data:t,query:n,render:a,children:i}=e;return r.createElement(o.Consumer,null,e=>r.createElement(s,{data:t,query:n,render:a||i,staticQueryData:e}))},u=e=>{var t;r.useContext;const n=r.useContext(o);if(isNaN(Number(e)))throw new Error(`useStaticQuery was called with a string but expects to be called using \`graphql\`. Try this:\n\nimport { useStaticQuery, graphql } from 'gatsby';\n\nuseStaticQuery(graphql\`${e}\`);\n`);if(null!==(t=n[e])&&void 0!==t&&t.data)return n[e].data;throw new Error("The result of this StaticQuery could not be fetched.\n\nThis is likely a bug in Gatsby and if refreshing the page does not fix it, please open an issue in https://github.com/gatsbyjs/gatsby/issues")}},7387:function(e,t,n){"use strict";n.d(t,{A:function(){return o}});var r=n(3662);function o(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,(0,r.A)(e,t)}},7688:function(e,t){"use strict";t.DEFAULT_OPTIONS={maxWidth:650,wrapperStyle:"",backgroundColor:"white",linkImagesToOriginal:!0,showCaptions:!1,markdownCaptions:!1,withWebp:!1,withAvif:!1,tracedSVG:!1,loading:"lazy",decoding:"async",disableBgImageOnAlpha:!1,disableBgImage:!1},t.EMPTY_ALT="GATSBY_EMPTY_ALT",t.imageClass="gatsby-resp-image-image",t.imageWrapperClass="gatsby-resp-image-wrapper",t.imageBackgroundClass="gatsby-resp-image-background-image"},7914:function(e,t,n){"use strict";n.r(t),n.d(t,{onRouteUpdate:function(){return r}});n(4794),n(4598);const r=function(e,t){let{location:n}=e}},8108:function(e,t,n){n(2962)},8163:function(e,t,n){"use strict";e.exports=n(207)},8417:function(e,t,n){"use strict";function r(e){return"Minified Redux error #"+e+"; visit https://redux.js.org/Errors?code="+e+" for the full message or use the non-minified dev environment for full errors. "}n.r(t),n.d(t,{default:function(){return p}});var o="function"==typeof Symbol&&Symbol.observable||"@@observable",a=function(){return Math.random().toString(36).substring(7).split("").join(".")},i={INIT:"@@redux/INIT"+a(),REPLACE:"@@redux/REPLACE"+a(),PROBE_UNKNOWN_ACTION:function(){return"@@redux/PROBE_UNKNOWN_ACTION"+a()}};function s(e){if("object"!=typeof e||null===e)return!1;for(var t=e;null!==Object.getPrototypeOf(t);)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}function c(e,t,n){var a;if("function"==typeof t&&"function"==typeof n||"function"==typeof n&&"function"==typeof arguments[3])throw new Error(r(0));if("function"==typeof t&&void 0===n&&(n=t,t=void 0),void 0!==n){if("function"!=typeof n)throw new Error(r(1));return n(c)(e,t)}if("function"!=typeof e)throw new Error(r(2));var u=e,l=t,p=[],f=p,d=!1;function h(){f===p&&(f=p.slice())}function m(){if(d)throw new Error(r(3));return l}function g(e){if("function"!=typeof e)throw new Error(r(4));if(d)throw new Error(r(5));var t=!0;return h(),f.push(e),function(){if(t){if(d)throw new Error(r(6));t=!1,h();var n=f.indexOf(e);f.splice(n,1),p=null}}}function y(e){if(!s(e))throw new Error(r(7));if(void 0===e.type)throw new Error(r(8));if(d)throw new Error(r(9));try{d=!0,l=u(l,e)}finally{d=!1}for(var t=p=f,n=0;nc(l,e)},8493:function(e,t,n){"use strict";var r=n(6540);var o="function"==typeof Object.is?Object.is:function(e,t){return e===t&&(0!==e||1/e==1/t)||e!=e&&t!=t},a=r.useState,i=r.useEffect,s=r.useLayoutEffect,c=r.useDebugValue;function u(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!o(e,n)}catch(r){return!0}}var l="undefined"==typeof window||void 0===window.document||void 0===window.document.createElement?function(e,t){return t()}:function(e,t){var n=t(),r=a({inst:{value:n,getSnapshot:t}}),o=r[0].inst,l=r[1];return s(function(){o.value=n,o.getSnapshot=t,u(o)&&l({inst:o})},[e,n,t]),i(function(){return u(o)&&l({inst:o}),e(function(){u(o)&&l({inst:o})})},[e]),c(n),n};t.useSyncExternalStore=void 0!==r.useSyncExternalStore?r.useSyncExternalStore:l},8797:function(e,t,n){"use strict";function r(e,t){return void 0===t&&(t=""),t?e===t?"/":e.startsWith(`${t}/`)?e.slice(t.length):e:e}n.d(t,{A:function(){return r}})},8919:function(e,t){"use strict";t.__esModule=!0,t.DEFAULT_OPTIONS=t.SCRIPT_ELEMENT_ID=void 0;t.SCRIPT_ELEMENT_ID="redux-ssr";t.DEFAULT_OPTIONS={serialize:{space:0,isJSON:!0,unsafe:!1,ignoreFunction:!0},cleanupOnClient:!0,windowKey:"__PRELOADED_STATE__"}},8989:function(e,t){"use strict";var n,r=Symbol.for("react.element"),o=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),i=Symbol.for("react.strict_mode"),s=Symbol.for("react.profiler"),c=Symbol.for("react.provider"),u=Symbol.for("react.context"),l=Symbol.for("react.server_context"),p=Symbol.for("react.forward_ref"),f=Symbol.for("react.suspense"),d=Symbol.for("react.suspense_list"),h=Symbol.for("react.memo"),m=Symbol.for("react.lazy"),g=Symbol.for("react.offscreen");function y(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case r:switch(e=e.type){case a:case s:case i:case f:case d:return e;default:switch(e=e&&e.$$typeof){case l:case u:case p:case m:case h:case c:return e;default:return t}}case o:return t}}}n=Symbol.for("react.module.reference"),t.isContextConsumer=function(e){return y(e)===u}},8990:function(e,t,n){"use strict";n.d(t,{Yl:function(){return f},Hh:function(){return h},UA:function(){return d},QX:function(){return p}});var r=n(6462),o=n(8797),a=e=>{if(void 0===e)return e;let[t,n=""]=e.split("?");return n&&(n="?"+n),"/"===t?"/"+n:"/"===t.charAt(t.length-1)?t.slice(0,-1)+n:t+n},i=n(6491);const s=new Map;let c=[];const u=e=>{let t=e;if(-1!==e.indexOf("?")){const[n,r]=e.split("?");t=`${n}?${encodeURIComponent(r)}`}const n=decodeURIComponent(t);return(0,o.A)(n,decodeURIComponent("/npe")).split("#")[0]};function l(e){return e.startsWith("/")||e.startsWith("https://")||e.startsWith("http://")?e:new URL(e,window.location.href+(window.location.href.endsWith("/")?"":"/")).pathname}const p=e=>{c=e},f=e=>{const t=m(e),n=c.map(e=>{let{path:t,matchPath:n}=e;return{path:n,originalPath:t}}),o=(0,r.pick)(n,t);return o?a(o.route.originalPath):null},d=e=>{const t=m(e),n=c.map(e=>{let{path:t,matchPath:n}=e;return{path:n,originalPath:t}}),o=(0,r.pick)(n,t);return o?o.params:{}},h=e=>{const t=u(l(e));if(s.has(t))return s.get(t);const n=(0,i.X)(e);if(n)return h(n.toPath);let r=f(t);return r||(r=m(e)),s.set(t,r),r},m=e=>{let t=u(l(e));return"/index.html"===t&&(t="/"),t=a(t),t}},9242:function(e,t,n){"use strict";e.exports=n(2162)},9300:function(e,t,n){"use strict";t.__esModule=!0,t.injectPartytownSnippet=function(e){if(!e.length)return;const t=document.querySelector("script[data-partytown]"),n=document.querySelector('iframe[src*="~partytown/partytown-sandbox-sw"]');t&&t.remove();n&&n.remove();const a=(0,o.getForwards)(e),i=document.createElement("script");i.dataset.partytown="",i.innerHTML=(0,r.partytownSnippet)({forward:a}),document.head.appendChild(i)};var r=n(4656),o=n(3309)},9369:function(e,t,n){"use strict";n.d(t,{A:function(){return r}});var r=function(e){return e=e||Object.create(null),{on:function(t,n){(e[t]||(e[t]=[])).push(n)},off:function(t,n){e[t]&&e[t].splice(e[t].indexOf(n)>>>0,1)},emit:function(t,n){(e[t]||[]).slice().map(function(e){e(n)}),(e["*"]||[]).slice().map(function(e){e(t,n)})}}}()},9377:function(e,t,n){e.exports=[{plugin:n(3697),options:{plugins:[]}},{plugin:n(3785),options:{plugins:[],pathToCreateStoreModule:"./src/reducers/createStore",serialize:{space:0,isJSON:!0,unsafe:!1,ignoreFunction:!0},cleanupOnClient:!0,windowKey:"__PRELOADED_STATE__"}},{plugin:n(2039),options:{plugins:[],displayName:!0,fileName:!0,minify:!0,namespace:"",transpileTemplateLiterals:!0,topLevelImportPaths:[],pure:!1,disableVendorPrefixes:!1}},{plugin:n(7914),options:{plugins:[],name:"CATCH NPE",short_name:"CATCH NPE",description:"CATCH NPE tech blog",start_url:"/",background_color:"#ffffff",theme_color:"#ced4da",display:"standalone",icon:"static/favicon.png",legacy:!0,theme_color_in_head:!0,cache_busting_mode:"query",crossOrigin:"anonymous",include_favicon:!0,cacheDigest:"a3797e645e79b21302dc98c81ba92b2c"}},{plugin:n(5616),options:{plugins:[],maxWidth:680,loading:"lazy",wrapperStyle:"margin-bottom: 16px;",quality:100,showCaptions:!0,linkImagesToOriginal:!0,markdownCaptions:!1,backgroundColor:"white",withWebp:!1,withAvif:!1,decoding:"async",disableBgImageOnAlpha:!1,disableBgImage:!1}},{plugin:n(6774),options:{plugins:[],icon:'',className:"heading-anchor",maintainCase:!0,removeAccents:!0,elements:["h1","h2","h3","h4","h5","h6"],offsetY:0}},{plugin:n(8108),options:{plugins:[]}},{plugin:n(2311),options:{plugins:[]}}]},9732:function(e,t,n){"use strict";n.d(t,{n:function(){return o}});const r=new WeakMap;function o(){const e=n(5338);return{render:(t,n)=>{let o=r.get(n);o||r.set(n,o=e.createRoot(n)),o.render(t)},hydrate:(t,n)=>e.hydrateRoot(n,t)}}},9829:function(e,t,n){"use strict";n.d(t,{h:function(){return i},nA:function(){return s}});const r={theme:"light"},o="setLight",a="setDark",i={type:o,data:{theme:"light"}},s={type:a,data:{theme:"dark"}};t.Ay=function(e,t){switch(void 0===e&&(e=r),t.type){case o:return{...e,theme:"light"};case a:return{...e,theme:"dark"};default:return{...e}}}},9888:function(e,t,n){"use strict";e.exports=n(8493)}},function(e){e.O(0,[593,869],function(){return t=6498,e(e.s=t);var t});e.O()}]); -//# sourceMappingURL=app-6ad6b3ba41313fcc3e4a.js.map \ No newline at end of file diff --git a/public/app-6ad6b3ba41313fcc3e4a.js.LICENSE.txt b/public/app-6ad6b3ba41313fcc3e4a.js.LICENSE.txt deleted file mode 100644 index a2110cb..0000000 --- a/public/app-6ad6b3ba41313fcc3e4a.js.LICENSE.txt +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @license React - * react-is.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** - * @license React - * react-server-dom-webpack.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** - * @license React - * use-sync-external-store-shim.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** - * @license React - * use-sync-external-store-shim/with-selector.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -/** @license React v16.13.1 - * react-is.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ diff --git a/public/app-6ad6b3ba41313fcc3e4a.js.map b/public/app-6ad6b3ba41313fcc3e4a.js.map deleted file mode 100644 index a38c7d0..0000000 --- a/public/app-6ad6b3ba41313fcc3e4a.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"app-6ad6b3ba41313fcc3e4a.js","mappings":"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","sources":["webpack://gatsby-starter-hoodie/./.cache/api-runner-browser.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/utils/batch.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/components/Context.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/hooks/useReduxContext.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/utils/useSyncExternalStore.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/hooks/useSelector.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/extends.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/connect/selectorFactory.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/connect/wrapMapToProps.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/connect/invalidArgFactory.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/connect/mergeProps.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/utils/Subscription.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/utils/useIsomorphicLayoutEffect.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/utils/shallowEqual.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/components/connect.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/connect/mapStateToProps.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/connect/mapDispatchToProps.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/utils/bindActionCreators.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/components/Provider.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/hooks/useStore.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/hooks/useDispatch.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/es/index.js","webpack://gatsby-starter-hoodie/./node_modules/react-server-dom-webpack/cjs/react-server-dom-webpack.production.min.js","webpack://gatsby-starter-hoodie/./node_modules/invariant/browser.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-plugin-catch-links/node_modules/escape-string-regexp/index.js","webpack://gatsby-starter-hoodie/./.cache/register-service-worker.js","webpack://gatsby-starter-hoodie/./.cache/create-content-digest-browser-shim.js","webpack://gatsby-starter-hoodie/./.cache/public-page-renderer-prod.js","webpack://gatsby-starter-hoodie/./.cache/slice/context.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-plugin-styled-components/gatsby-browser.js","webpack://gatsby-starter-hoodie/./node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.production.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby/dist/internal-plugins/partytown/gatsby-browser.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/assertThisInitialized.js","webpack://gatsby-starter-hoodie/./.cache/public-page-renderer.js","webpack://gatsby-starter-hoodie/./node_modules/@emotion/stylis/dist/stylis.browser.esm.js","webpack://gatsby-starter-hoodie/./node_modules/@emotion/unitless/dist/unitless.browser.esm.js","webpack://gatsby-starter-hoodie/./node_modules/@emotion/memoize/dist/emotion-memoize.esm.js","webpack://gatsby-starter-hoodie/./node_modules/@emotion/is-prop-valid/dist/emotion-is-prop-valid.esm.js","webpack://gatsby-starter-hoodie/./node_modules/styled-components/dist/styled-components.browser.esm.js","webpack://gatsby-starter-hoodie/./node_modules/react-is/cjs/react-is.production.min.js","webpack://gatsby-starter-hoodie/./node_modules/shallowequal/index.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-react-router-scroll/scroll-handler.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby/dist/internal-plugins/partytown/utils/get-forwards.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-plugin-catch-links/catch-links.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-plugin-catch-links/gatsby-browser.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-react-router-scroll/use-scroll-restoration.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-plugin-react-redux/gatsby-browser.js","webpack://gatsby-starter-hoodie/./node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-react-router-scroll/session-storage.js","webpack://gatsby-starter-hoodie/./node_modules/react-is/index.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/toConsumableArray.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/iterableToArray.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-plugin-manifest/get-manifest-pathname.js","webpack://gatsby-starter-hoodie/./node_modules/@builder.io/partytown/integration/index.cjs","webpack://gatsby-starter-hoodie/./node_modules/react-redux/node_modules/react-is/index.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/wrapNativeSuper.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/isNativeFunction.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/construct.js","webpack://gatsby-starter-hoodie/./.cache/slice/server-slice-renderer.js","webpack://gatsby-starter-hoodie/./.cache/slice/server-slice.js","webpack://gatsby-starter-hoodie/./.cache/slice/inline-slice.js","webpack://gatsby-starter-hoodie/./.cache/slice.js","webpack://gatsby-starter-hoodie/./.cache/gatsby-browser-entry.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/interopRequireDefault.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-script/dist/index.modern.mjs","webpack://gatsby-starter-hoodie/./node_modules/gatsby-remark-images/gatsby-browser.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/setPrototypeOf.js","webpack://gatsby-starter-hoodie/./.cache/head/components/fire-callback-in-effect.js","webpack://gatsby-starter-hoodie/./.cache/head/constants.js","webpack://gatsby-starter-hoodie/./.cache/head/utils.js","webpack://gatsby-starter-hoodie/./.cache/head/head-export-handler-for-browser.js","webpack://gatsby-starter-hoodie/./.cache/page-renderer.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/inheritsLoose.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-plugin-react-redux/.tmp/createStore.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-page-utils/dist/apply-trailing-slash-option.js","webpack://gatsby-starter-hoodie/./node_modules/@gatsbyjs/reach-router/dist/index.modern.mjs","webpack://gatsby-starter-hoodie/./.cache/redirect-utils.js","webpack://gatsby-starter-hoodie/./.cache/route-announcer-props.js","webpack://gatsby-starter-hoodie/./.cache/navigation.js","webpack://gatsby-starter-hoodie/./node_modules/shallow-compare/es/index.js","webpack://gatsby-starter-hoodie/./.cache/ensure-resources.js","webpack://gatsby-starter-hoodie/./.cache/production-app.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-remark-autolink-headers/gatsby-browser.js","webpack://gatsby-starter-hoodie/./.cache/prefetch.js","webpack://gatsby-starter-hoodie/./.cache/loader.js","webpack://gatsby-starter-hoodie/./.cache/_this_is_virtual_fs_path_/$virtual/async-requires.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-react-router-scroll/index.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-link/dist/index.modern.mjs","webpack://gatsby-starter-hoodie/./.cache/static-query.js","webpack://gatsby-starter-hoodie/./.cache/context-utils.js","webpack://gatsby-starter-hoodie/./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-remark-images/constants.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-plugin-manifest/gatsby-browser.js","webpack://gatsby-starter-hoodie/./gatsby-browser.js","webpack://gatsby-starter-hoodie/./node_modules/react-server-dom-webpack/index.js","webpack://gatsby-starter-hoodie/./node_modules/redux/es/redux.js","webpack://gatsby-starter-hoodie/./src/reducers/index.js","webpack://gatsby-starter-hoodie/./src/reducers/createStore.js","webpack://gatsby-starter-hoodie/./node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js","webpack://gatsby-starter-hoodie/./.cache/strip-prefix.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby-plugin-react-redux/constants.js","webpack://gatsby-starter-hoodie/./node_modules/react-redux/node_modules/react-is/cjs/react-is.production.min.js","webpack://gatsby-starter-hoodie/./.cache/normalize-page-path.js","webpack://gatsby-starter-hoodie/./.cache/find-path.js","webpack://gatsby-starter-hoodie/./node_modules/use-sync-external-store/shim/with-selector.js","webpack://gatsby-starter-hoodie/./node_modules/gatsby/dist/internal-plugins/partytown/utils/inject-partytown-snippet.js","webpack://gatsby-starter-hoodie/./.cache/emitter.js","webpack://gatsby-starter-hoodie/./node_modules/mitt/dist/mitt.es.js","webpack://gatsby-starter-hoodie/./.cache/api-runner-browser-plugins.js","webpack://gatsby-starter-hoodie/./.cache/react-dom-utils.js","webpack://gatsby-starter-hoodie/./src/reducers/theme.js","webpack://gatsby-starter-hoodie/./node_modules/use-sync-external-store/shim/index.js"],"sourcesContent":["const plugins = require(`./api-runner-browser-plugins`)\nconst { getResourceURLsForPathname, loadPage, loadPageSync } =\n require(`./loader`).publicLoader\n\nexports.apiRunner = (api, args = {}, defaultReturn, argTransform) => {\n // Hooks for gatsby-cypress's API handler\n if (process.env.CYPRESS_SUPPORT) {\n if (window.___apiHandler) {\n window.___apiHandler(api)\n } else if (window.___resolvedAPIs) {\n window.___resolvedAPIs.push(api)\n } else {\n window.___resolvedAPIs = [api]\n }\n }\n\n let results = plugins.map(plugin => {\n if (!plugin.plugin[api]) {\n return undefined\n }\n\n args.getResourceURLsForPathname = getResourceURLsForPathname\n args.loadPage = loadPage\n args.loadPageSync = loadPageSync\n\n const result = plugin.plugin[api](args, plugin.options)\n if (result && argTransform) {\n args = argTransform({ args, result, plugin })\n }\n return result\n })\n\n // Filter out undefined results.\n results = results.filter(result => typeof result !== `undefined`)\n\n if (results.length > 0) {\n return results\n } else if (defaultReturn) {\n return [defaultReturn]\n } else {\n return []\n }\n}\n\nexports.apiRunnerAsync = (api, args, defaultReturn) =>\n plugins.reduce(\n (previous, next) =>\n next.plugin[api]\n ? previous.then(() => next.plugin[api](args, next.options))\n : previous,\n Promise.resolve()\n )\n","// Default to a dummy \"batch\" implementation that just runs the callback\nfunction defaultNoopBatch(callback) {\n callback();\n}\n\nlet batch = defaultNoopBatch; // Allow injecting another batching function later\n\nexport const setBatch = newBatch => batch = newBatch; // Supply a getter just to skip dealing with ESM bindings\n\nexport const getBatch = () => batch;","import * as React from 'react';\nconst ContextKey = Symbol.for(`react-redux-context`);\nconst gT = typeof globalThis !== \"undefined\" ? globalThis :\n/* fall back to a per-module scope (pre-8.1 behaviour) if `globalThis` is not available */\n{};\n\nfunction getContext() {\n var _gT$ContextKey;\n\n if (!React.createContext) return {};\n const contextMap = (_gT$ContextKey = gT[ContextKey]) != null ? _gT$ContextKey : gT[ContextKey] = new Map();\n let realContext = contextMap.get(React.createContext);\n\n if (!realContext) {\n realContext = React.createContext(null);\n\n if (process.env.NODE_ENV !== 'production') {\n realContext.displayName = 'ReactRedux';\n }\n\n contextMap.set(React.createContext, realContext);\n }\n\n return realContext;\n}\n\nexport const ReactReduxContext = /*#__PURE__*/getContext();\nexport default ReactReduxContext;","import { useContext } from 'react';\nimport { ReactReduxContext } from '../components/Context';\n\n/**\r\n * Hook factory, which creates a `useReduxContext` hook bound to a given context. This is a low-level\r\n * hook that you should usually not need to call directly.\r\n *\r\n * @param {React.Context} [context=ReactReduxContext] Context passed to your ``.\r\n * @returns {Function} A `useReduxContext` hook bound to the specified context.\r\n */\nexport function createReduxContextHook(context = ReactReduxContext) {\n return function useReduxContext() {\n const contextValue = useContext(context);\n\n if (process.env.NODE_ENV !== 'production' && !contextValue) {\n throw new Error('could not find react-redux context value; please ensure the component is wrapped in a ');\n }\n\n return contextValue;\n };\n}\n/**\r\n * A hook to access the value of the `ReactReduxContext`. This is a low-level\r\n * hook that you should usually not need to call directly.\r\n *\r\n * @returns {any} the value of the `ReactReduxContext`\r\n *\r\n * @example\r\n *\r\n * import React from 'react'\r\n * import { useReduxContext } from 'react-redux'\r\n *\r\n * export const CounterComponent = () => {\r\n * const { store } = useReduxContext()\r\n * return
{store.getState()}
\r\n * }\r\n */\n\nexport const useReduxContext = /*#__PURE__*/createReduxContextHook();","export const notInitialized = () => {\n throw new Error('uSES not initialized!');\n};","import { useCallback, useDebugValue, useRef } from 'react';\nimport { createReduxContextHook, useReduxContext as useDefaultReduxContext } from './useReduxContext';\nimport { ReactReduxContext } from '../components/Context';\nimport { notInitialized } from '../utils/useSyncExternalStore';\nlet useSyncExternalStoreWithSelector = notInitialized;\nexport const initializeUseSelector = fn => {\n useSyncExternalStoreWithSelector = fn;\n};\n\nconst refEquality = (a, b) => a === b;\n/**\r\n * Hook factory, which creates a `useSelector` hook bound to a given context.\r\n *\r\n * @param {React.Context} [context=ReactReduxContext] Context passed to your ``.\r\n * @returns {Function} A `useSelector` hook bound to the specified context.\r\n */\n\n\nexport function createSelectorHook(context = ReactReduxContext) {\n const useReduxContext = context === ReactReduxContext ? useDefaultReduxContext : createReduxContextHook(context);\n return function useSelector(selector, equalityFnOrOptions = {}) {\n const {\n equalityFn = refEquality,\n stabilityCheck = undefined,\n noopCheck = undefined\n } = typeof equalityFnOrOptions === 'function' ? {\n equalityFn: equalityFnOrOptions\n } : equalityFnOrOptions;\n\n if (process.env.NODE_ENV !== 'production') {\n if (!selector) {\n throw new Error(`You must pass a selector to useSelector`);\n }\n\n if (typeof selector !== 'function') {\n throw new Error(`You must pass a function as a selector to useSelector`);\n }\n\n if (typeof equalityFn !== 'function') {\n throw new Error(`You must pass a function as an equality function to useSelector`);\n }\n }\n\n const {\n store,\n subscription,\n getServerState,\n stabilityCheck: globalStabilityCheck,\n noopCheck: globalNoopCheck\n } = useReduxContext();\n const firstRun = useRef(true);\n const wrappedSelector = useCallback({\n [selector.name](state) {\n const selected = selector(state);\n\n if (process.env.NODE_ENV !== 'production') {\n const finalStabilityCheck = typeof stabilityCheck === 'undefined' ? globalStabilityCheck : stabilityCheck;\n\n if (finalStabilityCheck === 'always' || finalStabilityCheck === 'once' && firstRun.current) {\n const toCompare = selector(state);\n\n if (!equalityFn(selected, toCompare)) {\n let stack = undefined;\n\n try {\n throw new Error();\n } catch (e) {\n ;\n ({\n stack\n } = e);\n }\n\n console.warn('Selector ' + (selector.name || 'unknown') + ' returned a different result when called with the same parameters. This can lead to unnecessary rerenders.' + '\\nSelectors that return a new reference (such as an object or an array) should be memoized: https://redux.js.org/usage/deriving-data-selectors#optimizing-selectors-with-memoization', {\n state,\n selected,\n selected2: toCompare,\n stack\n });\n }\n }\n\n const finalNoopCheck = typeof noopCheck === 'undefined' ? globalNoopCheck : noopCheck;\n\n if (finalNoopCheck === 'always' || finalNoopCheck === 'once' && firstRun.current) {\n // @ts-ignore\n if (selected === state) {\n let stack = undefined;\n\n try {\n throw new Error();\n } catch (e) {\n ;\n ({\n stack\n } = e);\n }\n\n console.warn('Selector ' + (selector.name || 'unknown') + ' returned the root state when called. This can lead to unnecessary rerenders.' + '\\nSelectors that return the entire state are almost certainly a mistake, as they will cause a rerender whenever *anything* in state changes.', {\n stack\n });\n }\n }\n\n if (firstRun.current) firstRun.current = false;\n }\n\n return selected;\n }\n\n }[selector.name], [selector, globalStabilityCheck, stabilityCheck]);\n const selectedState = useSyncExternalStoreWithSelector(subscription.addNestedSub, store.getState, getServerState || store.getState, wrappedSelector, equalityFn);\n useDebugValue(selectedState);\n return selectedState;\n };\n}\n/**\r\n * A hook to access the redux store's state. This hook takes a selector function\r\n * as an argument. The selector is called with the store state.\r\n *\r\n * This hook takes an optional equality comparison function as the second parameter\r\n * that allows you to customize the way the selected state is compared to determine\r\n * whether the component needs to be re-rendered.\r\n *\r\n * @param {Function} selector the selector function\r\n * @param {Function=} equalityFn the function that will be used to determine equality\r\n *\r\n * @returns {any} the selected state\r\n *\r\n * @example\r\n *\r\n * import React from 'react'\r\n * import { useSelector } from 'react-redux'\r\n *\r\n * export const CounterComponent = () => {\r\n * const counter = useSelector(state => state.counter)\r\n * return
{counter}
\r\n * }\r\n */\n\nexport const useSelector = /*#__PURE__*/createSelectorHook();","function _extends() {\n return _extends = Object.assign ? Object.assign.bind() : function (n) {\n for (var e = 1; e < arguments.length; e++) {\n var t = arguments[e];\n for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);\n }\n return n;\n }, _extends.apply(null, arguments);\n}\nexport { _extends as default };","function _objectWithoutPropertiesLoose(r, e) {\n if (null == r) return {};\n var t = {};\n for (var n in r) if ({}.hasOwnProperty.call(r, n)) {\n if (-1 !== e.indexOf(n)) continue;\n t[n] = r[n];\n }\n return t;\n}\nexport { _objectWithoutPropertiesLoose as default };","import _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nconst _excluded = [\"initMapStateToProps\", \"initMapDispatchToProps\", \"initMergeProps\"];\nimport verifySubselectors from './verifySubselectors';\nexport function pureFinalPropsSelectorFactory(mapStateToProps, mapDispatchToProps, mergeProps, dispatch, {\n areStatesEqual,\n areOwnPropsEqual,\n areStatePropsEqual\n}) {\n let hasRunAtLeastOnce = false;\n let state;\n let ownProps;\n let stateProps;\n let dispatchProps;\n let mergedProps;\n\n function handleFirstCall(firstState, firstOwnProps) {\n state = firstState;\n ownProps = firstOwnProps;\n stateProps = mapStateToProps(state, ownProps);\n dispatchProps = mapDispatchToProps(dispatch, ownProps);\n mergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n hasRunAtLeastOnce = true;\n return mergedProps;\n }\n\n function handleNewPropsAndNewState() {\n stateProps = mapStateToProps(state, ownProps);\n if (mapDispatchToProps.dependsOnOwnProps) dispatchProps = mapDispatchToProps(dispatch, ownProps);\n mergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n return mergedProps;\n }\n\n function handleNewProps() {\n if (mapStateToProps.dependsOnOwnProps) stateProps = mapStateToProps(state, ownProps);\n if (mapDispatchToProps.dependsOnOwnProps) dispatchProps = mapDispatchToProps(dispatch, ownProps);\n mergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n return mergedProps;\n }\n\n function handleNewState() {\n const nextStateProps = mapStateToProps(state, ownProps);\n const statePropsChanged = !areStatePropsEqual(nextStateProps, stateProps);\n stateProps = nextStateProps;\n if (statePropsChanged) mergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n return mergedProps;\n }\n\n function handleSubsequentCalls(nextState, nextOwnProps) {\n const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps);\n const stateChanged = !areStatesEqual(nextState, state, nextOwnProps, ownProps);\n state = nextState;\n ownProps = nextOwnProps;\n if (propsChanged && stateChanged) return handleNewPropsAndNewState();\n if (propsChanged) return handleNewProps();\n if (stateChanged) return handleNewState();\n return mergedProps;\n }\n\n return function pureFinalPropsSelector(nextState, nextOwnProps) {\n return hasRunAtLeastOnce ? handleSubsequentCalls(nextState, nextOwnProps) : handleFirstCall(nextState, nextOwnProps);\n };\n}\n// TODO: Add more comments\n// The selector returned by selectorFactory will memoize its results,\n// allowing connect's shouldComponentUpdate to return false if final\n// props have not changed.\nexport default function finalPropsSelectorFactory(dispatch, _ref) {\n let {\n initMapStateToProps,\n initMapDispatchToProps,\n initMergeProps\n } = _ref,\n options = _objectWithoutPropertiesLoose(_ref, _excluded);\n\n const mapStateToProps = initMapStateToProps(dispatch, options);\n const mapDispatchToProps = initMapDispatchToProps(dispatch, options);\n const mergeProps = initMergeProps(dispatch, options);\n\n if (process.env.NODE_ENV !== 'production') {\n verifySubselectors(mapStateToProps, mapDispatchToProps, mergeProps);\n }\n\n return pureFinalPropsSelectorFactory(mapStateToProps, mapDispatchToProps, mergeProps, dispatch, options);\n}","import verifyPlainObject from '../utils/verifyPlainObject';\nexport function wrapMapToPropsConstant( // * Note:\n// It seems that the dispatch argument\n// could be a dispatch function in some cases (ex: whenMapDispatchToPropsIsMissing)\n// and a state object in some others (ex: whenMapStateToPropsIsMissing)\n// eslint-disable-next-line no-unused-vars\ngetConstant) {\n return function initConstantSelector(dispatch) {\n const constant = getConstant(dispatch);\n\n function constantSelector() {\n return constant;\n }\n\n constantSelector.dependsOnOwnProps = false;\n return constantSelector;\n };\n} // dependsOnOwnProps is used by createMapToPropsProxy to determine whether to pass props as args\n// to the mapToProps function being wrapped. It is also used by makePurePropsSelector to determine\n// whether mapToProps needs to be invoked when props have changed.\n//\n// A length of one signals that mapToProps does not depend on props from the parent component.\n// A length of zero is assumed to mean mapToProps is getting args via arguments or ...args and\n// therefore not reporting its length accurately..\n// TODO Can this get pulled out so that we can subscribe directly to the store if we don't need ownProps?\n\nexport function getDependsOnOwnProps(mapToProps) {\n return mapToProps.dependsOnOwnProps ? Boolean(mapToProps.dependsOnOwnProps) : mapToProps.length !== 1;\n} // Used by whenMapStateToPropsIsFunction and whenMapDispatchToPropsIsFunction,\n// this function wraps mapToProps in a proxy function which does several things:\n//\n// * Detects whether the mapToProps function being called depends on props, which\n// is used by selectorFactory to decide if it should reinvoke on props changes.\n//\n// * On first call, handles mapToProps if returns another function, and treats that\n// new function as the true mapToProps for subsequent calls.\n//\n// * On first call, verifies the first result is a plain object, in order to warn\n// the developer that their mapToProps function is not returning a valid result.\n//\n\nexport function wrapMapToPropsFunc(mapToProps, methodName) {\n return function initProxySelector(dispatch, {\n displayName\n }) {\n const proxy = function mapToPropsProxy(stateOrDispatch, ownProps) {\n return proxy.dependsOnOwnProps ? proxy.mapToProps(stateOrDispatch, ownProps) : proxy.mapToProps(stateOrDispatch, undefined);\n }; // allow detectFactoryAndVerify to get ownProps\n\n\n proxy.dependsOnOwnProps = true;\n\n proxy.mapToProps = function detectFactoryAndVerify(stateOrDispatch, ownProps) {\n proxy.mapToProps = mapToProps;\n proxy.dependsOnOwnProps = getDependsOnOwnProps(mapToProps);\n let props = proxy(stateOrDispatch, ownProps);\n\n if (typeof props === 'function') {\n proxy.mapToProps = props;\n proxy.dependsOnOwnProps = getDependsOnOwnProps(props);\n props = proxy(stateOrDispatch, ownProps);\n }\n\n if (process.env.NODE_ENV !== 'production') verifyPlainObject(props, displayName, methodName);\n return props;\n };\n\n return proxy;\n };\n}","export function createInvalidArgFactory(arg, name) {\n return (dispatch, options) => {\n throw new Error(`Invalid value of type ${typeof arg} for ${name} argument when connecting component ${options.wrappedComponentName}.`);\n };\n}","import _extends from \"@babel/runtime/helpers/esm/extends\";\nimport verifyPlainObject from '../utils/verifyPlainObject';\nimport { createInvalidArgFactory } from './invalidArgFactory';\nexport function defaultMergeProps(stateProps, dispatchProps, ownProps) {\n // @ts-ignore\n return _extends({}, ownProps, stateProps, dispatchProps);\n}\nexport function wrapMergePropsFunc(mergeProps) {\n return function initMergePropsProxy(dispatch, {\n displayName,\n areMergedPropsEqual\n }) {\n let hasRunOnce = false;\n let mergedProps;\n return function mergePropsProxy(stateProps, dispatchProps, ownProps) {\n const nextMergedProps = mergeProps(stateProps, dispatchProps, ownProps);\n\n if (hasRunOnce) {\n if (!areMergedPropsEqual(nextMergedProps, mergedProps)) mergedProps = nextMergedProps;\n } else {\n hasRunOnce = true;\n mergedProps = nextMergedProps;\n if (process.env.NODE_ENV !== 'production') verifyPlainObject(mergedProps, displayName, 'mergeProps');\n }\n\n return mergedProps;\n };\n };\n}\nexport function mergePropsFactory(mergeProps) {\n return !mergeProps ? () => defaultMergeProps : typeof mergeProps === 'function' ? wrapMergePropsFunc(mergeProps) : createInvalidArgFactory(mergeProps, 'mergeProps');\n}","import { getBatch } from './batch'; // encapsulates the subscription logic for connecting a component to the redux store, as\n// well as nesting subscriptions of descendant components, so that we can ensure the\n// ancestor components re-render before descendants\n\nfunction createListenerCollection() {\n const batch = getBatch();\n let first = null;\n let last = null;\n return {\n clear() {\n first = null;\n last = null;\n },\n\n notify() {\n batch(() => {\n let listener = first;\n\n while (listener) {\n listener.callback();\n listener = listener.next;\n }\n });\n },\n\n get() {\n let listeners = [];\n let listener = first;\n\n while (listener) {\n listeners.push(listener);\n listener = listener.next;\n }\n\n return listeners;\n },\n\n subscribe(callback) {\n let isSubscribed = true;\n let listener = last = {\n callback,\n next: null,\n prev: last\n };\n\n if (listener.prev) {\n listener.prev.next = listener;\n } else {\n first = listener;\n }\n\n return function unsubscribe() {\n if (!isSubscribed || first === null) return;\n isSubscribed = false;\n\n if (listener.next) {\n listener.next.prev = listener.prev;\n } else {\n last = listener.prev;\n }\n\n if (listener.prev) {\n listener.prev.next = listener.next;\n } else {\n first = listener.next;\n }\n };\n }\n\n };\n}\n\nconst nullListeners = {\n notify() {},\n\n get: () => []\n};\nexport function createSubscription(store, parentSub) {\n let unsubscribe;\n let listeners = nullListeners; // Reasons to keep the subscription active\n\n let subscriptionsAmount = 0; // Is this specific subscription subscribed (or only nested ones?)\n\n let selfSubscribed = false;\n\n function addNestedSub(listener) {\n trySubscribe();\n const cleanupListener = listeners.subscribe(listener); // cleanup nested sub\n\n let removed = false;\n return () => {\n if (!removed) {\n removed = true;\n cleanupListener();\n tryUnsubscribe();\n }\n };\n }\n\n function notifyNestedSubs() {\n listeners.notify();\n }\n\n function handleChangeWrapper() {\n if (subscription.onStateChange) {\n subscription.onStateChange();\n }\n }\n\n function isSubscribed() {\n return selfSubscribed;\n }\n\n function trySubscribe() {\n subscriptionsAmount++;\n\n if (!unsubscribe) {\n unsubscribe = parentSub ? parentSub.addNestedSub(handleChangeWrapper) : store.subscribe(handleChangeWrapper);\n listeners = createListenerCollection();\n }\n }\n\n function tryUnsubscribe() {\n subscriptionsAmount--;\n\n if (unsubscribe && subscriptionsAmount === 0) {\n unsubscribe();\n unsubscribe = undefined;\n listeners.clear();\n listeners = nullListeners;\n }\n }\n\n function trySubscribeSelf() {\n if (!selfSubscribed) {\n selfSubscribed = true;\n trySubscribe();\n }\n }\n\n function tryUnsubscribeSelf() {\n if (selfSubscribed) {\n selfSubscribed = false;\n tryUnsubscribe();\n }\n }\n\n const subscription = {\n addNestedSub,\n notifyNestedSubs,\n handleChangeWrapper,\n isSubscribed,\n trySubscribe: trySubscribeSelf,\n tryUnsubscribe: tryUnsubscribeSelf,\n getListeners: () => listeners\n };\n return subscription;\n}","import * as React from 'react'; // React currently throws a warning when using useLayoutEffect on the server.\n// To get around it, we can conditionally useEffect on the server (no-op) and\n// useLayoutEffect in the browser. We need useLayoutEffect to ensure the store\n// subscription callback always has the selector from the latest render commit\n// available, otherwise a store update may happen between render and the effect,\n// which may cause missed updates; we also must ensure the store subscription\n// is created synchronously, otherwise a store update may occur before the\n// subscription is created and an inconsistent state may be observed\n// Matches logic in React's `shared/ExecutionEnvironment` file\n\nexport const canUseDOM = !!(typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined');\nexport const useIsomorphicLayoutEffect = canUseDOM ? React.useLayoutEffect : React.useEffect;","function is(x, y) {\n if (x === y) {\n return x !== 0 || y !== 0 || 1 / x === 1 / y;\n } else {\n return x !== x && y !== y;\n }\n}\n\nexport default function shallowEqual(objA, objB) {\n if (is(objA, objB)) return true;\n\n if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {\n return false;\n }\n\n const keysA = Object.keys(objA);\n const keysB = Object.keys(objB);\n if (keysA.length !== keysB.length) return false;\n\n for (let i = 0; i < keysA.length; i++) {\n if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {\n return false;\n }\n }\n\n return true;\n}","import _extends from \"@babel/runtime/helpers/esm/extends\";\nimport _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nconst _excluded = [\"reactReduxForwardedRef\"];\n\n/* eslint-disable valid-jsdoc, @typescript-eslint/no-unused-vars */\nimport hoistStatics from 'hoist-non-react-statics';\nimport * as React from 'react';\nimport { isValidElementType, isContextConsumer } from 'react-is';\nimport defaultSelectorFactory from '../connect/selectorFactory';\nimport { mapDispatchToPropsFactory } from '../connect/mapDispatchToProps';\nimport { mapStateToPropsFactory } from '../connect/mapStateToProps';\nimport { mergePropsFactory } from '../connect/mergeProps';\nimport { createSubscription } from '../utils/Subscription';\nimport { useIsomorphicLayoutEffect } from '../utils/useIsomorphicLayoutEffect';\nimport shallowEqual from '../utils/shallowEqual';\nimport warning from '../utils/warning';\nimport { ReactReduxContext } from './Context';\nimport { notInitialized } from '../utils/useSyncExternalStore';\nlet useSyncExternalStore = notInitialized;\nexport const initializeConnect = fn => {\n useSyncExternalStore = fn;\n}; // Define some constant arrays just to avoid re-creating these\n\nconst EMPTY_ARRAY = [null, 0];\nconst NO_SUBSCRIPTION_ARRAY = [null, null]; // Attempts to stringify whatever not-really-a-component value we were given\n// for logging in an error message\n\nconst stringifyComponent = Comp => {\n try {\n return JSON.stringify(Comp);\n } catch (err) {\n return String(Comp);\n }\n};\n\n// This is \"just\" a `useLayoutEffect`, but with two modifications:\n// - we need to fall back to `useEffect` in SSR to avoid annoying warnings\n// - we extract this to a separate function to avoid closing over values\n// and causing memory leaks\nfunction useIsomorphicLayoutEffectWithArgs(effectFunc, effectArgs, dependencies) {\n useIsomorphicLayoutEffect(() => effectFunc(...effectArgs), dependencies);\n} // Effect callback, extracted: assign the latest props values to refs for later usage\n\n\nfunction captureWrapperProps(lastWrapperProps, lastChildProps, renderIsScheduled, wrapperProps, // actualChildProps: unknown,\nchildPropsFromStoreUpdate, notifyNestedSubs) {\n // We want to capture the wrapper props and child props we used for later comparisons\n lastWrapperProps.current = wrapperProps;\n renderIsScheduled.current = false; // If the render was from a store update, clear out that reference and cascade the subscriber update\n\n if (childPropsFromStoreUpdate.current) {\n childPropsFromStoreUpdate.current = null;\n notifyNestedSubs();\n }\n} // Effect callback, extracted: subscribe to the Redux store or nearest connected ancestor,\n// check for updates after dispatched actions, and trigger re-renders.\n\n\nfunction subscribeUpdates(shouldHandleStateChanges, store, subscription, childPropsSelector, lastWrapperProps, lastChildProps, renderIsScheduled, isMounted, childPropsFromStoreUpdate, notifyNestedSubs, // forceComponentUpdateDispatch: React.Dispatch,\nadditionalSubscribeListener) {\n // If we're not subscribed to the store, nothing to do here\n if (!shouldHandleStateChanges) return () => {}; // Capture values for checking if and when this component unmounts\n\n let didUnsubscribe = false;\n let lastThrownError = null; // We'll run this callback every time a store subscription update propagates to this component\n\n const checkForUpdates = () => {\n if (didUnsubscribe || !isMounted.current) {\n // Don't run stale listeners.\n // Redux doesn't guarantee unsubscriptions happen until next dispatch.\n return;\n } // TODO We're currently calling getState ourselves here, rather than letting `uSES` do it\n\n\n const latestStoreState = store.getState();\n let newChildProps, error;\n\n try {\n // Actually run the selector with the most recent store state and wrapper props\n // to determine what the child props should be\n newChildProps = childPropsSelector(latestStoreState, lastWrapperProps.current);\n } catch (e) {\n error = e;\n lastThrownError = e;\n }\n\n if (!error) {\n lastThrownError = null;\n } // If the child props haven't changed, nothing to do here - cascade the subscription update\n\n\n if (newChildProps === lastChildProps.current) {\n if (!renderIsScheduled.current) {\n notifyNestedSubs();\n }\n } else {\n // Save references to the new child props. Note that we track the \"child props from store update\"\n // as a ref instead of a useState/useReducer because we need a way to determine if that value has\n // been processed. If this went into useState/useReducer, we couldn't clear out the value without\n // forcing another re-render, which we don't want.\n lastChildProps.current = newChildProps;\n childPropsFromStoreUpdate.current = newChildProps;\n renderIsScheduled.current = true; // TODO This is hacky and not how `uSES` is meant to be used\n // Trigger the React `useSyncExternalStore` subscriber\n\n additionalSubscribeListener();\n }\n }; // Actually subscribe to the nearest connected ancestor (or store)\n\n\n subscription.onStateChange = checkForUpdates;\n subscription.trySubscribe(); // Pull data from the store after first render in case the store has\n // changed since we began.\n\n checkForUpdates();\n\n const unsubscribeWrapper = () => {\n didUnsubscribe = true;\n subscription.tryUnsubscribe();\n subscription.onStateChange = null;\n\n if (lastThrownError) {\n // It's possible that we caught an error due to a bad mapState function, but the\n // parent re-rendered without this component and we're about to unmount.\n // This shouldn't happen as long as we do top-down subscriptions correctly, but\n // if we ever do those wrong, this throw will surface the error in our tests.\n // In that case, throw the error from here so it doesn't get lost.\n throw lastThrownError;\n }\n };\n\n return unsubscribeWrapper;\n} // Reducer initial state creation for our update reducer\n\n\nconst initStateUpdates = () => EMPTY_ARRAY;\n\nfunction strictEqual(a, b) {\n return a === b;\n}\n/**\r\n * Infers the type of props that a connector will inject into a component.\r\n */\n\n\nlet hasWarnedAboutDeprecatedPureOption = false;\n/**\r\n * Connects a React component to a Redux store.\r\n *\r\n * - Without arguments, just wraps the component, without changing the behavior / props\r\n *\r\n * - If 2 params are passed (3rd param, mergeProps, is skipped), default behavior\r\n * is to override ownProps (as stated in the docs), so what remains is everything that's\r\n * not a state or dispatch prop\r\n *\r\n * - When 3rd param is passed, we don't know if ownProps propagate and whether they\r\n * should be valid component props, because it depends on mergeProps implementation.\r\n * As such, it is the user's responsibility to extend ownProps interface from state or\r\n * dispatch props or both when applicable\r\n *\r\n * @param mapStateToProps A function that extracts values from state\r\n * @param mapDispatchToProps Setup for dispatching actions\r\n * @param mergeProps Optional callback to merge state and dispatch props together\r\n * @param options Options for configuring the connection\r\n *\r\n */\n\nfunction connect(mapStateToProps, mapDispatchToProps, mergeProps, {\n // The `pure` option has been removed, so TS doesn't like us destructuring this to check its existence.\n // @ts-ignore\n pure,\n areStatesEqual = strictEqual,\n areOwnPropsEqual = shallowEqual,\n areStatePropsEqual = shallowEqual,\n areMergedPropsEqual = shallowEqual,\n // use React's forwardRef to expose a ref of the wrapped component\n forwardRef = false,\n // the context consumer to use\n context = ReactReduxContext\n} = {}) {\n if (process.env.NODE_ENV !== 'production') {\n if (pure !== undefined && !hasWarnedAboutDeprecatedPureOption) {\n hasWarnedAboutDeprecatedPureOption = true;\n warning('The `pure` option has been removed. `connect` is now always a \"pure/memoized\" component');\n }\n }\n\n const Context = context;\n const initMapStateToProps = mapStateToPropsFactory(mapStateToProps);\n const initMapDispatchToProps = mapDispatchToPropsFactory(mapDispatchToProps);\n const initMergeProps = mergePropsFactory(mergeProps);\n const shouldHandleStateChanges = Boolean(mapStateToProps);\n\n const wrapWithConnect = WrappedComponent => {\n if (process.env.NODE_ENV !== 'production' && !isValidElementType(WrappedComponent)) {\n throw new Error(`You must pass a component to the function returned by connect. Instead received ${stringifyComponent(WrappedComponent)}`);\n }\n\n const wrappedComponentName = WrappedComponent.displayName || WrappedComponent.name || 'Component';\n const displayName = `Connect(${wrappedComponentName})`;\n const selectorFactoryOptions = {\n shouldHandleStateChanges,\n displayName,\n wrappedComponentName,\n WrappedComponent,\n // @ts-ignore\n initMapStateToProps,\n // @ts-ignore\n initMapDispatchToProps,\n initMergeProps,\n areStatesEqual,\n areStatePropsEqual,\n areOwnPropsEqual,\n areMergedPropsEqual\n };\n\n function ConnectFunction(props) {\n const [propsContext, reactReduxForwardedRef, wrapperProps] = React.useMemo(() => {\n // Distinguish between actual \"data\" props that were passed to the wrapper component,\n // and values needed to control behavior (forwarded refs, alternate context instances).\n // To maintain the wrapperProps object reference, memoize this destructuring.\n const {\n reactReduxForwardedRef\n } = props,\n wrapperProps = _objectWithoutPropertiesLoose(props, _excluded);\n\n return [props.context, reactReduxForwardedRef, wrapperProps];\n }, [props]);\n const ContextToUse = React.useMemo(() => {\n // Users may optionally pass in a custom context instance to use instead of our ReactReduxContext.\n // Memoize the check that determines which context instance we should use.\n return propsContext && propsContext.Consumer && // @ts-ignore\n isContextConsumer( /*#__PURE__*/React.createElement(propsContext.Consumer, null)) ? propsContext : Context;\n }, [propsContext, Context]); // Retrieve the store and ancestor subscription via context, if available\n\n const contextValue = React.useContext(ContextToUse); // The store _must_ exist as either a prop or in context.\n // We'll check to see if it _looks_ like a Redux store first.\n // This allows us to pass through a `store` prop that is just a plain value.\n\n const didStoreComeFromProps = Boolean(props.store) && Boolean(props.store.getState) && Boolean(props.store.dispatch);\n const didStoreComeFromContext = Boolean(contextValue) && Boolean(contextValue.store);\n\n if (process.env.NODE_ENV !== 'production' && !didStoreComeFromProps && !didStoreComeFromContext) {\n throw new Error(`Could not find \"store\" in the context of ` + `\"${displayName}\". Either wrap the root component in a , ` + `or pass a custom React context provider to and the corresponding ` + `React context consumer to ${displayName} in connect options.`);\n } // Based on the previous check, one of these must be true\n\n\n const store = didStoreComeFromProps ? props.store : contextValue.store;\n const getServerState = didStoreComeFromContext ? contextValue.getServerState : store.getState;\n const childPropsSelector = React.useMemo(() => {\n // The child props selector needs the store reference as an input.\n // Re-create this selector whenever the store changes.\n return defaultSelectorFactory(store.dispatch, selectorFactoryOptions);\n }, [store]);\n const [subscription, notifyNestedSubs] = React.useMemo(() => {\n if (!shouldHandleStateChanges) return NO_SUBSCRIPTION_ARRAY; // This Subscription's source should match where store came from: props vs. context. A component\n // connected to the store via props shouldn't use subscription from context, or vice versa.\n\n const subscription = createSubscription(store, didStoreComeFromProps ? undefined : contextValue.subscription); // `notifyNestedSubs` is duplicated to handle the case where the component is unmounted in\n // the middle of the notification loop, where `subscription` will then be null. This can\n // probably be avoided if Subscription's listeners logic is changed to not call listeners\n // that have been unsubscribed in the middle of the notification loop.\n\n const notifyNestedSubs = subscription.notifyNestedSubs.bind(subscription);\n return [subscription, notifyNestedSubs];\n }, [store, didStoreComeFromProps, contextValue]); // Determine what {store, subscription} value should be put into nested context, if necessary,\n // and memoize that value to avoid unnecessary context updates.\n\n const overriddenContextValue = React.useMemo(() => {\n if (didStoreComeFromProps) {\n // This component is directly subscribed to a store from props.\n // We don't want descendants reading from this store - pass down whatever\n // the existing context value is from the nearest connected ancestor.\n return contextValue;\n } // Otherwise, put this component's subscription instance into context, so that\n // connected descendants won't update until after this component is done\n\n\n return _extends({}, contextValue, {\n subscription\n });\n }, [didStoreComeFromProps, contextValue, subscription]); // Set up refs to coordinate values between the subscription effect and the render logic\n\n const lastChildProps = React.useRef();\n const lastWrapperProps = React.useRef(wrapperProps);\n const childPropsFromStoreUpdate = React.useRef();\n const renderIsScheduled = React.useRef(false);\n const isProcessingDispatch = React.useRef(false);\n const isMounted = React.useRef(false);\n const latestSubscriptionCallbackError = React.useRef();\n useIsomorphicLayoutEffect(() => {\n isMounted.current = true;\n return () => {\n isMounted.current = false;\n };\n }, []);\n const actualChildPropsSelector = React.useMemo(() => {\n const selector = () => {\n // Tricky logic here:\n // - This render may have been triggered by a Redux store update that produced new child props\n // - However, we may have gotten new wrapper props after that\n // If we have new child props, and the same wrapper props, we know we should use the new child props as-is.\n // But, if we have new wrapper props, those might change the child props, so we have to recalculate things.\n // So, we'll use the child props from store update only if the wrapper props are the same as last time.\n if (childPropsFromStoreUpdate.current && wrapperProps === lastWrapperProps.current) {\n return childPropsFromStoreUpdate.current;\n } // TODO We're reading the store directly in render() here. Bad idea?\n // This will likely cause Bad Things (TM) to happen in Concurrent Mode.\n // Note that we do this because on renders _not_ caused by store updates, we need the latest store state\n // to determine what the child props should be.\n\n\n return childPropsSelector(store.getState(), wrapperProps);\n };\n\n return selector;\n }, [store, wrapperProps]); // We need this to execute synchronously every time we re-render. However, React warns\n // about useLayoutEffect in SSR, so we try to detect environment and fall back to\n // just useEffect instead to avoid the warning, since neither will run anyway.\n\n const subscribeForReact = React.useMemo(() => {\n const subscribe = reactListener => {\n if (!subscription) {\n return () => {};\n }\n\n return subscribeUpdates(shouldHandleStateChanges, store, subscription, // @ts-ignore\n childPropsSelector, lastWrapperProps, lastChildProps, renderIsScheduled, isMounted, childPropsFromStoreUpdate, notifyNestedSubs, reactListener);\n };\n\n return subscribe;\n }, [subscription]);\n useIsomorphicLayoutEffectWithArgs(captureWrapperProps, [lastWrapperProps, lastChildProps, renderIsScheduled, wrapperProps, childPropsFromStoreUpdate, notifyNestedSubs]);\n let actualChildProps;\n\n try {\n actualChildProps = useSyncExternalStore( // TODO We're passing through a big wrapper that does a bunch of extra side effects besides subscribing\n subscribeForReact, // TODO This is incredibly hacky. We've already processed the store update and calculated new child props,\n // TODO and we're just passing that through so it triggers a re-render for us rather than relying on `uSES`.\n actualChildPropsSelector, getServerState ? () => childPropsSelector(getServerState(), wrapperProps) : actualChildPropsSelector);\n } catch (err) {\n if (latestSubscriptionCallbackError.current) {\n ;\n err.message += `\\nThe error may be correlated with this previous error:\\n${latestSubscriptionCallbackError.current.stack}\\n\\n`;\n }\n\n throw err;\n }\n\n useIsomorphicLayoutEffect(() => {\n latestSubscriptionCallbackError.current = undefined;\n childPropsFromStoreUpdate.current = undefined;\n lastChildProps.current = actualChildProps;\n }); // Now that all that's done, we can finally try to actually render the child component.\n // We memoize the elements for the rendered child component as an optimization.\n\n const renderedWrappedComponent = React.useMemo(() => {\n return (\n /*#__PURE__*/\n // @ts-ignore\n React.createElement(WrappedComponent, _extends({}, actualChildProps, {\n ref: reactReduxForwardedRef\n }))\n );\n }, [reactReduxForwardedRef, WrappedComponent, actualChildProps]); // If React sees the exact same element reference as last time, it bails out of re-rendering\n // that child, same as if it was wrapped in React.memo() or returned false from shouldComponentUpdate.\n\n const renderedChild = React.useMemo(() => {\n if (shouldHandleStateChanges) {\n // If this component is subscribed to store updates, we need to pass its own\n // subscription instance down to our descendants. That means rendering the same\n // Context instance, and putting a different value into the context.\n return /*#__PURE__*/React.createElement(ContextToUse.Provider, {\n value: overriddenContextValue\n }, renderedWrappedComponent);\n }\n\n return renderedWrappedComponent;\n }, [ContextToUse, renderedWrappedComponent, overriddenContextValue]);\n return renderedChild;\n }\n\n const _Connect = React.memo(ConnectFunction);\n\n // Add a hacky cast to get the right output type\n const Connect = _Connect;\n Connect.WrappedComponent = WrappedComponent;\n Connect.displayName = ConnectFunction.displayName = displayName;\n\n if (forwardRef) {\n const _forwarded = React.forwardRef(function forwardConnectRef(props, ref) {\n // @ts-ignore\n return /*#__PURE__*/React.createElement(Connect, _extends({}, props, {\n reactReduxForwardedRef: ref\n }));\n });\n\n const forwarded = _forwarded;\n forwarded.displayName = displayName;\n forwarded.WrappedComponent = WrappedComponent;\n return hoistStatics(forwarded, WrappedComponent);\n }\n\n return hoistStatics(Connect, WrappedComponent);\n };\n\n return wrapWithConnect;\n}\n\nexport default connect;","import { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps';\nimport { createInvalidArgFactory } from './invalidArgFactory';\nexport function mapStateToPropsFactory(mapStateToProps) {\n return !mapStateToProps ? wrapMapToPropsConstant(() => ({})) : typeof mapStateToProps === 'function' ? // @ts-ignore\n wrapMapToPropsFunc(mapStateToProps, 'mapStateToProps') : createInvalidArgFactory(mapStateToProps, 'mapStateToProps');\n}","import bindActionCreators from '../utils/bindActionCreators';\nimport { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps';\nimport { createInvalidArgFactory } from './invalidArgFactory';\nexport function mapDispatchToPropsFactory(mapDispatchToProps) {\n return mapDispatchToProps && typeof mapDispatchToProps === 'object' ? wrapMapToPropsConstant(dispatch => // @ts-ignore\n bindActionCreators(mapDispatchToProps, dispatch)) : !mapDispatchToProps ? wrapMapToPropsConstant(dispatch => ({\n dispatch\n })) : typeof mapDispatchToProps === 'function' ? // @ts-ignore\n wrapMapToPropsFunc(mapDispatchToProps, 'mapDispatchToProps') : createInvalidArgFactory(mapDispatchToProps, 'mapDispatchToProps');\n}","export default function bindActionCreators(actionCreators, dispatch) {\n const boundActionCreators = {};\n\n for (const key in actionCreators) {\n const actionCreator = actionCreators[key];\n\n if (typeof actionCreator === 'function') {\n boundActionCreators[key] = (...args) => dispatch(actionCreator(...args));\n }\n }\n\n return boundActionCreators;\n}","import * as React from 'react';\nimport { ReactReduxContext } from './Context';\nimport { createSubscription } from '../utils/Subscription';\nimport { useIsomorphicLayoutEffect } from '../utils/useIsomorphicLayoutEffect';\n\nfunction Provider({\n store,\n context,\n children,\n serverState,\n stabilityCheck = 'once',\n noopCheck = 'once'\n}) {\n const contextValue = React.useMemo(() => {\n const subscription = createSubscription(store);\n return {\n store,\n subscription,\n getServerState: serverState ? () => serverState : undefined,\n stabilityCheck,\n noopCheck\n };\n }, [store, serverState, stabilityCheck, noopCheck]);\n const previousState = React.useMemo(() => store.getState(), [store]);\n useIsomorphicLayoutEffect(() => {\n const {\n subscription\n } = contextValue;\n subscription.onStateChange = subscription.notifyNestedSubs;\n subscription.trySubscribe();\n\n if (previousState !== store.getState()) {\n subscription.notifyNestedSubs();\n }\n\n return () => {\n subscription.tryUnsubscribe();\n subscription.onStateChange = undefined;\n };\n }, [contextValue, previousState]);\n const Context = context || ReactReduxContext; // @ts-ignore 'AnyAction' is assignable to the constraint of type 'A', but 'A' could be instantiated with a different subtype\n\n return /*#__PURE__*/React.createElement(Context.Provider, {\n value: contextValue\n }, children);\n}\n\nexport default Provider;","import { ReactReduxContext } from '../components/Context';\nimport { useReduxContext as useDefaultReduxContext, createReduxContextHook } from './useReduxContext';\n/**\r\n * Hook factory, which creates a `useStore` hook bound to a given context.\r\n *\r\n * @param {React.Context} [context=ReactReduxContext] Context passed to your ``.\r\n * @returns {Function} A `useStore` hook bound to the specified context.\r\n */\n\nexport function createStoreHook(context = ReactReduxContext) {\n const useReduxContext = // @ts-ignore\n context === ReactReduxContext ? useDefaultReduxContext : // @ts-ignore\n createReduxContextHook(context);\n return function useStore() {\n const {\n store\n } = useReduxContext(); // @ts-ignore\n\n return store;\n };\n}\n/**\r\n * A hook to access the redux store.\r\n *\r\n * @returns {any} the redux store\r\n *\r\n * @example\r\n *\r\n * import React from 'react'\r\n * import { useStore } from 'react-redux'\r\n *\r\n * export const ExampleComponent = () => {\r\n * const store = useStore()\r\n * return
{store.getState()}
\r\n * }\r\n */\n\nexport const useStore = /*#__PURE__*/createStoreHook();","import { ReactReduxContext } from '../components/Context';\nimport { useStore as useDefaultStore, createStoreHook } from './useStore';\n/**\r\n * Hook factory, which creates a `useDispatch` hook bound to a given context.\r\n *\r\n * @param {React.Context} [context=ReactReduxContext] Context passed to your ``.\r\n * @returns {Function} A `useDispatch` hook bound to the specified context.\r\n */\n\nexport function createDispatchHook(context = ReactReduxContext) {\n const useStore = // @ts-ignore\n context === ReactReduxContext ? useDefaultStore : createStoreHook(context);\n return function useDispatch() {\n const store = useStore(); // @ts-ignore\n\n return store.dispatch;\n };\n}\n/**\r\n * A hook to access the redux `dispatch` function.\r\n *\r\n * @returns {any|function} redux store's `dispatch` function\r\n *\r\n * @example\r\n *\r\n * import React, { useCallback } from 'react'\r\n * import { useDispatch } from 'react-redux'\r\n *\r\n * export const CounterComponent = ({ value }) => {\r\n * const dispatch = useDispatch()\r\n * const increaseCounter = useCallback(() => dispatch({ type: 'increase-counter' }), [])\r\n * return (\r\n *
\r\n * {value}\r\n * \r\n *
\r\n * )\r\n * }\r\n */\n\nexport const useDispatch = /*#__PURE__*/createDispatchHook();","// The primary entry point assumes we're working with standard ReactDOM/RN, but\n// older versions that do not include `useSyncExternalStore` (React 16.9 - 17.x).\n// Because of that, the useSyncExternalStore compat shim is needed.\nimport { useSyncExternalStore } from 'use-sync-external-store/shim';\nimport { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector';\nimport { unstable_batchedUpdates as batch } from './utils/reactBatchedUpdates';\nimport { setBatch } from './utils/batch';\nimport { initializeUseSelector } from './hooks/useSelector';\nimport { initializeConnect } from './components/connect';\ninitializeUseSelector(useSyncExternalStoreWithSelector);\ninitializeConnect(useSyncExternalStore); // Enable batched updates in our subscriptions for use\n// with standard React renderers (ReactDOM, React Native)\n\nsetBatch(batch);\nexport { batch };\nexport * from './exports';","/**\n * @license React\n * react-server-dom-webpack.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';var k=require(\"react\"),l={stream:!0},n=new Map,p=Symbol.for(\"react.element\"),q=Symbol.for(\"react.lazy\"),r=Symbol.for(\"react.default_value\"),t=k.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ContextRegistry;function u(a){t[a]||(t[a]=k.createServerContext(a,r));return t[a]}function v(a,b,c){this._status=a;this._value=b;this._response=c}v.prototype.then=function(a){0===this._status?(null===this._value&&(this._value=[]),this._value.push(a)):a()};\nfunction w(a){switch(a._status){case 3:return a._value;case 1:var b=JSON.parse(a._value,a._response._fromJSON);a._status=3;return a._value=b;case 2:b=a._value;for(var c=b.chunks,d=0;d {\n apiRunner(`onServiceWorkerUpdateFound`, { serviceWorker: reg })\n // The updatefound event implies that reg.installing is set; see\n // https://w3c.github.io/ServiceWorker/#service-worker-registration-updatefound-event\n const installingWorker = reg.installing\n console.log(`installingWorker`, installingWorker)\n installingWorker.addEventListener(`statechange`, () => {\n switch (installingWorker.state) {\n case `installed`:\n if (navigator.serviceWorker.controller) {\n // At this point, the old content will have been purged and the fresh content will\n // have been added to the cache.\n\n // We set a flag so Gatsby Link knows to refresh the page on next navigation attempt\n window.___swUpdated = true\n // We call the onServiceWorkerUpdateReady API so users can show update prompts.\n apiRunner(`onServiceWorkerUpdateReady`, { serviceWorker: reg })\n\n // If resources failed for the current page, reload.\n if (window.___failedResources) {\n console.log(`resources failed, SW updated - reloading`)\n window.location.reload()\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a \"Content is cached for offline use.\" message.\n console.log(`Content is now available offline!`)\n\n // Post to service worker that install is complete.\n // Delay to allow time for the event listener to be added --\n // otherwise fetch is called too soon and resources aren't cached.\n apiRunner(`onServiceWorkerInstalled`, { serviceWorker: reg })\n }\n break\n\n case `redundant`:\n console.error(`The installing service worker became redundant.`)\n apiRunner(`onServiceWorkerRedundant`, { serviceWorker: reg })\n break\n\n case `activated`:\n apiRunner(`onServiceWorkerActive`, { serviceWorker: reg })\n break\n }\n })\n })\n })\n .catch(function (e) {\n console.error(`Error during service worker registration:`, e)\n })\n}\n","exports.createContentDigest = () => ``\n","import React from \"react\"\nimport PropTypes from \"prop-types\"\n\nimport loader from \"./loader\"\nimport InternalPageRenderer from \"./page-renderer\"\n\nconst ProdPageRenderer = ({ location }) => {\n const pageResources = loader.loadPageSync(location.pathname)\n if (!pageResources) {\n return null\n }\n return React.createElement(InternalPageRenderer, {\n location,\n pageResources,\n ...pageResources.json,\n })\n}\n\nProdPageRenderer.propTypes = {\n location: PropTypes.shape({\n pathname: PropTypes.string.isRequired,\n }).isRequired,\n}\n\nexport default ProdPageRenderer\n","import React from \"react\"\n\nconst SlicesResultsContext = React.createContext({})\nconst SlicesContext = React.createContext({})\nconst SlicesMapContext = React.createContext({})\nconst SlicesPropsContext = React.createContext({})\n\nexport {\n SlicesResultsContext,\n SlicesContext,\n SlicesMapContext,\n SlicesPropsContext,\n}\n","\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\nvar _react = _interopRequireDefault(require(\"react\"));\nvar _styledComponents = require(\"styled-components\");\n// eslint-disable-next-line react/prop-types,react/display-name\nexports.wrapRootElement = function (_ref, pluginOptions) {\n var element = _ref.element;\n return /*#__PURE__*/_react.default.createElement(_styledComponents.StyleSheetManager, {\n disableVendorPrefixes: (pluginOptions === null || pluginOptions === void 0 ? void 0 : pluginOptions.disableVendorPrefixes) === true\n }, element);\n};","/**\n * @license React\n * use-sync-external-store-shim/with-selector.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar React = require(\"react\"),\n shim = require(\"use-sync-external-store/shim\");\nfunction is(x, y) {\n return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);\n}\nvar objectIs = \"function\" === typeof Object.is ? Object.is : is,\n useSyncExternalStore = shim.useSyncExternalStore,\n useRef = React.useRef,\n useEffect = React.useEffect,\n useMemo = React.useMemo,\n useDebugValue = React.useDebugValue;\nexports.useSyncExternalStoreWithSelector = function (\n subscribe,\n getSnapshot,\n getServerSnapshot,\n selector,\n isEqual\n) {\n var instRef = useRef(null);\n if (null === instRef.current) {\n var inst = { hasValue: !1, value: null };\n instRef.current = inst;\n } else inst = instRef.current;\n instRef = useMemo(\n function () {\n function memoizedSelector(nextSnapshot) {\n if (!hasMemo) {\n hasMemo = !0;\n memoizedSnapshot = nextSnapshot;\n nextSnapshot = selector(nextSnapshot);\n if (void 0 !== isEqual && inst.hasValue) {\n var currentSelection = inst.value;\n if (isEqual(currentSelection, nextSnapshot))\n return (memoizedSelection = currentSelection);\n }\n return (memoizedSelection = nextSnapshot);\n }\n currentSelection = memoizedSelection;\n if (objectIs(memoizedSnapshot, nextSnapshot)) return currentSelection;\n var nextSelection = selector(nextSnapshot);\n if (void 0 !== isEqual && isEqual(currentSelection, nextSelection))\n return (memoizedSnapshot = nextSnapshot), currentSelection;\n memoizedSnapshot = nextSnapshot;\n return (memoizedSelection = nextSelection);\n }\n var hasMemo = !1,\n memoizedSnapshot,\n memoizedSelection,\n maybeGetServerSnapshot =\n void 0 === getServerSnapshot ? null : getServerSnapshot;\n return [\n function () {\n return memoizedSelector(getSnapshot());\n },\n null === maybeGetServerSnapshot\n ? void 0\n : function () {\n return memoizedSelector(maybeGetServerSnapshot());\n }\n ];\n },\n [getSnapshot, getServerSnapshot, selector, isEqual]\n );\n var value = useSyncExternalStore(subscribe, instRef[0], instRef[1]);\n useEffect(\n function () {\n inst.hasValue = !0;\n inst.value = value;\n },\n [value]\n );\n useDebugValue(value);\n return value;\n};\n","\"use strict\";\n\nexports.__esModule = true;\nexports.onInitialClientRender = void 0;\nvar _gatsbyScript = require(\"gatsby-script\");\nvar _injectPartytownSnippet = require(\"./utils/inject-partytown-snippet\");\n// Makes sure off-main-thread scripts are loaded in `gatsby develop`\nconst onInitialClientRender = () => {\n if (process.env.NODE_ENV !== `development`) {\n return;\n }\n (0, _injectPartytownSnippet.injectPartytownSnippet)(_gatsbyScript.collectedScriptsByPage.get(window.location.pathname));\n\n // Clear scripts after we've used them to avoid leaky behavior\n _gatsbyScript.collectedScriptsByPage.delete(window.location.pathname);\n};\n\n// Client-side navigation (CSR, e.g. Gatsby Link navigations) are broken upstream in Partytown.\n// We need an official API from Partytown for handling re-configuration and on-demand script loading.\n// Until then, `off-main-thread` scripts load only on server-side navigation (SSR).\n// See https://github.com/BuilderIO/partytown/issues/74 for more details.\nexports.onInitialClientRender = onInitialClientRender;\n//# sourceMappingURL=gatsby-browser.js.map","function _assertThisInitialized(e) {\n if (void 0 === e) throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");\n return e;\n}\nmodule.exports = _assertThisInitialized, module.exports.__esModule = true, module.exports[\"default\"] = module.exports;","const preferDefault = m => (m && m.default) || m\n\nif (process.env.BUILD_STAGE === `develop`) {\n module.exports = preferDefault(require(`./public-page-renderer-dev`))\n} else if (process.env.BUILD_STAGE === `build-javascript`) {\n module.exports = preferDefault(require(`./public-page-renderer-prod`))\n} else {\n module.exports = () => null\n}\n","function stylis_min (W) {\n function M(d, c, e, h, a) {\n for (var m = 0, b = 0, v = 0, n = 0, q, g, x = 0, K = 0, k, u = k = q = 0, l = 0, r = 0, I = 0, t = 0, B = e.length, J = B - 1, y, f = '', p = '', F = '', G = '', C; l < B;) {\n g = e.charCodeAt(l);\n l === J && 0 !== b + n + v + m && (0 !== b && (g = 47 === b ? 10 : 47), n = v = m = 0, B++, J++);\n\n if (0 === b + n + v + m) {\n if (l === J && (0 < r && (f = f.replace(N, '')), 0 < f.trim().length)) {\n switch (g) {\n case 32:\n case 9:\n case 59:\n case 13:\n case 10:\n break;\n\n default:\n f += e.charAt(l);\n }\n\n g = 59;\n }\n\n switch (g) {\n case 123:\n f = f.trim();\n q = f.charCodeAt(0);\n k = 1;\n\n for (t = ++l; l < B;) {\n switch (g = e.charCodeAt(l)) {\n case 123:\n k++;\n break;\n\n case 125:\n k--;\n break;\n\n case 47:\n switch (g = e.charCodeAt(l + 1)) {\n case 42:\n case 47:\n a: {\n for (u = l + 1; u < J; ++u) {\n switch (e.charCodeAt(u)) {\n case 47:\n if (42 === g && 42 === e.charCodeAt(u - 1) && l + 2 !== u) {\n l = u + 1;\n break a;\n }\n\n break;\n\n case 10:\n if (47 === g) {\n l = u + 1;\n break a;\n }\n\n }\n }\n\n l = u;\n }\n\n }\n\n break;\n\n case 91:\n g++;\n\n case 40:\n g++;\n\n case 34:\n case 39:\n for (; l++ < J && e.charCodeAt(l) !== g;) {\n }\n\n }\n\n if (0 === k) break;\n l++;\n }\n\n k = e.substring(t, l);\n 0 === q && (q = (f = f.replace(ca, '').trim()).charCodeAt(0));\n\n switch (q) {\n case 64:\n 0 < r && (f = f.replace(N, ''));\n g = f.charCodeAt(1);\n\n switch (g) {\n case 100:\n case 109:\n case 115:\n case 45:\n r = c;\n break;\n\n default:\n r = O;\n }\n\n k = M(c, r, k, g, a + 1);\n t = k.length;\n 0 < A && (r = X(O, f, I), C = H(3, k, r, c, D, z, t, g, a, h), f = r.join(''), void 0 !== C && 0 === (t = (k = C.trim()).length) && (g = 0, k = ''));\n if (0 < t) switch (g) {\n case 115:\n f = f.replace(da, ea);\n\n case 100:\n case 109:\n case 45:\n k = f + '{' + k + '}';\n break;\n\n case 107:\n f = f.replace(fa, '$1 $2');\n k = f + '{' + k + '}';\n k = 1 === w || 2 === w && L('@' + k, 3) ? '@-webkit-' + k + '@' + k : '@' + k;\n break;\n\n default:\n k = f + k, 112 === h && (k = (p += k, ''));\n } else k = '';\n break;\n\n default:\n k = M(c, X(c, f, I), k, h, a + 1);\n }\n\n F += k;\n k = I = r = u = q = 0;\n f = '';\n g = e.charCodeAt(++l);\n break;\n\n case 125:\n case 59:\n f = (0 < r ? f.replace(N, '') : f).trim();\n if (1 < (t = f.length)) switch (0 === u && (q = f.charCodeAt(0), 45 === q || 96 < q && 123 > q) && (t = (f = f.replace(' ', ':')).length), 0 < A && void 0 !== (C = H(1, f, c, d, D, z, p.length, h, a, h)) && 0 === (t = (f = C.trim()).length) && (f = '\\x00\\x00'), q = f.charCodeAt(0), g = f.charCodeAt(1), q) {\n case 0:\n break;\n\n case 64:\n if (105 === g || 99 === g) {\n G += f + e.charAt(l);\n break;\n }\n\n default:\n 58 !== f.charCodeAt(t - 1) && (p += P(f, q, g, f.charCodeAt(2)));\n }\n I = r = u = q = 0;\n f = '';\n g = e.charCodeAt(++l);\n }\n }\n\n switch (g) {\n case 13:\n case 10:\n 47 === b ? b = 0 : 0 === 1 + q && 107 !== h && 0 < f.length && (r = 1, f += '\\x00');\n 0 < A * Y && H(0, f, c, d, D, z, p.length, h, a, h);\n z = 1;\n D++;\n break;\n\n case 59:\n case 125:\n if (0 === b + n + v + m) {\n z++;\n break;\n }\n\n default:\n z++;\n y = e.charAt(l);\n\n switch (g) {\n case 9:\n case 32:\n if (0 === n + m + b) switch (x) {\n case 44:\n case 58:\n case 9:\n case 32:\n y = '';\n break;\n\n default:\n 32 !== g && (y = ' ');\n }\n break;\n\n case 0:\n y = '\\\\0';\n break;\n\n case 12:\n y = '\\\\f';\n break;\n\n case 11:\n y = '\\\\v';\n break;\n\n case 38:\n 0 === n + b + m && (r = I = 1, y = '\\f' + y);\n break;\n\n case 108:\n if (0 === n + b + m + E && 0 < u) switch (l - u) {\n case 2:\n 112 === x && 58 === e.charCodeAt(l - 3) && (E = x);\n\n case 8:\n 111 === K && (E = K);\n }\n break;\n\n case 58:\n 0 === n + b + m && (u = l);\n break;\n\n case 44:\n 0 === b + v + n + m && (r = 1, y += '\\r');\n break;\n\n case 34:\n case 39:\n 0 === b && (n = n === g ? 0 : 0 === n ? g : n);\n break;\n\n case 91:\n 0 === n + b + v && m++;\n break;\n\n case 93:\n 0 === n + b + v && m--;\n break;\n\n case 41:\n 0 === n + b + m && v--;\n break;\n\n case 40:\n if (0 === n + b + m) {\n if (0 === q) switch (2 * x + 3 * K) {\n case 533:\n break;\n\n default:\n q = 1;\n }\n v++;\n }\n\n break;\n\n case 64:\n 0 === b + v + n + m + u + k && (k = 1);\n break;\n\n case 42:\n case 47:\n if (!(0 < n + m + v)) switch (b) {\n case 0:\n switch (2 * g + 3 * e.charCodeAt(l + 1)) {\n case 235:\n b = 47;\n break;\n\n case 220:\n t = l, b = 42;\n }\n\n break;\n\n case 42:\n 47 === g && 42 === x && t + 2 !== l && (33 === e.charCodeAt(t + 2) && (p += e.substring(t, l + 1)), y = '', b = 0);\n }\n }\n\n 0 === b && (f += y);\n }\n\n K = x;\n x = g;\n l++;\n }\n\n t = p.length;\n\n if (0 < t) {\n r = c;\n if (0 < A && (C = H(2, p, r, d, D, z, t, h, a, h), void 0 !== C && 0 === (p = C).length)) return G + p + F;\n p = r.join(',') + '{' + p + '}';\n\n if (0 !== w * E) {\n 2 !== w || L(p, 2) || (E = 0);\n\n switch (E) {\n case 111:\n p = p.replace(ha, ':-moz-$1') + p;\n break;\n\n case 112:\n p = p.replace(Q, '::-webkit-input-$1') + p.replace(Q, '::-moz-$1') + p.replace(Q, ':-ms-input-$1') + p;\n }\n\n E = 0;\n }\n }\n\n return G + p + F;\n }\n\n function X(d, c, e) {\n var h = c.trim().split(ia);\n c = h;\n var a = h.length,\n m = d.length;\n\n switch (m) {\n case 0:\n case 1:\n var b = 0;\n\n for (d = 0 === m ? '' : d[0] + ' '; b < a; ++b) {\n c[b] = Z(d, c[b], e).trim();\n }\n\n break;\n\n default:\n var v = b = 0;\n\n for (c = []; b < a; ++b) {\n for (var n = 0; n < m; ++n) {\n c[v++] = Z(d[n] + ' ', h[b], e).trim();\n }\n }\n\n }\n\n return c;\n }\n\n function Z(d, c, e) {\n var h = c.charCodeAt(0);\n 33 > h && (h = (c = c.trim()).charCodeAt(0));\n\n switch (h) {\n case 38:\n return c.replace(F, '$1' + d.trim());\n\n case 58:\n return d.trim() + c.replace(F, '$1' + d.trim());\n\n default:\n if (0 < 1 * e && 0 < c.indexOf('\\f')) return c.replace(F, (58 === d.charCodeAt(0) ? '' : '$1') + d.trim());\n }\n\n return d + c;\n }\n\n function P(d, c, e, h) {\n var a = d + ';',\n m = 2 * c + 3 * e + 4 * h;\n\n if (944 === m) {\n d = a.indexOf(':', 9) + 1;\n var b = a.substring(d, a.length - 1).trim();\n b = a.substring(0, d).trim() + b + ';';\n return 1 === w || 2 === w && L(b, 1) ? '-webkit-' + b + b : b;\n }\n\n if (0 === w || 2 === w && !L(a, 1)) return a;\n\n switch (m) {\n case 1015:\n return 97 === a.charCodeAt(10) ? '-webkit-' + a + a : a;\n\n case 951:\n return 116 === a.charCodeAt(3) ? '-webkit-' + a + a : a;\n\n case 963:\n return 110 === a.charCodeAt(5) ? '-webkit-' + a + a : a;\n\n case 1009:\n if (100 !== a.charCodeAt(4)) break;\n\n case 969:\n case 942:\n return '-webkit-' + a + a;\n\n case 978:\n return '-webkit-' + a + '-moz-' + a + a;\n\n case 1019:\n case 983:\n return '-webkit-' + a + '-moz-' + a + '-ms-' + a + a;\n\n case 883:\n if (45 === a.charCodeAt(8)) return '-webkit-' + a + a;\n if (0 < a.indexOf('image-set(', 11)) return a.replace(ja, '$1-webkit-$2') + a;\n break;\n\n case 932:\n if (45 === a.charCodeAt(4)) switch (a.charCodeAt(5)) {\n case 103:\n return '-webkit-box-' + a.replace('-grow', '') + '-webkit-' + a + '-ms-' + a.replace('grow', 'positive') + a;\n\n case 115:\n return '-webkit-' + a + '-ms-' + a.replace('shrink', 'negative') + a;\n\n case 98:\n return '-webkit-' + a + '-ms-' + a.replace('basis', 'preferred-size') + a;\n }\n return '-webkit-' + a + '-ms-' + a + a;\n\n case 964:\n return '-webkit-' + a + '-ms-flex-' + a + a;\n\n case 1023:\n if (99 !== a.charCodeAt(8)) break;\n b = a.substring(a.indexOf(':', 15)).replace('flex-', '').replace('space-between', 'justify');\n return '-webkit-box-pack' + b + '-webkit-' + a + '-ms-flex-pack' + b + a;\n\n case 1005:\n return ka.test(a) ? a.replace(aa, ':-webkit-') + a.replace(aa, ':-moz-') + a : a;\n\n case 1e3:\n b = a.substring(13).trim();\n c = b.indexOf('-') + 1;\n\n switch (b.charCodeAt(0) + b.charCodeAt(c)) {\n case 226:\n b = a.replace(G, 'tb');\n break;\n\n case 232:\n b = a.replace(G, 'tb-rl');\n break;\n\n case 220:\n b = a.replace(G, 'lr');\n break;\n\n default:\n return a;\n }\n\n return '-webkit-' + a + '-ms-' + b + a;\n\n case 1017:\n if (-1 === a.indexOf('sticky', 9)) break;\n\n case 975:\n c = (a = d).length - 10;\n b = (33 === a.charCodeAt(c) ? a.substring(0, c) : a).substring(d.indexOf(':', 7) + 1).trim();\n\n switch (m = b.charCodeAt(0) + (b.charCodeAt(7) | 0)) {\n case 203:\n if (111 > b.charCodeAt(8)) break;\n\n case 115:\n a = a.replace(b, '-webkit-' + b) + ';' + a;\n break;\n\n case 207:\n case 102:\n a = a.replace(b, '-webkit-' + (102 < m ? 'inline-' : '') + 'box') + ';' + a.replace(b, '-webkit-' + b) + ';' + a.replace(b, '-ms-' + b + 'box') + ';' + a;\n }\n\n return a + ';';\n\n case 938:\n if (45 === a.charCodeAt(5)) switch (a.charCodeAt(6)) {\n case 105:\n return b = a.replace('-items', ''), '-webkit-' + a + '-webkit-box-' + b + '-ms-flex-' + b + a;\n\n case 115:\n return '-webkit-' + a + '-ms-flex-item-' + a.replace(ba, '') + a;\n\n default:\n return '-webkit-' + a + '-ms-flex-line-pack' + a.replace('align-content', '').replace(ba, '') + a;\n }\n break;\n\n case 973:\n case 989:\n if (45 !== a.charCodeAt(3) || 122 === a.charCodeAt(4)) break;\n\n case 931:\n case 953:\n if (!0 === la.test(d)) return 115 === (b = d.substring(d.indexOf(':') + 1)).charCodeAt(0) ? P(d.replace('stretch', 'fill-available'), c, e, h).replace(':fill-available', ':stretch') : a.replace(b, '-webkit-' + b) + a.replace(b, '-moz-' + b.replace('fill-', '')) + a;\n break;\n\n case 962:\n if (a = '-webkit-' + a + (102 === a.charCodeAt(5) ? '-ms-' + a : '') + a, 211 === e + h && 105 === a.charCodeAt(13) && 0 < a.indexOf('transform', 10)) return a.substring(0, a.indexOf(';', 27) + 1).replace(ma, '$1-webkit-$2') + a;\n }\n\n return a;\n }\n\n function L(d, c) {\n var e = d.indexOf(1 === c ? ':' : '{'),\n h = d.substring(0, 3 !== c ? e : 10);\n e = d.substring(e + 1, d.length - 1);\n return R(2 !== c ? h : h.replace(na, '$1'), e, c);\n }\n\n function ea(d, c) {\n var e = P(c, c.charCodeAt(0), c.charCodeAt(1), c.charCodeAt(2));\n return e !== c + ';' ? e.replace(oa, ' or ($1)').substring(4) : '(' + c + ')';\n }\n\n function H(d, c, e, h, a, m, b, v, n, q) {\n for (var g = 0, x = c, w; g < A; ++g) {\n switch (w = S[g].call(B, d, x, e, h, a, m, b, v, n, q)) {\n case void 0:\n case !1:\n case !0:\n case null:\n break;\n\n default:\n x = w;\n }\n }\n\n if (x !== c) return x;\n }\n\n function T(d) {\n switch (d) {\n case void 0:\n case null:\n A = S.length = 0;\n break;\n\n default:\n if ('function' === typeof d) S[A++] = d;else if ('object' === typeof d) for (var c = 0, e = d.length; c < e; ++c) {\n T(d[c]);\n } else Y = !!d | 0;\n }\n\n return T;\n }\n\n function U(d) {\n d = d.prefix;\n void 0 !== d && (R = null, d ? 'function' !== typeof d ? w = 1 : (w = 2, R = d) : w = 0);\n return U;\n }\n\n function B(d, c) {\n var e = d;\n 33 > e.charCodeAt(0) && (e = e.trim());\n V = e;\n e = [V];\n\n if (0 < A) {\n var h = H(-1, c, e, e, D, z, 0, 0, 0, 0);\n void 0 !== h && 'string' === typeof h && (c = h);\n }\n\n var a = M(O, e, c, 0, 0);\n 0 < A && (h = H(-2, a, e, e, D, z, a.length, 0, 0, 0), void 0 !== h && (a = h));\n V = '';\n E = 0;\n z = D = 1;\n return a;\n }\n\n var ca = /^\\0+/g,\n N = /[\\0\\r\\f]/g,\n aa = /: */g,\n ka = /zoo|gra/,\n ma = /([,: ])(transform)/g,\n ia = /,\\r+?/g,\n F = /([\\t\\r\\n ])*\\f?&/g,\n fa = /@(k\\w+)\\s*(\\S*)\\s*/,\n Q = /::(place)/g,\n ha = /:(read-only)/g,\n G = /[svh]\\w+-[tblr]{2}/,\n da = /\\(\\s*(.*)\\s*\\)/g,\n oa = /([\\s\\S]*?);/g,\n ba = /-self|flex-/g,\n na = /[^]*?(:[rp][el]a[\\w-]+)[^]*/,\n la = /stretch|:\\s*\\w+\\-(?:conte|avail)/,\n ja = /([^-])(image-set\\()/,\n z = 1,\n D = 1,\n E = 0,\n w = 1,\n O = [],\n S = [],\n A = 0,\n R = null,\n Y = 0,\n V = '';\n B.use = T;\n B.set = U;\n void 0 !== W && U(W);\n return B;\n}\n\nexport default stylis_min;\n","var unitlessKeys = {\n animationIterationCount: 1,\n borderImageOutset: 1,\n borderImageSlice: 1,\n borderImageWidth: 1,\n boxFlex: 1,\n boxFlexGroup: 1,\n boxOrdinalGroup: 1,\n columnCount: 1,\n columns: 1,\n flex: 1,\n flexGrow: 1,\n flexPositive: 1,\n flexShrink: 1,\n flexNegative: 1,\n flexOrder: 1,\n gridRow: 1,\n gridRowEnd: 1,\n gridRowSpan: 1,\n gridRowStart: 1,\n gridColumn: 1,\n gridColumnEnd: 1,\n gridColumnSpan: 1,\n gridColumnStart: 1,\n msGridRow: 1,\n msGridRowSpan: 1,\n msGridColumn: 1,\n msGridColumnSpan: 1,\n fontWeight: 1,\n lineHeight: 1,\n opacity: 1,\n order: 1,\n orphans: 1,\n tabSize: 1,\n widows: 1,\n zIndex: 1,\n zoom: 1,\n WebkitLineClamp: 1,\n // SVG-related properties\n fillOpacity: 1,\n floodOpacity: 1,\n stopOpacity: 1,\n strokeDasharray: 1,\n strokeDashoffset: 1,\n strokeMiterlimit: 1,\n strokeOpacity: 1,\n strokeWidth: 1\n};\n\nexport default unitlessKeys;\n","function memoize(fn) {\n var cache = Object.create(null);\n return function (arg) {\n if (cache[arg] === undefined) cache[arg] = fn(arg);\n return cache[arg];\n };\n}\n\nexport { memoize as default };\n","import memoize from '@emotion/memoize';\n\n// eslint-disable-next-line no-undef\nvar reactPropsRegex = /^((children|dangerouslySetInnerHTML|key|ref|autoFocus|defaultValue|defaultChecked|innerHTML|suppressContentEditableWarning|suppressHydrationWarning|valueLink|abbr|accept|acceptCharset|accessKey|action|allow|allowUserMedia|allowPaymentRequest|allowFullScreen|allowTransparency|alt|async|autoComplete|autoPlay|capture|cellPadding|cellSpacing|challenge|charSet|checked|cite|classID|className|cols|colSpan|content|contentEditable|contextMenu|controls|controlsList|coords|crossOrigin|data|dateTime|decoding|default|defer|dir|disabled|disablePictureInPicture|disableRemotePlayback|download|draggable|encType|enterKeyHint|fetchpriority|fetchPriority|form|formAction|formEncType|formMethod|formNoValidate|formTarget|frameBorder|headers|height|hidden|high|href|hrefLang|htmlFor|httpEquiv|id|inputMode|integrity|is|keyParams|keyType|kind|label|lang|list|loading|loop|low|marginHeight|marginWidth|max|maxLength|media|mediaGroup|method|min|minLength|multiple|muted|name|nonce|noValidate|open|optimum|pattern|placeholder|playsInline|popover|popoverTarget|popoverTargetAction|poster|preload|profile|radioGroup|readOnly|referrerPolicy|rel|required|reversed|role|rows|rowSpan|sandbox|scope|scoped|scrolling|seamless|selected|shape|size|sizes|slot|span|spellCheck|src|srcDoc|srcLang|srcSet|start|step|style|summary|tabIndex|target|title|translate|type|useMap|value|width|wmode|wrap|about|datatype|inlist|prefix|property|resource|typeof|vocab|autoCapitalize|autoCorrect|autoSave|color|incremental|fallback|inert|itemProp|itemScope|itemType|itemID|itemRef|on|option|results|security|unselectable|accentHeight|accumulate|additive|alignmentBaseline|allowReorder|alphabetic|amplitude|arabicForm|ascent|attributeName|attributeType|autoReverse|azimuth|baseFrequency|baselineShift|baseProfile|bbox|begin|bias|by|calcMode|capHeight|clip|clipPathUnits|clipPath|clipRule|colorInterpolation|colorInterpolationFilters|colorProfile|colorRendering|contentScriptType|contentStyleType|cursor|cx|cy|d|decelerate|descent|diffuseConstant|direction|display|divisor|dominantBaseline|dur|dx|dy|edgeMode|elevation|enableBackground|end|exponent|externalResourcesRequired|fill|fillOpacity|fillRule|filter|filterRes|filterUnits|floodColor|floodOpacity|focusable|fontFamily|fontSize|fontSizeAdjust|fontStretch|fontStyle|fontVariant|fontWeight|format|from|fr|fx|fy|g1|g2|glyphName|glyphOrientationHorizontal|glyphOrientationVertical|glyphRef|gradientTransform|gradientUnits|hanging|horizAdvX|horizOriginX|ideographic|imageRendering|in|in2|intercept|k|k1|k2|k3|k4|kernelMatrix|kernelUnitLength|kerning|keyPoints|keySplines|keyTimes|lengthAdjust|letterSpacing|lightingColor|limitingConeAngle|local|markerEnd|markerMid|markerStart|markerHeight|markerUnits|markerWidth|mask|maskContentUnits|maskUnits|mathematical|mode|numOctaves|offset|opacity|operator|order|orient|orientation|origin|overflow|overlinePosition|overlineThickness|panose1|paintOrder|pathLength|patternContentUnits|patternTransform|patternUnits|pointerEvents|points|pointsAtX|pointsAtY|pointsAtZ|preserveAlpha|preserveAspectRatio|primitiveUnits|r|radius|refX|refY|renderingIntent|repeatCount|repeatDur|requiredExtensions|requiredFeatures|restart|result|rotate|rx|ry|scale|seed|shapeRendering|slope|spacing|specularConstant|specularExponent|speed|spreadMethod|startOffset|stdDeviation|stemh|stemv|stitchTiles|stopColor|stopOpacity|strikethroughPosition|strikethroughThickness|string|stroke|strokeDasharray|strokeDashoffset|strokeLinecap|strokeLinejoin|strokeMiterlimit|strokeOpacity|strokeWidth|surfaceScale|systemLanguage|tableValues|targetX|targetY|textAnchor|textDecoration|textRendering|textLength|to|transform|u1|u2|underlinePosition|underlineThickness|unicode|unicodeBidi|unicodeRange|unitsPerEm|vAlphabetic|vHanging|vIdeographic|vMathematical|values|vectorEffect|version|vertAdvY|vertOriginX|vertOriginY|viewBox|viewTarget|visibility|widths|wordSpacing|writingMode|x|xHeight|x1|x2|xChannelSelector|xlinkActuate|xlinkArcrole|xlinkHref|xlinkRole|xlinkShow|xlinkTitle|xlinkType|xmlBase|xmlns|xmlnsXlink|xmlLang|xmlSpace|y|y1|y2|yChannelSelector|z|zoomAndPan|for|class|autofocus)|(([Dd][Aa][Tt][Aa]|[Aa][Rr][Ii][Aa]|x)-.*))$/; // https://esbench.com/bench/5bfee68a4cd7e6009ef61d23\n\nvar isPropValid = /* #__PURE__ */memoize(function (prop) {\n return reactPropsRegex.test(prop) || prop.charCodeAt(0) === 111\n /* o */\n && prop.charCodeAt(1) === 110\n /* n */\n && prop.charCodeAt(2) < 91;\n}\n/* Z+1 */\n);\n\nexport { isPropValid as default };\n","import{typeOf as e,isElement as t,isValidElementType as n}from\"react-is\";import r,{useState as o,useContext as s,useMemo as i,useEffect as a,useRef as c,createElement as u,useLayoutEffect as l}from\"react\";import d from\"shallowequal\";import h from\"@emotion/stylis\";import p from\"@emotion/unitless\";import f from\"@emotion/is-prop-valid\";import m from\"hoist-non-react-statics\";function y(){return(y=Object.assign||function(e){for(var t=1;t ({})}\\n```\\n\\n',8:'ThemeProvider: Please make your \"theme\" prop an object.\\n\\n',9:\"Missing document ``\\n\\n\",10:\"Cannot find a StyleSheet instance. Usually this happens if there are multiple copies of styled-components loaded at once. Check out this issue for how to troubleshoot and fix the common cases where this situation can happen: https://github.com/styled-components/styled-components/issues/1941#issuecomment-417862021\\n\\n\",11:\"_This error was replaced with a dev-time warning, it will be deleted for v4 final._ [createGlobalStyle] received children which will not be rendered. Please use the component without passing children elements.\\n\\n\",12:\"It seems you are interpolating a keyframe declaration (%s) into an untagged string. This was supported in styled-components v3, but is not longer supported in v4 as keyframes are now injected on-demand. Please wrap your string in the css\\\\`\\\\` helper which ensures the styles are injected correctly. See https://www.styled-components.com/docs/api#css\\n\\n\",13:\"%s is not a styled component and cannot be referred to via component selector. See https://www.styled-components.com/docs/advanced#referring-to-other-components for more details.\\n\\n\",14:'ThemeProvider: \"theme\" prop is required.\\n\\n',15:\"A stylis plugin has been supplied that is not named. We need a name for each plugin to be able to prevent styling collisions between different stylis configurations within the same app. Before you pass your plugin to ``, please make sure each plugin is uniquely-named, e.g.\\n\\n```js\\nObject.defineProperty(importedPlugin, 'name', { value: 'some-unique-name' });\\n```\\n\\n\",16:\"Reached the limit of how many styled components may be created at group %s.\\nYou may only create up to 1,073,741,824 components. If you're creating components dynamically,\\nas for instance in your render method then you may be running into this limitation.\\n\\n\",17:\"CSSStyleSheet could not be found on HTMLStyleElement.\\nHas styled-components' style tag been unmounted or altered by another script?\\n\"}:{};function R(){for(var e=arguments.length<=0?void 0:arguments[0],t=[],n=1,r=arguments.length;n1?t-1:0),r=1;r0?\" Args: \"+n.join(\", \"):\"\")):new Error(R.apply(void 0,[O[e]].concat(n)).trim())}var j=function(){function e(e){this.groupSizes=new Uint32Array(512),this.length=512,this.tag=e}var t=e.prototype;return t.indexOfGroup=function(e){for(var t=0,n=0;n=this.groupSizes.length){for(var n=this.groupSizes,r=n.length,o=r;e>=o;)(o<<=1)<0&&D(16,\"\"+e);this.groupSizes=new Uint32Array(o),this.groupSizes.set(n),this.length=o;for(var s=r;s=this.length||0===this.groupSizes[e])return t;for(var n=this.groupSizes[e],r=this.indexOfGroup(e),o=r+n,s=r;s1<<30)&&D(16,\"\"+t),T.set(e,t),x.set(t,e),t},B=function(e){return x.get(e)},z=function(e,t){t>=k&&(k=t+1),T.set(e,t),x.set(t,e)},M=\"style[\"+N+'][data-styled-version=\"5.3.11\"]',G=new RegExp(\"^\"+N+'\\\\.g(\\\\d+)\\\\[id=\"([\\\\w\\\\d-]+)\"\\\\].*?\"([^\"]*)'),L=function(e,t,n){for(var r,o=n.split(\",\"),s=0,i=o.length;s=0;n--){var r=t[n];if(r&&1===r.nodeType&&r.hasAttribute(N))return r}}(n),s=void 0!==o?o.nextSibling:null;r.setAttribute(N,\"active\"),r.setAttribute(\"data-styled-version\",\"5.3.11\");var i=Y();return i&&r.setAttribute(\"nonce\",i),n.insertBefore(r,s),r},H=function(){function e(e){var t=this.element=q(e);t.appendChild(document.createTextNode(\"\")),this.sheet=function(e){if(e.sheet)return e.sheet;for(var t=document.styleSheets,n=0,r=t.length;n=0){var n=document.createTextNode(t),r=this.nodes[e];return this.element.insertBefore(n,r||null),this.length++,!0}return!1},t.deleteRule=function(e){this.element.removeChild(this.nodes[e]),this.length--},t.getRule=function(e){return e0&&(u+=e+\",\")})),r+=\"\"+a+c+'{content:\"'+u+'\"}/*!sc*/\\n'}}}return r}(this)},e}(),Z=/(a)(d)/gi,K=function(e){return String.fromCharCode(e+(e>25?39:97))};function Q(e){var t,n=\"\";for(t=Math.abs(e);t>52;t=t/52|0)n=K(t%52)+n;return(K(t%52)+n).replace(Z,\"$1-$2\")}var ee=function(e,t){for(var n=t.length;n;)e=33*e^t.charCodeAt(--n);return e},te=function(e){return ee(5381,e)};function ne(e){for(var t=0;t>>0);if(!t.hasNameForId(r,i)){var a=n(s,\".\"+i,void 0,r);t.insertRules(r,i,a)}o.push(i),this.staticRulesId=i}else{for(var c=this.rules.length,u=ee(this.baseHash,n.hash),l=\"\",d=0;d>>0);if(!t.hasNameForId(r,m)){var y=n(l,\".\"+m,void 0,r);t.insertRules(r,m,y)}o.push(m)}}return o.join(\" \")},e}(),se=/^\\s*\\/\\/.*$/gm,ie=[\":\",\"[\",\".\",\"#\"];function ae(e){var t,n,r,o,s=void 0===e?w:e,i=s.options,a=void 0===i?w:i,c=s.plugins,u=void 0===c?S:c,l=new h(a),d=[],p=function(e){function t(t){if(t)try{e(t+\"}\")}catch(e){}}return function(n,r,o,s,i,a,c,u,l,d){switch(n){case 1:if(0===l&&64===r.charCodeAt(0))return e(r+\";\"),\"\";break;case 2:if(0===u)return r+\"/*|*/\";break;case 3:switch(u){case 102:case 112:return e(o[0]+r),\"\";default:return r+(0===d?\"/*|*/\":\"\")}case-2:r.split(\"/*|*/}\").forEach(t)}}}((function(e){d.push(e)})),f=function(e,r,s){return 0===r&&-1!==ie.indexOf(s[n.length])||s.match(o)?e:\".\"+t};function m(e,s,i,a){void 0===a&&(a=\"&\");var c=e.replace(se,\"\"),u=s&&i?i+\" \"+s+\" { \"+c+\" }\":c;return t=a,n=s,r=new RegExp(\"\\\\\"+n+\"\\\\b\",\"g\"),o=new RegExp(\"(\\\\\"+n+\"\\\\b){2,}\"),l(i||!s?\"\":s,u)}return l.use([].concat(u,[function(e,t,o){2===e&&o.length&&o[0].lastIndexOf(n)>0&&(o[0]=o[0].replace(r,f))},p,function(e){if(-2===e){var t=d;return d=[],t}}])),m.hash=u.length?u.reduce((function(e,t){return t.name||D(15),ee(e,t.name)}),5381).toString():\"\",m}var ce=r.createContext(),ue=ce.Consumer,le=r.createContext(),de=(le.Consumer,new X),he=ae();function pe(){return s(ce)||de}function fe(){return s(le)||he}function me(e){var t=o(e.stylisPlugins),n=t[0],s=t[1],c=pe(),u=i((function(){var t=c;return e.sheet?t=e.sheet:e.target&&(t=t.reconstructWithOptions({target:e.target},!1)),e.disableCSSOMInjection&&(t=t.reconstructWithOptions({useCSSOMInjection:!1})),t}),[e.disableCSSOMInjection,e.sheet,e.target]),l=i((function(){return ae({options:{prefix:!e.disableVendorPrefixes},plugins:n})}),[e.disableVendorPrefixes,n]);return a((function(){d(n,e.stylisPlugins)||s(e.stylisPlugins)}),[e.stylisPlugins]),r.createElement(ce.Provider,{value:u},r.createElement(le.Provider,{value:l},\"production\"!==process.env.NODE_ENV?r.Children.only(e.children):e.children))}var ye=function(){function e(e,t){var n=this;this.inject=function(e,t){void 0===t&&(t=he);var r=n.name+t.hash;e.hasNameForId(n.id,r)||e.insertRules(n.id,r,t(n.rules,r,\"@keyframes\"))},this.toString=function(){return D(12,String(n.name))},this.name=e,this.id=\"sc-keyframes-\"+e,this.rules=t}return e.prototype.getName=function(e){return void 0===e&&(e=he),this.name+e.hash},e}(),ve=/([A-Z])/,ge=/([A-Z])/g,Se=/^ms-/,we=function(e){return\"-\"+e.toLowerCase()};function Ee(e){return ve.test(e)?e.replace(ge,we).replace(Se,\"-ms-\"):e}var be=function(e){return null==e||!1===e||\"\"===e};function _e(e,n,r,o){if(Array.isArray(e)){for(var s,i=[],a=0,c=e.length;a1?t-1:0),r=1;r1?t-1:0),i=1;i?@[\\\\\\]^`{|}~-]+/g,De=/(^-|-$)/g;function je(e){return e.replace(Re,\"-\").replace(De,\"\")}var Te=function(e){return Q(te(e)>>>0)};function xe(e){return\"string\"==typeof e&&(\"production\"===process.env.NODE_ENV||e.charAt(0)===e.charAt(0).toLowerCase())}var ke=function(e){return\"function\"==typeof e||\"object\"==typeof e&&null!==e&&!Array.isArray(e)},Ve=function(e){return\"__proto__\"!==e&&\"constructor\"!==e&&\"prototype\"!==e};function Be(e,t,n){var r=e[n];ke(t)&&ke(r)?ze(r,t):e[n]=t}function ze(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r=0||(o[n]=e[n]);return o}(t,[\"componentId\"]),s=r&&r+\"-\"+(xe(e)?e:je(b(e)));return Ye(e,y({},o,{attrs:g,componentId:s}),n)},Object.defineProperty(A,\"defaultProps\",{get:function(){return this._foldedDefaultProps},set:function(t){this._foldedDefaultProps=o?ze({},e.defaultProps,t):t}}),\"production\"!==process.env.NODE_ENV&&(Pe(p,v),A.warnTooManyClasses=function(e,t){var n={},r=!1;return function(o){if(!r&&(n[o]=!0,Object.keys(n).length>=200)){var s=t?' with the id of \"'+t+'\"':\"\";console.warn(\"Over 200 classes were generated for component \"+e+s+\".\\nConsider using the attrs method, together with a style object for frequently changed styles.\\nExample:\\n const Component = styled.div.attrs(props => ({\\n style: {\\n background: props.background,\\n },\\n }))`width: 100%;`\\n\\n \"),r=!0,n={}}}}(p,v)),Object.defineProperty(A,\"toString\",{value:function(){return\".\"+A.styledComponentId}}),i&&m(A,e,{attrs:!0,componentStyle:!0,displayName:!0,foldedComponentIds:!0,shouldForwardProp:!0,styledComponentId:!0,target:!0,withComponent:!0}),A}var qe=function(e){return function e(t,r,o){if(void 0===o&&(o=w),!n(r))return D(1,String(r));var s=function(){return t(r,o,Ae.apply(void 0,arguments))};return s.withConfig=function(n){return e(t,r,y({},o,{},n))},s.attrs=function(n){return e(t,r,y({},o,{attrs:Array.prototype.concat(o.attrs,n).filter(Boolean)}))},s}(Ye,e)};[\"a\",\"abbr\",\"address\",\"area\",\"article\",\"aside\",\"audio\",\"b\",\"base\",\"bdi\",\"bdo\",\"big\",\"blockquote\",\"body\",\"br\",\"button\",\"canvas\",\"caption\",\"cite\",\"code\",\"col\",\"colgroup\",\"data\",\"datalist\",\"dd\",\"del\",\"details\",\"dfn\",\"dialog\",\"div\",\"dl\",\"dt\",\"em\",\"embed\",\"fieldset\",\"figcaption\",\"figure\",\"footer\",\"form\",\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\",\"head\",\"header\",\"hgroup\",\"hr\",\"html\",\"i\",\"iframe\",\"img\",\"input\",\"ins\",\"kbd\",\"keygen\",\"label\",\"legend\",\"li\",\"link\",\"main\",\"map\",\"mark\",\"marquee\",\"menu\",\"menuitem\",\"meta\",\"meter\",\"nav\",\"noscript\",\"object\",\"ol\",\"optgroup\",\"option\",\"output\",\"p\",\"param\",\"picture\",\"pre\",\"progress\",\"q\",\"rp\",\"rt\",\"ruby\",\"s\",\"samp\",\"script\",\"section\",\"select\",\"small\",\"source\",\"span\",\"strong\",\"style\",\"sub\",\"summary\",\"sup\",\"table\",\"tbody\",\"td\",\"textarea\",\"tfoot\",\"th\",\"thead\",\"time\",\"title\",\"tr\",\"track\",\"u\",\"ul\",\"var\",\"video\",\"wbr\",\"circle\",\"clipPath\",\"defs\",\"ellipse\",\"foreignObject\",\"g\",\"image\",\"line\",\"linearGradient\",\"marker\",\"mask\",\"path\",\"pattern\",\"polygon\",\"polyline\",\"radialGradient\",\"rect\",\"stop\",\"svg\",\"text\",\"textPath\",\"tspan\"].forEach((function(e){qe[e]=qe(e)}));var He=function(){function e(e,t){this.rules=e,this.componentId=t,this.isStatic=ne(e),X.registerId(this.componentId+1)}var t=e.prototype;return t.createStyles=function(e,t,n,r){var o=r(_e(this.rules,t,n,r).join(\"\"),\"\"),s=this.componentId+e;n.insertRules(s,s,o)},t.removeStyles=function(e,t){t.clearRules(this.componentId+e)},t.renderStyles=function(e,t,n,r){e>2&&X.registerId(this.componentId+e),this.removeStyles(e,n),this.createStyles(e,t,n,r)},e}();function $e(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),o=1;o meta tag to the stylesheet, or simply embedding it manually in your index.html section for a simpler app.\"),t.server&&h(d,e,t,o,n),l((function(){if(!t.server)return h(d,e,t,o,n),function(){return u.removeStyles(d,t)}}),[d,e,t,o,n]),null}function h(e,t,n,r,o){if(u.isStatic)u.renderStyles(e,P,n,o);else{var s=y({},t,{theme:Oe(t,r,d.defaultProps)});u.renderStyles(e,s,n,o)}}return\"production\"!==process.env.NODE_ENV&&Pe(a),r.memo(d)}function We(e){\"production\"!==process.env.NODE_ENV&&\"undefined\"!=typeof navigator&&\"ReactNative\"===navigator.product&&console.warn(\"`keyframes` cannot be used on ReactNative, only on the web. To do animation in ReactNative please use Animated.\");for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r\"+t+\"\"},this.getStyleTags=function(){return e.sealed?D(2):e._emitSheetCSS()},this.getStyleElement=function(){var t;if(e.sealed)return D(2);var n=((t={})[N]=\"\",t[\"data-styled-version\"]=\"5.3.11\",t.dangerouslySetInnerHTML={__html:e.instance.toString()},t),o=Y();return o&&(n.nonce=o),[r.createElement(\"style\",y({},n,{key:\"sc-0-0\"}))]},this.seal=function(){e.sealed=!0},this.instance=new X({isServer:!0}),this.sealed=!1}var t=e.prototype;return t.collectStyles=function(e){return this.sealed?D(2):r.createElement(me,{sheet:this.instance},e)},t.interleaveWithNodeStream=function(e){return D(3)},e}(),Je=function(e){var t=r.forwardRef((function(t,n){var o=s(Me),i=e.defaultProps,a=Oe(t,o,i);return\"production\"!==process.env.NODE_ENV&&void 0===a&&console.warn('[withTheme] You are not using a ThemeProvider nor passing a theme prop or a theme in defaultProps in component class \"'+b(e)+'\"'),r.createElement(e,y({},t,{theme:a,ref:n}))}));return m(t,e),t.displayName=\"WithTheme(\"+b(e)+\")\",t},Xe=function(){return s(Me)},Ze={StyleSheet:X,masterSheet:de};\"production\"!==process.env.NODE_ENV&&\"undefined\"!=typeof navigator&&\"ReactNative\"===navigator.product&&console.warn(\"It looks like you've imported 'styled-components' on React Native.\\nPerhaps you're looking to import 'styled-components/native'?\\nRead more about this at https://www.styled-components.com/docs/basics#react-native\"),\"production\"!==process.env.NODE_ENV&&\"test\"!==process.env.NODE_ENV&&\"undefined\"!=typeof window&&(window[\"__styled-components-init__\"]=window[\"__styled-components-init__\"]||0,1===window[\"__styled-components-init__\"]&&console.warn(\"It looks like there are several instances of 'styled-components' initialized in this application. This may cause dynamic styles to not render properly, errors during the rehydration process, a missing theme prop, and makes your application bigger without good reason.\\n\\nSee https://s-c.sh/2BAXzed for more info.\"),window[\"__styled-components-init__\"]+=1);export default qe;export{Ue as ServerStyleSheet,ue as StyleSheetConsumer,ce as StyleSheetContext,me as StyleSheetManager,Ge as ThemeConsumer,Me as ThemeContext,Le as ThemeProvider,Ze as __PRIVATE__,$e as createGlobalStyle,Ae as css,_ as isStyledComponent,We as keyframes,Xe as useTheme,A as version,Je as withTheme};\n//# sourceMappingURL=styled-components.browser.esm.js.map\n","/** @license React v16.13.1\n * react-is.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';var b=\"function\"===typeof Symbol&&Symbol.for,c=b?Symbol.for(\"react.element\"):60103,d=b?Symbol.for(\"react.portal\"):60106,e=b?Symbol.for(\"react.fragment\"):60107,f=b?Symbol.for(\"react.strict_mode\"):60108,g=b?Symbol.for(\"react.profiler\"):60114,h=b?Symbol.for(\"react.provider\"):60109,k=b?Symbol.for(\"react.context\"):60110,l=b?Symbol.for(\"react.async_mode\"):60111,m=b?Symbol.for(\"react.concurrent_mode\"):60111,n=b?Symbol.for(\"react.forward_ref\"):60112,p=b?Symbol.for(\"react.suspense\"):60113,q=b?\nSymbol.for(\"react.suspense_list\"):60120,r=b?Symbol.for(\"react.memo\"):60115,t=b?Symbol.for(\"react.lazy\"):60116,v=b?Symbol.for(\"react.block\"):60121,w=b?Symbol.for(\"react.fundamental\"):60117,x=b?Symbol.for(\"react.responder\"):60118,y=b?Symbol.for(\"react.scope\"):60119;\nfunction z(a){if(\"object\"===typeof a&&null!==a){var u=a.$$typeof;switch(u){case c:switch(a=a.type,a){case l:case m:case e:case g:case f:case p:return a;default:switch(a=a&&a.$$typeof,a){case k:case n:case t:case r:case h:return a;default:return u}}case d:return u}}}function A(a){return z(a)===m}exports.AsyncMode=l;exports.ConcurrentMode=m;exports.ContextConsumer=k;exports.ContextProvider=h;exports.Element=c;exports.ForwardRef=n;exports.Fragment=e;exports.Lazy=t;exports.Memo=r;exports.Portal=d;\nexports.Profiler=g;exports.StrictMode=f;exports.Suspense=p;exports.isAsyncMode=function(a){return A(a)||z(a)===l};exports.isConcurrentMode=A;exports.isContextConsumer=function(a){return z(a)===k};exports.isContextProvider=function(a){return z(a)===h};exports.isElement=function(a){return\"object\"===typeof a&&null!==a&&a.$$typeof===c};exports.isForwardRef=function(a){return z(a)===n};exports.isFragment=function(a){return z(a)===e};exports.isLazy=function(a){return z(a)===t};\nexports.isMemo=function(a){return z(a)===r};exports.isPortal=function(a){return z(a)===d};exports.isProfiler=function(a){return z(a)===g};exports.isStrictMode=function(a){return z(a)===f};exports.isSuspense=function(a){return z(a)===p};\nexports.isValidElementType=function(a){return\"string\"===typeof a||\"function\"===typeof a||a===e||a===m||a===g||a===f||a===p||a===q||\"object\"===typeof a&&null!==a&&(a.$$typeof===t||a.$$typeof===r||a.$$typeof===h||a.$$typeof===k||a.$$typeof===n||a.$$typeof===w||a.$$typeof===x||a.$$typeof===y||a.$$typeof===v)};exports.typeOf=z;\n","//\n\nmodule.exports = function shallowEqual(objA, objB, compare, compareContext) {\n var ret = compare ? compare.call(compareContext, objA, objB) : void 0;\n\n if (ret !== void 0) {\n return !!ret;\n }\n\n if (objA === objB) {\n return true;\n }\n\n if (typeof objA !== \"object\" || !objA || typeof objB !== \"object\" || !objB) {\n return false;\n }\n\n var keysA = Object.keys(objA);\n var keysB = Object.keys(objB);\n\n if (keysA.length !== keysB.length) {\n return false;\n }\n\n var bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB);\n\n // Test for A's keys different from B.\n for (var idx = 0; idx < keysA.length; idx++) {\n var key = keysA[idx];\n\n if (!bHasOwnProperty(key)) {\n return false;\n }\n\n var valueA = objA[key];\n var valueB = objB[key];\n\n ret = compare ? compare.call(compareContext, valueA, valueB, key) : void 0;\n\n if (ret === false || (ret === void 0 && valueA !== valueB)) {\n return false;\n }\n }\n\n return true;\n};\n","\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\nexports.__esModule = true;\nexports.ScrollHandler = exports.ScrollContext = void 0;\nvar _assertThisInitialized2 = _interopRequireDefault(require(\"@babel/runtime/helpers/assertThisInitialized\"));\nvar _inheritsLoose2 = _interopRequireDefault(require(\"@babel/runtime/helpers/inheritsLoose\"));\nvar React = _interopRequireWildcard(require(\"react\"));\nvar _propTypes = _interopRequireDefault(require(\"prop-types\"));\nvar _sessionStorage = require(\"./session-storage\");\nfunction _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== \"function\") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }\nfunction _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== \"object\" && typeof obj !== \"function\") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== \"default\" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }\nvar ScrollContext = /*#__PURE__*/React.createContext(new _sessionStorage.SessionStorage());\nexports.ScrollContext = ScrollContext;\nScrollContext.displayName = \"GatsbyScrollContext\";\nvar ScrollHandler = /*#__PURE__*/function (_React$Component) {\n (0, _inheritsLoose2.default)(ScrollHandler, _React$Component);\n function ScrollHandler() {\n var _this;\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;\n _this._stateStorage = new _sessionStorage.SessionStorage();\n _this._isTicking = false;\n _this._latestKnownScrollY = 0;\n _this.scrollListener = function () {\n _this._latestKnownScrollY = window.scrollY;\n if (!_this._isTicking) {\n _this._isTicking = true;\n requestAnimationFrame(_this._saveScroll.bind((0, _assertThisInitialized2.default)(_this)));\n }\n };\n _this.windowScroll = function (position, prevProps) {\n if (_this.shouldUpdateScroll(prevProps, _this.props)) {\n window.scrollTo(0, position);\n }\n };\n _this.scrollToHash = function (hash, prevProps) {\n var node = document.getElementById(hash.substring(1));\n if (node && _this.shouldUpdateScroll(prevProps, _this.props)) {\n node.scrollIntoView();\n }\n };\n _this.shouldUpdateScroll = function (prevRouterProps, routerProps) {\n var shouldUpdateScroll = _this.props.shouldUpdateScroll;\n if (!shouldUpdateScroll) {\n return true;\n }\n\n // Hack to allow accessing this._stateStorage.\n return shouldUpdateScroll.call((0, _assertThisInitialized2.default)(_this), prevRouterProps, routerProps);\n };\n return _this;\n }\n var _proto = ScrollHandler.prototype;\n _proto._saveScroll = function _saveScroll() {\n var key = this.props.location.key || null;\n if (key) {\n this._stateStorage.save(this.props.location, key, this._latestKnownScrollY);\n }\n this._isTicking = false;\n };\n _proto.componentDidMount = function componentDidMount() {\n window.addEventListener(\"scroll\", this.scrollListener);\n var scrollPosition;\n var _this$props$location = this.props.location,\n key = _this$props$location.key,\n hash = _this$props$location.hash;\n if (key) {\n scrollPosition = this._stateStorage.read(this.props.location, key);\n }\n\n /** If a hash is present in the browser url as the component mounts (i.e. the user is navigating\n * from an external website) then scroll to the hash instead of any previously stored scroll\n * position. */\n if (hash) {\n this.scrollToHash(decodeURI(hash), undefined);\n } else if (scrollPosition) {\n this.windowScroll(scrollPosition, undefined);\n }\n };\n _proto.componentWillUnmount = function componentWillUnmount() {\n window.removeEventListener(\"scroll\", this.scrollListener);\n };\n _proto.componentDidUpdate = function componentDidUpdate(prevProps) {\n var _this$props$location2 = this.props.location,\n hash = _this$props$location2.hash,\n key = _this$props$location2.key;\n var scrollPosition;\n if (key) {\n scrollPosition = this._stateStorage.read(this.props.location, key);\n }\n\n /** There are two pieces of state: the browser url and\n * history state which keeps track of scroll position\n * Native behaviour prescribes that we ought to restore scroll position\n * when a user navigates back in their browser (this is the `POP` action)\n * Currently, reach router has a bug that prevents this at https://github.com/reach/router/issues/228\n * So we _always_ stick to the url as a source of truth — if the url\n * contains a hash, we scroll to it\n */\n\n if (hash) {\n this.scrollToHash(decodeURI(hash), prevProps);\n } else {\n this.windowScroll(scrollPosition, prevProps);\n }\n };\n _proto.render = function render() {\n return /*#__PURE__*/React.createElement(ScrollContext.Provider, {\n value: this._stateStorage\n }, this.props.children);\n };\n return ScrollHandler;\n}(React.Component);\nexports.ScrollHandler = ScrollHandler;\nScrollHandler.propTypes = {\n shouldUpdateScroll: _propTypes.default.func,\n children: _propTypes.default.element.isRequired,\n location: _propTypes.default.object.isRequired\n};","\"use strict\";\n\nexports.__esModule = true;\nexports.getForwards = getForwards;\nfunction getForwards(collectedScripts) {\n return collectedScripts === null || collectedScripts === void 0 ? void 0 : collectedScripts.flatMap(script => (script === null || script === void 0 ? void 0 : script.forward) || []);\n}\n//# sourceMappingURL=get-forwards.js.map","function _setPrototypeOf(t, e) {\n return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {\n return t.__proto__ = e, t;\n }, _setPrototypeOf(t, e);\n}\nexport { _setPrototypeOf as default };","import escapeStringRegexp from \"escape-string-regexp\";\nimport { withPrefix } from \"gatsby\";\nexport const userIsForcingNavigation = event => event.button !== 0 || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;\n\n// IE does not include leading slash in anchor.pathname\nexport const slashedPathname = pathname => pathname[0] === `/` ? pathname : `/${pathname}`;\nexport const navigationWasHandledElsewhere = event => event.defaultPrevented;\nexport const findClosestAnchor = node => {\n for (; node.parentNode; node = node.parentNode) {\n if (node.nodeName.toLowerCase() === `a`) {\n return node;\n }\n }\n return null;\n};\nexport const anchorsTargetIsEquivalentToSelf = anchor => /* If target attribute is not present it's treated as _self */\nanchor.hasAttribute(`target`) === false ||\n/**\n * The browser defaults to _self, but, not all browsers set\n * a.target to the string value `_self` by default\n */\n\n/**\n * Assumption: some browsers use null/undefined for default\n * attribute values\n */\nanchor.target == null ||\n/**\n * Some browsers use the empty string to mean _self, check\n * for actual `_self`\n */\n[`_self`, ``].includes(anchor.target) ||\n/**\n * As per https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-target\n */\nanchor.target === `_parent` && (!anchor.ownerDocument.defaultView.parent ||\n// Assumption: This can be falsey\nanchor.ownerDocument.defaultView.parent === anchor.ownerDocument.defaultView) || anchor.target === `_top` && (!anchor.ownerDocument.defaultView.top ||\n// Assumption: This can be falsey\nanchor.ownerDocument.defaultView.top === anchor.ownerDocument.defaultView);\nexport const authorIsForcingNavigation = anchor =>\n/**\n * HTML5 attribute that informs the browser to handle the\n * href as a downloadable file; let the browser handle it\n */\nanchor.hasAttribute(`download`) === true ||\n/**\n * Let the browser handle anything that doesn't look like a\n * target=\"_self\" anchor\n */\nanchorsTargetIsEquivalentToSelf(anchor) === false;\n\n// https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy\nexport const urlsAreOnSameOrigin = (origin, destination) => origin.protocol === destination.protocol && /* a.host includes both hostname and port in the expected format host:port */\norigin.host === destination.host;\nexport const pathIsNotHandledByApp = (destination, pathStartRegEx) => {\n const pathFileExtensionRegEx = /^.*\\.((?!htm)[a-z0-9]{1,5})$/i;\n return (\n /**\n * For when pathPrefix is used in an app and there happens to be a link\n * pointing to the same domain but outside of the app's pathPrefix. For\n * example, a Gatsby app lives at https://example.com/myapp/, with the\n * pathPrefix set to `/myapp`. When adding an absolute link to the same\n * domain but outside of the /myapp path, for example, `` the plugin won't catch it and\n * will navigate to an external link instead of doing a pushState resulting\n * in `https://example.com/myapp/https://example.com/not-my-app`\n */\n pathStartRegEx.test(slashedPathname(destination.pathname)) === false ||\n /**\n * Don't catch links pointed at what look like file extensions (other than\n * .htm/html extensions).\n */\n destination.pathname.search(pathFileExtensionRegEx) !== -1\n );\n};\nexport const hashShouldBeFollowed = (origin, destination) => destination.hash !== `` && (\n/**\n * Dynamically created anchor links (href=\"#my-anchor\") do not always\n * have pathname on IE\n */\ndestination.pathname === `` || /* Don't catch links pointed to the same page but with a hash. */\ndestination.pathname === origin.pathname);\nexport const routeThroughBrowserOrApp = (hrefHandler, pluginOptions) => event => {\n if (window.___failedResources) return true;\n if (userIsForcingNavigation(event)) return true;\n if (navigationWasHandledElsewhere(event)) return true;\n const clickedAnchor = findClosestAnchor(event.target);\n if (clickedAnchor == null) return true;\n if (authorIsForcingNavigation(clickedAnchor)) return true;\n\n // IE clears the host value if the anchor href changed after creation, e.g.\n // in React. Creating a new anchor element to ensure host value is present\n const destination = document.createElement(`a`);\n\n // https://html.spec.whatwg.org/multipage/links.html#concept-hyperlink-url-set\n // If clickedAnchor has no href attribute like `example`, the href getter returns empty string.\n if (clickedAnchor.href !== ``) {\n destination.href = clickedAnchor.href;\n }\n if (`SVGAnimatedString` in window && clickedAnchor.href instanceof SVGAnimatedString) {\n destination.href = clickedAnchor.href.animVal;\n }\n\n // In IE, the default port is included in the anchor host but excluded from\n // the location host. This affects the ability to directly compare\n // location host to anchor host. For example: http://example.com would\n // have a location.host of 'example.com' and an destination.host of\n // 'example.com:80' Creating anchor from the location.href to normalize the\n // host value.\n const origin = document.createElement(`a`);\n origin.href = window.location.href;\n if (urlsAreOnSameOrigin(origin, destination) === false) return true;\n\n // Regex to test pathname against pathPrefix\n const pathStartRegEx = new RegExp(`^${escapeStringRegexp(withPrefix(`/`))}`);\n if (pathIsNotHandledByApp(destination, pathStartRegEx)) return true;\n if (hashShouldBeFollowed(origin, destination)) return true;\n if (pluginOptions.excludePattern) {\n const excludeRegex = new RegExp(pluginOptions.excludePattern);\n if (excludeRegex.test(destination.pathname)) {\n return true;\n }\n }\n event.preventDefault();\n\n // See issue #8907: destination.pathname already includes pathPrefix added\n // by gatsby-transformer-remark but gatsby-link.navigate needs href without\n const destinationPathname = slashedPathname(destination.pathname).replace(pathStartRegEx, `/`);\n hrefHandler(`${destinationPathname}${destination.search}${destination.hash}`);\n return false;\n};\nexport default function (root, pluginOptions, cb) {\n const clickHandler = routeThroughBrowserOrApp(cb, pluginOptions);\n root.addEventListener(`click`, clickHandler);\n return () => root.removeEventListener(`click`, clickHandler);\n}","import { navigate } from \"gatsby\";\nimport catchLinks from \"./catch-links\";\nexport const onClientEntry = (_, pluginOptions = {}) => {\n catchLinks(window, pluginOptions, href => {\n navigate(href);\n });\n};","\"use strict\";\n\nexports.__esModule = true;\nexports.useScrollRestoration = useScrollRestoration;\nvar _scrollHandler = require(\"./scroll-handler\");\nvar _react = require(\"react\");\nvar _reachRouter = require(\"@gatsbyjs/reach-router\");\nfunction useScrollRestoration(identifier) {\n var location = (0, _reachRouter.useLocation)();\n var state = (0, _react.useContext)(_scrollHandler.ScrollContext);\n var ref = (0, _react.useRef)(null);\n (0, _react.useLayoutEffect)(function () {\n if (ref.current) {\n var position = state.read(location, identifier);\n ref.current.scrollTo(0, position || 0);\n }\n }, [location.key]);\n return {\n ref: ref,\n onScroll: function onScroll() {\n if (ref.current) {\n state.save(location, identifier, ref.current.scrollTop);\n }\n }\n };\n}","\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\n\nexports.__esModule = true;\nexports.onInitialClientRender = exports.wrapRootElement = void 0;\n\nvar _react = _interopRequireDefault(require(\"react\"));\n\nvar _reactRedux = require(\"react-redux\");\n\nvar _createStore = _interopRequireDefault(require(\"./.tmp/createStore\"));\n\nvar _constants = require(\"./constants\");\n\nvar wrapRootElement = function wrapRootElement(_ref, pluginOptions) {\n var _pluginOptions$window;\n\n var element = _ref.element;\n\n if (pluginOptions === void 0) {\n pluginOptions = {};\n }\n\n var preloadedState = window[(_pluginOptions$window = pluginOptions.windowKey) !== null && _pluginOptions$window !== void 0 ? _pluginOptions$window : _constants.DEFAULT_OPTIONS.windowKey];\n var store = (0, _createStore.default)(preloadedState);\n return /*#__PURE__*/_react.default.createElement(_reactRedux.Provider, {\n store: store\n }, element);\n};\n\nexports.wrapRootElement = wrapRootElement;\n\nvar onInitialClientRender = function onInitialClientRender(_, pluginOptions) {\n var _pluginOptions$cleanu;\n\n if (pluginOptions === void 0) {\n pluginOptions = {};\n }\n\n var shouldCleanup = Boolean((_pluginOptions$cleanu = pluginOptions.cleanupOnClient) !== null && _pluginOptions$cleanu !== void 0 ? _pluginOptions$cleanu : _constants.DEFAULT_OPTIONS.cleanupOnClient);\n\n if (shouldCleanup) {\n var _pluginOptions$window2;\n\n var windowKey = (_pluginOptions$window2 = pluginOptions.windowKey) !== null && _pluginOptions$window2 !== void 0 ? _pluginOptions$window2 : _constants.DEFAULT_OPTIONS.windowKey;\n delete window[windowKey];\n var preloadedStateEl = document.getElementById(_constants.SCRIPT_ELEMENT_ID);\n\n if (preloadedStateEl) {\n preloadedStateEl.parentNode.removeChild(preloadedStateEl);\n }\n }\n};\n\nexports.onInitialClientRender = onInitialClientRender;","'use strict';\n\nvar reactIs = require('react-is');\n\n/**\n * Copyright 2015, Yahoo! Inc.\n * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.\n */\nvar REACT_STATICS = {\n childContextTypes: true,\n contextType: true,\n contextTypes: true,\n defaultProps: true,\n displayName: true,\n getDefaultProps: true,\n getDerivedStateFromError: true,\n getDerivedStateFromProps: true,\n mixins: true,\n propTypes: true,\n type: true\n};\nvar KNOWN_STATICS = {\n name: true,\n length: true,\n prototype: true,\n caller: true,\n callee: true,\n arguments: true,\n arity: true\n};\nvar FORWARD_REF_STATICS = {\n '$$typeof': true,\n render: true,\n defaultProps: true,\n displayName: true,\n propTypes: true\n};\nvar MEMO_STATICS = {\n '$$typeof': true,\n compare: true,\n defaultProps: true,\n displayName: true,\n propTypes: true,\n type: true\n};\nvar TYPE_STATICS = {};\nTYPE_STATICS[reactIs.ForwardRef] = FORWARD_REF_STATICS;\nTYPE_STATICS[reactIs.Memo] = MEMO_STATICS;\n\nfunction getStatics(component) {\n // React v16.11 and below\n if (reactIs.isMemo(component)) {\n return MEMO_STATICS;\n } // React v16.12 and above\n\n\n return TYPE_STATICS[component['$$typeof']] || REACT_STATICS;\n}\n\nvar defineProperty = Object.defineProperty;\nvar getOwnPropertyNames = Object.getOwnPropertyNames;\nvar getOwnPropertySymbols = Object.getOwnPropertySymbols;\nvar getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;\nvar getPrototypeOf = Object.getPrototypeOf;\nvar objectPrototype = Object.prototype;\nfunction hoistNonReactStatics(targetComponent, sourceComponent, blacklist) {\n if (typeof sourceComponent !== 'string') {\n // don't hoist over string (html) components\n if (objectPrototype) {\n var inheritedComponent = getPrototypeOf(sourceComponent);\n\n if (inheritedComponent && inheritedComponent !== objectPrototype) {\n hoistNonReactStatics(targetComponent, inheritedComponent, blacklist);\n }\n }\n\n var keys = getOwnPropertyNames(sourceComponent);\n\n if (getOwnPropertySymbols) {\n keys = keys.concat(getOwnPropertySymbols(sourceComponent));\n }\n\n var targetStatics = getStatics(targetComponent);\n var sourceStatics = getStatics(sourceComponent);\n\n for (var i = 0; i < keys.length; ++i) {\n var key = keys[i];\n\n if (!KNOWN_STATICS[key] && !(blacklist && blacklist[key]) && !(sourceStatics && sourceStatics[key]) && !(targetStatics && targetStatics[key])) {\n var descriptor = getOwnPropertyDescriptor(sourceComponent, key);\n\n try {\n // Avoid failures from read-only properties\n defineProperty(targetComponent, key, descriptor);\n } catch (e) {}\n }\n }\n }\n\n return targetComponent;\n}\n\nmodule.exports = hoistNonReactStatics;\n","\"use strict\";\n\nexports.__esModule = true;\nexports.SessionStorage = void 0;\nvar STATE_KEY_PREFIX = \"@@scroll|\";\nvar GATSBY_ROUTER_SCROLL_STATE = \"___GATSBY_REACT_ROUTER_SCROLL\";\nvar SessionStorage = /*#__PURE__*/function () {\n function SessionStorage() {}\n var _proto = SessionStorage.prototype;\n _proto.read = function read(location, key) {\n var stateKey = this.getStateKey(location, key);\n try {\n var value = window.sessionStorage.getItem(stateKey);\n return value ? JSON.parse(value) : 0;\n } catch (e) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[gatsby-react-router-scroll] Unable to access sessionStorage; sessionStorage is not available.\");\n }\n if (window && window[GATSBY_ROUTER_SCROLL_STATE] && window[GATSBY_ROUTER_SCROLL_STATE][stateKey]) {\n return window[GATSBY_ROUTER_SCROLL_STATE][stateKey];\n }\n return 0;\n }\n };\n _proto.save = function save(location, key, value) {\n var stateKey = this.getStateKey(location, key);\n var storedValue = JSON.stringify(value);\n try {\n window.sessionStorage.setItem(stateKey, storedValue);\n } catch (e) {\n if (window && window[GATSBY_ROUTER_SCROLL_STATE]) {\n window[GATSBY_ROUTER_SCROLL_STATE][stateKey] = JSON.parse(storedValue);\n } else {\n window[GATSBY_ROUTER_SCROLL_STATE] = {};\n window[GATSBY_ROUTER_SCROLL_STATE][stateKey] = JSON.parse(storedValue);\n }\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[gatsby-react-router-scroll] Unable to save state in sessionStorage; sessionStorage is not available.\");\n }\n }\n };\n _proto.getStateKey = function getStateKey(location, key) {\n var stateKeyBase = \"\" + STATE_KEY_PREFIX + location.pathname;\n return key === null || typeof key === \"undefined\" ? stateKeyBase : stateKeyBase + \"|\" + key;\n };\n return SessionStorage;\n}();\nexports.SessionStorage = SessionStorage;","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-is.production.min.js');\n} else {\n module.exports = require('./cjs/react-is.development.js');\n}\n","function _arrayLikeToArray(r, a) {\n (null == a || a > r.length) && (a = r.length);\n for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];\n return n;\n}\nexport { _arrayLikeToArray as default };","import arrayWithoutHoles from \"./arrayWithoutHoles.js\";\nimport iterableToArray from \"./iterableToArray.js\";\nimport unsupportedIterableToArray from \"./unsupportedIterableToArray.js\";\nimport nonIterableSpread from \"./nonIterableSpread.js\";\nfunction _toConsumableArray(r) {\n return arrayWithoutHoles(r) || iterableToArray(r) || unsupportedIterableToArray(r) || nonIterableSpread();\n}\nexport { _toConsumableArray as default };","import arrayLikeToArray from \"./arrayLikeToArray.js\";\nfunction _arrayWithoutHoles(r) {\n if (Array.isArray(r)) return arrayLikeToArray(r);\n}\nexport { _arrayWithoutHoles as default };","function _iterableToArray(r) {\n if (\"undefined\" != typeof Symbol && null != r[Symbol.iterator] || null != r[\"@@iterator\"]) return Array.from(r);\n}\nexport { _iterableToArray as default };","import arrayLikeToArray from \"./arrayLikeToArray.js\";\nfunction _unsupportedIterableToArray(r, a) {\n if (r) {\n if (\"string\" == typeof r) return arrayLikeToArray(r, a);\n var t = {}.toString.call(r).slice(8, -1);\n return \"Object\" === t && r.constructor && (t = r.constructor.name), \"Map\" === t || \"Set\" === t ? Array.from(r) : \"Arguments\" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? arrayLikeToArray(r, a) : void 0;\n }\n}\nexport { _unsupportedIterableToArray as default };","function _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\nexport { _nonIterableSpread as default };","\"use strict\";\n\nexports.__esModule = true;\nexports.default = void 0;\nvar _gatsby = require(\"gatsby\");\n/**\n * Get a manifest filename depending on localized pathname\n *\n * @param {string} pathname\n * @param {Array<{start_url: string, lang: string}>} localizedManifests\n * @param {boolean} shouldPrependPathPrefix\n * @return string\n */\nvar _default = (pathname, localizedManifests, shouldPrependPathPrefix = false) => {\n const defaultFilename = `manifest.webmanifest`;\n if (!Array.isArray(localizedManifests)) {\n return defaultFilename;\n }\n const localizedManifest = localizedManifests.find(app => {\n let startUrl = app.start_url;\n if (shouldPrependPathPrefix) {\n startUrl = (0, _gatsby.withPrefix)(startUrl);\n }\n return pathname.startsWith(startUrl);\n });\n if (!localizedManifest) {\n return defaultFilename;\n }\n return `manifest_${localizedManifest.lang}.webmanifest`;\n};\nexports.default = _default;","'use strict';\n\nObject.defineProperty(exports, '__esModule', { value: true });\n\nconst PartytownSnippet = \"/* Partytown 0.7.6 - MIT builder.io */\\n!function(t,e,n,i,r,o,a,d,s,c,p,l){function u(){l||(l=1,\\\"/\\\"==(a=(o.lib||\\\"/~partytown/\\\")+(o.debug?\\\"debug/\\\":\\\"\\\"))[0]&&(s=e.querySelectorAll('script[type=\\\"text/partytown\\\"]'),i!=t?i.dispatchEvent(new CustomEvent(\\\"pt1\\\",{detail:t})):(d=setTimeout(f,1e4),e.addEventListener(\\\"pt0\\\",w),r?h(1):n.serviceWorker?n.serviceWorker.register(a+(o.swPath||\\\"partytown-sw.js\\\"),{scope:a}).then((function(t){t.active?h():t.installing&&t.installing.addEventListener(\\\"statechange\\\",(function(t){\\\"activated\\\"==t.target.state&&h()}))}),console.error):f())))}function h(t){c=e.createElement(t?\\\"script\\\":\\\"iframe\\\"),t||(c.setAttribute(\\\"style\\\",\\\"display:block;width:0;height:0;border:0;visibility:hidden\\\"),c.setAttribute(\\\"aria-hidden\\\",!0)),c.src=a+\\\"partytown-\\\"+(t?\\\"atomics.js?v=0.7.6\\\":\\\"sandbox-sw.html?\\\"+Date.now()),e.body.appendChild(c)}function f(n,r){for(w(),i==t&&(o.forward||[]).map((function(e){delete t[e.split(\\\".\\\")[0]]})),n=0;n {\n const { forward = [], ...filteredConfig } = config || {};\n const configStr = JSON.stringify(filteredConfig, (k, v) => {\n if (typeof v === 'function') {\n v = String(v);\n if (v.startsWith(k + '(')) {\n v = 'function ' + v;\n }\n }\n return v;\n });\n return [\n `!(function(w,p,f,c){`,\n Object.keys(filteredConfig).length > 0\n ? `c=w[p]=Object.assign(w[p]||{},${configStr});`\n : `c=w[p]=w[p]||{};`,\n `c[f]=(c[f]||[])`,\n forward.length > 0 ? `.concat(${JSON.stringify(forward)})` : ``,\n `})(window,'partytown','forward');`,\n snippetCode,\n ].join('');\n};\n\n/**\n * The `type` attribute for Partytown scripts, which does two things:\n *\n * 1. Prevents the `1. 운영체제의 개념과 구조

1. 운영체제의 개념과 구조

@jc, 023· September 03, 2025 · 10 min read

운영체제(OS, Operating System)

+

운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다.

+

+ + + img + +

+

운영체제가 없으면 어떻게 될까? 꼭 필요할까?

+
+

A computer is a machine that can be programmed to automatically carry out sequences of arithmetic or logical operations +(컴퓨터는 산술적 또는 논리적 연산(계산)의 순서를 자동으로 수행하도록 프로그래밍할 수 있는 기계이다). + - wikepedia

+
+

운영체제가 없다면 컴퓨터는 그저 하드웨어의 집합체에 불과하다. +사용자는 프로그램을 실행하기 위해서 매번 하드웨어를 직접 제어해야 하며, 이렇게 하는 것은 매우 비효율적일거다. +또한 직접 제어를 한다고 해도 하드웨어의 성능은 제한적이므로 이 환경에서 최대한의 성능을 끌어내기 위해 최적화라는 고통스러운 작업을 해야 할 것이다. +이러한 상황을 상상해보면 "배보다 배꼽이 더 크다"라는 말이 떠오른다.

+

실제로 운영체제라는 개념이 있기 전에는 사용자들이 하나의 작업을 위해 펀치카드를 소지하며 관리해야 했다. +그리고 단순 하드웨어에 올려 실행하는 과정의 방식이기에 한 번에 하나의 프로그램만 실행할 수 있었고, 해당 프로그램이 끝나야 다른 프로그램을 수행할 수 있었다. +지금처럼 복잡한 방식의 프로그램은 꿈도 꿀 수 없었을 것이다.

+

이러한 문제를 해결하기 위해 운영체제가 나왔고, 다음과 같은 목적을 지닌다.

+
    +
  • 사용자에게 컴퓨터의 프로그램을 쉽고 효율적으로 실행할 수 있는 환경을 제공한다.
  • +
  • 컴퓨터 시스템 하드웨어 및 소프트웨어 자원을 여러 사용자 간에 효율적 할당, 관리, 보호하는 것
  • +
  • 운영체제는 제어 프로그램으로서 사용자 프로그램의 오류나 잘못된 자원 사용을 감시하는 것과 입출력 장치 등의 자원에 대한 연산과 제어를 관리한다.
  • +
+

운영체제은 위와 같은 목적을 위해 다양한 방식을 가지고 있다.

+

일괄 처리 시스템 (Batch Operating System)

+

사용자의 개입없이 비슷한 작업들을 모아서 순차적으로 처리하는 방식이다. +한 작업이 끝나야 다음 작업이 실행되기 때문에 모든 작업이 완료될 때까지 기다릴 수 있는 환경에서 사용된다. +주로 대용량 데이터를 처리하거나 시간이 많이 소요되는 작업에 활용되며, 사용자의 개입이 필요하지 않고 반복적인 작업을 일괄적으로 처리할 수 있다.

+

다중 프로그래밍 시스템 (Multi Programming System)

+

이 방식은 CPU을 최대한 사용하고 하는 방식으로, +여러 응용프로그램을 메모리에 동시에 올라가 CPU가 쉬지 않고 여러 작업을 번갈아서 실행하며 항상 연산을 수행하는 상태로 활용하는 방식이다. +하나의 프로그램을 실행하는 동안 다른 프로그램은 대기하거나 I/O 작업 등을 수행하며 메모리에 올라간 상태로 대기하게 된다. +운영 체제는 이런 과정에서 CPU를 배분하는 작업 스케줄링과 CPU 스케줄링을 진행하며, +이를 통해 시스템 자원을 효율적으로 활용하고 응용 프로그램들이 서로 영향을 주지 않으면서 병렬적으로 실행된다.

+

시분할 시스템 (Time Sharing System)

+

이 방식은 CPU에 대해 일정 시간을 할당 받아 짧은 간격으로 번갈아 실행하는 방식이다. +다중 프로그래밍 시스템에서는 Context Switching(CPU 점유 권한 전환)이 I/O작업에서만 발생한다. +이를 통해서만 스케줄링을 할 경우 하나의 프로세스가 아주 오래 CPU를 독점하고 있는 상태가 발생할 수 있다는 문제점이 있다. +이를 해결하기 위한 것이 시분할 시스템으로, 다중 프로그래밍과 비슷하지만 모든 프로세스가 특정 시간만 CPU를 점유하고 다른 프로세스에 권한을 넘겨주는 방식으로 +Context Switching 기준 시간으로 시분할을 구현해서 RR(Round-Robin) 알고리즘으로 스케줄링을 한다.

+

대화형 시스템(Interactive System)

+

앞서 설명한 일괄 처리 시스템은 처리해야할 작업들을 한번에 정의하고 일괄적으로 처리하는 방식이었다. +이러한 일괄 처리 시스템의 문제점은 처리가 이루어지는 중에 시스템의 상태를 확인하기가 힘들고, +작업이 끝나 결과가 도출되기 전까지는 작업을 수정할 수도 없다는 문제점이 있었다. +이를 보완하기위해 등장한 시스템이 대화형 시스템으로, +작업 중에도 사용자가 데이터, 명령 또는 작업을 입력하면 컴퓨터가 즉각적으로 해당 입력에 응답하는 사용자와 컴퓨터 간의 상호작용을 통해 작동하는 방식이다.

+

커널(Kernel)

+

그럼 우리들의 컴퓨터 속 운영체제는 어떻게 이러한 기능을 수행하고 있을까?

+

운영체제의 이러한 핵심적인 부분을 담당하고 수행하는 것이 바로 커널이다.

+

+ + + img 3 + + +커널을 한글로 번역하면 핵심이다! 재밌지 아니한가? 아무튼 다시 돌아와서 커널은 어떻게 운영체제의 기능을 수행할까?

+

커널은 하드웨어를 인터페이스로 제공하여 여러 사용자 또는 여러 프로세스가 하드웨어 즉 리소스를 효율적으로 관리하며 작업을 수행할 수 있도록 해준다. +여기서 중요한 점은 커널은 사용자가 직접 제어할 수는 없다. +그 이유는 보안상 유저 어플리케이션이 함부로 운영체제의 리소스를 건들지 못하게 하기 위해서다. +그래서 커널에는 하드웨어에 접근이 허가된 커널모드와 그렇지 못한 유저모드로 분리가 되어있다.

+

+ + + img 1 + +

+

커널의 구조는 위 사진과 같은데, 간단한 흐름을 설명하자면 사용자가 유저모드인 어플리케이션을 실행하면서 발생하는 요청이 시스템 콜을 통해 커널 모드로 전환이 된다. +애플리케이션은 커널모드로 전환되었다가 작업을 끝낸 후 응답을 반환하면서 다시 유저모드로 되돌아 가게 된다. +여기서 시스템 콜은 뭐지 싶을텐데 어플리케이션의 요청이 커널에 접근해 시스템에 요청하는 것으로 간단히 유저모드에서 커널모드로 전환하는 것이라고 생각하면 된다.

+

+ + + img 4 + +

+

이러한 방식을 통해 사용자의 프로세스가 직접적으로 운영체제의 리소스를 함부로 변경하지 못하게 보호해준다.

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/hs2/index.html b/public/hs2/index.html new file mode 100755 index 0000000..b104829 --- /dev/null +++ b/public/hs2/index.html @@ -0,0 +1,398 @@ +2. 커널의 작동 방식

2. 커널의 작동 방식

@jc, 023· September 04, 2025 · 6 min read

앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다. +이제 커널이 어떻게 작동하는지 제대로 알아보자.

+

먼저 인터럽트(Interrupt)에 대해 알아야 한다.

+

+ + + + img_3.png + + +
img_3.png
+

+

컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데 +이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다. +이중 하나가 인터럽트이다.

+

+ + + img + + +인터럽트는 중단시키다라는 의미로 초인종과 같다고 할 수 있다. +즉, 인터럽트가 발생하면 잠깐 멈추고 다시 실행된다.

+

+ + + img 1 + +

+

실제 발생하는 대부분의 인터럽트는 I/O 인터럽트이다. +예를들면, 우리가 자바에서 print을 할 때 print라는 API를 파일이라는 인터페이스를 통해서 유저모드에서 커널 모드로 시스템 콜이 발생한다. +유저모드 API에서 커널모드 구성요소에서 시스템 콜이 이어지고 디바이스 드라이버를 제어하기 시작하는데 +이때 디바이스 드라이버가 인터럽트를 CPU에 요청한다. 이 행위를 IRQ라고 한다. +이러한 IRQ는 장치마다 다른 번호로 관리하게 된다. +아무튼 출력기기에 출력이 되면, 다시 역순으로 디바이스(하드웨어)에서 디바이스 드라이버로, +디바이스 드라이버에서 커널 모드로 해서 최종적으로 유저 모드로 다시 돌아오게 된다.

+

+ + + img 4 + + +이때, 이러한 행위 도중 wait을 걸면 블라킹(동기) 안걸면 논블라킹(비동기)으로 동작하게 된다.

+

인터럽트에는 우선순위가 있고 외부 인터럽트인지 내부 인터럽트인지에 따라 우선순위가 달라진다.

+

먼저, 외부 인터럽트로 내부 인터럽트보다 우선 시 된다.

+

그 중에서도 우선 순위가 있는데, 다음과 같다.

+
    +
  • 전원 이상 인터럽트: 말 그대로 정전 또는 파워 이상
  • +
  • 기계 착오 인터럽트: CPU의 기능적인 오류.
  • +
  • 외부 신호 인터럽트: 타이머 또는, 키보드 인터럽트 키(Ctrl + Alt + Delete). 외부장치로부터 인터럽트 요청이 있는 경우. I/O 인터럽트와 다른 개념이다.
  • +
  • 입출력 인터럽트: 입출력 장치가 데이터 전송을 요구하거나 전송이 끝나 다음 동작이 수행되어야 할 경우. 입출력 데이터에 이상이 있는 경우. 우리가 자주 다루게 될 인터럽트 부분이다.
  • +
+

이제 내부 인터럽트인데, 사실 우리가 주로 다루게 될 것은 외부 인터럽트에 있어 내부 인터럽트는 뭐가 있는지만 대강 본다.

+
    +
  • 명령어 잘못 인터럽트: 잘못된 명령어나 잘못된 데이터를 사용할 때 발생하며 Trap이라 부른다,
  • +
  • 프로그램 검사
  • +
  • 소프트웨어 인터럽트(=SVC, SuperVisor Call)
  • +
+

인터럽트 동작 순서에 대해 다시 살펴보면 다음과 같은데,

+
    +
  1. 인터럽트 요청
  2. +
  3. 프로그램 실행 중단
  4. +
  5. 현재 프로그램 상태 보존 -> PCB(Process Control Block), PC(Program Counter) 등
  6. +
  7. 인터럽트 서비스 루틴 실행: 인터럽트 처리 코드
  8. +
  9. 상태 복구
  10. +
  11. 중단 프로그램 실행 재개
  12. +
+

+ + + img 2 + +

+

이 과정에서 유저모드에서 커널모드로 넘어갈 떄 컨텍스트 스위칭이 되면서 오버헤드가 발생하는데 이로 인해 시스템 상 지연이 발생한다. +하지만 고성능 어플리케이션을 할 때 이 지연은 꽤나 치명적일 것이다. +그래서 위와 같이 DMA(Direct Memory Access)라는 기술을 사용하게 됐다. +예를들어, DirectX라는 것이 있는데 이는 게임을 할 때 이러한 컨텍스트 스위칭 되는 부분을 건너뛰어 직접 드라이버까지 가는 방식이 있다. +이렇듯 DirectX처럼 인터럽트 시 컨텍스트 스위칭으로 인한 오버헤드가 발생하면서 지연이 발생하는데 이걸 해소하는 것이 DMA인 것이다. +정리하자면, DMA는 RAM에 일정 부분을 예약해 불필요한 컨텍스트 스위칭을 스킵해 오버헤드 방지 및 지연을 획기적으로 줄이는 방식이다.

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/hs3/index.html b/public/hs3/index.html new file mode 100755 index 0000000..570e2d3 --- /dev/null +++ b/public/hs3/index.html @@ -0,0 +1,412 @@ +3. 프로세스

3. 프로세스

@jc, 023· September 08, 2025 · 12 min read

프로세스란?

+

+ + + img + +

+

컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 인스턴스를 의미합니다. +여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다.

+

프로세스의 메모리 공간

+

프로세스는 다음 4개의 메모리 영역으로 구성되고 가상 메모리 공간에 독립적으로 형성됩니다.

+
    +
  • 코드 영역(Code) : 프로그램 실행 코드가 적재되는 영역입니다. 읽기 모드만 지원합니다.
  • +
  • 데이터 영역(Data) : 프로세스의 초기화 된 데이터들인 전역 변수와 정적 변수들이 적재되는 영역입니다.
  • +
  • 힙 영역(Heap) : 런타임 동안 생성된 데이터를 보관하기 위해 동적으로 할당받는 영역입니다.
  • +
  • 스택 영역(Stack) : 지역변수, 매개변수, 리턴 값, 복귀 주소 등이 저장되는 영역입니다.
  • +
+

이렇게 영역이 나눠진 이유는 최대한 중복적인 데이터를 방지하여 메모리 사용량을 줄이는데 목적이 있습니다.

+
+

예를 들면, 코드에서 공통으로 사용하는 부분을 전역 변수로 지정하는 행위와 같다.

+
+

PCB(프로세스 제어 블록)

+

커널은 시스템 전체에 대해 레지스터에 하나의 프로세스 테이블을 두고 모든 프로세스의 정보를 관리합니다. +여기서의 프로세스 정보는 해당 프로세스를 실행하기 위해 필요한 정보들로 컨텍스트라고 부릅니다. +여기서 프로세스의 상태에 따라 프로세스를 교체하는 작업인 컨텍스트 스위칭 작업 이루어 지는데, +이와 같은 상황에서 여러 프로세스를 관리하기 위해 각 프로세스들에 대해 식별이 가능해야 관리가 가능하기에 해당 프로세스의 정보가 필요합니다.

+

예를 들어, 인터럽트가 발생해서 자원을 할당받은 프로세스가 대기 상태가 되고 다른 프로세스를 실행 상태로 올릴 때 +대기 중인 프로세스를 나중에 다시 수행하기 위해 대기 중인 프로세스의 상태와 같은 정보를 알아야 할 것입니다.

+

운영체제의 커널은 이러한 이유로 활성된 프로세스를 관리하기 위해 해당 프로세스에 대한 정보를 PCB(프로세스 제어 블록)이라는 데이터 구조에 저장합니다. +("PCB는 운영 체제가 프로세스를 표현한 것이다."라는 말도 있습니다.)

+

+ + + img 1 + +

+
+

PCB는 해당 프로세스가 실행되면 생성되어 종료 시 제거가 되는데 이 과정에서 PCB의 삽입 및 삭제가 용이한 연결 리스트(Linked List) 방식으로 관리됩니다.

+
+

Process Metadata

+

그럼 PCB에는 어떤 정보가 담겨있을까요? +PCB에는 아래와 같은 프로세스의 메타데이터들이 담겨져 있습니다.

+
    +
  • 프로세스 번호(PID, Process ID): 각 프로세스의 고유 식별 번호입니다.(PPID: 부모 프로세스 ID)
  • +
  • 프로세스 상태(Process State): 프로세스가 현재 어떤 상태인지를 나타내는 정보(new, ready, running, waiting, end)입니다.
  • +
  • 프로그램 카운터(PC, Program Counter): 이 프로세스에서 실행될 다음 명령어의 주소를 가리키는 포인터(주소)입니다.
  • +
  • 레지스터 상태(Register State): 프로세스의 레지스터 값 세트로, 프로세스를 다시 실행할 때 현재 상태를 복원하는 데 사용됩니다.
  • +
  • 스케줄링 정보(Scheduling Information): CPU 시간 스케줄링에 대한 정보입니다.
  • +
  • 메모리 관리 정보 (Memory Management Information): 프로세스의 메모리 할당과 사용에 관한 정보입니다.
  • +
  • 입출력 상태 (I/O Status): 프로세스가 입출력 작업을 수행 중인 경우, 해당 상태 정보 및 장치 정보입니다.
  • +
+

프로세스 상태

+

운영체제의 커널은 프로세스를 관리하기 위해 프로세스 정보를 알아야 해서 PCB를 생성하는 것을 알았습니다. +여기서 커널의 프로세스 관리는 프로세스 상태를 관리하는 것이기도 합니다.

+

프로세스 상태는 위에서 언급한대로 프로세스가 현재 어떤 상태인지를 나타내는 정보로, +프로세스의 상태에 따라 CPU를 할당하거나 대기 상태로 전환하는 등의 작업이 이루어집니다. +프로세스 상태는 일반적으로 다음과 같은 상태로 구분됩니다.

+

+ + + img 2 + +

+
    +
  • New(생성) : 프로세스는 저장장치에서 메모리로 로드되어 생성됩니다. 이후 커널은 메모리를 할당하고 PCB를 생성하고 프로세스 테이블에 등록합니다. 실행 준비를 마치면 ready 상태로 전이됩니다.
  • +
  • Ready(준비) : 프로세스가 CPU를 사용하고 있지는 않지만 언제든지 사용할 수 있는 상태로, 해당 상태의 프로세스들은 커널에 있는 준비 큐(우선순위 큐)에 들어갑니다. 스케줄러가 컨텍스트 스위칭을 수행할 때, 준비 큐에서 우선순위가 높은 프로세스가 CPU 스케줄링에 따라 리소스를 할당받아 running 상태로 전이(디스패치)됩니다.
  • +
  • Running(실행) : 프로세스가 CPU를 차지하여 명령어들이 실행되고 있는 상태입니다. 할당된 시간을 모두 사용(타임아웃)했다면 타이머 인터럽트가 발생되어 준비 상태로 전이되고, 입출력 요청이나 자원 요청 등으로 인해 대기 상태로 전이될 수도 있습니다.
  • +
  • Waiting(대기) : 프로세스 실행 도중 입출력 완료(주된 원인)와 같은 수신 등을 대기하는 상태를 말합니다.
  • +
  • End(=terminated, 종료) : 프로세스의 실행이 종료된 상태입니다. 이떄, PCB와 프로세스의 메모리를 해제 또는 정리합니다.
  • +
+

프로세스 계층 구조

+

프로세스는 실행 도중 시스템 콜을 통해 다른 프로세스를 생성할 수 있습니다. +이때 시스템 콜을 호출한 프로세스를 부모 프로세스, 생성된 프로세스를 자식 프로세스라 합니다.

+
+

서로 다른 프로세스라 서로 다른 PID를 가집니다. +일부 운영체제에서는 자식 프로세스의 PCB에 부모 프로세스의 PID (PPID)가 기록되기도 합니다.

+
+

프로세스 생성 기법은 복제와 교체 과정을 통한 방식을 사용합니다.

+

+ + + img 3 + +

+

흐름의 시작인 부모 프로세스는 fork(복제) 시스템 콜을 통해 자신의 복사본을 자식 프로세스로 생성합니다. +자식 프로세스는 exec(교체) 시스템 콜을 통해 자신의 메모리 공간을 다른 프로그램으로 교체합니다. +이때, 자식 프로세스의 메모리 공간을 새로운 프로그램으로 덮어쓰게 합니다.(코드/데이터는 내용만 바꾸고, 나머지는 초기화) +자식 프로세스가 exec 시스템 콜을 호출하지 않을 경우, 부모 프로세스와 자식 프로세스는 같은 코드를 병행하여 실행하는 프로세스가 됩니다. +이러한 과정을 통해 프로세스는 계층 구조를 이루어 관리할 수 있습니다.

+

많은 운영체제에서는 이처럼 프로세스를 낳는 계층적인 구조로써 프로세스들을 관리합니다. +컴퓨터가 부팅될 때 실행되는 최초의 프로세스가 자식 프로세스들을 생성하고, +생성된 자식 프로세스들이 새로운 프로세스들을 낳는 형식으로 여러 프로세스가 동시에 실행되는 것입니다.

+

프로세스 간 통신

+

앞서 언급했던 것처럼 프로세스는 서로 독립된 메모리 공간을 가지므로, 프로세스끼리는 서로의 영역에 접근 또는 간섭할 수 없습니다. +이러한 이유로 통신이 필요할 경우, IPC를 통해 프로세스 간에 통신을 할 수 있습니다. +IPC에는 공유 메모리를 이용한 통신과 파일을 통한 프로세스 간 통신 이렇게 두 가지 방법이 있습니다.

+
+

IPC 통신 시, 프로세스 간 데이터를 동기화하고 보호하기 위해 세마포어뮤텍스를 사용합니다.

+
@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/hs4/index.html b/public/hs4/index.html new file mode 100755 index 0000000..2b1b386 --- /dev/null +++ b/public/hs4/index.html @@ -0,0 +1,389 @@ +4. 쓰레드

4. 쓰레드

@jc, 023· September 08, 2025 · 7 min read

쓰레드란?

+

쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다.

+

+ + + img + +

+

그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다. +이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다.

+
+

사용자 수준 쓰레드와 커널 수준 쓰레드의 차이

+

사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다. +쓰레드와 관련된 모든 행위를 사용자 영역에서 하기 때문에, +커널은 사용자 수준 쓰레드의 존재를 알지 못하고 쓰레드 교환에 개입하지 않습니다. +커널 수준 쓰레드란, 커널이 직접 생성하고 관리하는 쓰레드를 의미합니다.

+
+

쓰레드의 메모리 공간

+

같은 프로세스의 쓰레드는 프로세스로부터 각각의 스택을 나눠갖지만 Code, Data, Heap 메모리 영역을 공유합니다. +하지만, 쓰레드 ID, 스택, PC나 레지스터 같은 쓰레드 컨텍스트에 대해서는 각기 다른 값을 가지고 있습니다.

+

+ + + img 1 + +

+

이렇게 각자의 PC, 레지스터, 스택을 가지고 있기에 쓰레드마다 독립적으로 실행할 수 있습니다.

+

여기서 중요한 점은 프로세스의 쓰레드들은 실행에 필요한 최소한의 정보(PC, 레지스터, 스택)만을 유지한 채 +프로세스 자원을 공유하며 실행된다는 점입니다.

+

TCB(쓰레드 제어블록)

+

쓰레드 또한 프로세스의 PCB(프로세스 제어 블록)처럼 TCB(쓰레드 제어 블록)을 통해 관리됩니다. +TCB는 각 쓰레드에 위치하고, 커널은 TCB를 통해 쓰레드를 관리합니다.

+

그럼 TCB에는 어떤 정보가 담겨있을까요? +TCB에는 아래와 같은 쓰레드의 메타데이터들이 담겨져 있습니다.

+

+ + + img 2 + +

+
    +
  • 쓰레드 번호(TID, Thread ID): 각 쓰레드의 고유 식별 번호입니다.
  • +
  • 스택 포인터 (Stack Pointer): 쓰레드가 존재하는 프로세스의 PCB에 대한 포인터
  • +
  • 프로그램 카운터(PC, Program Counter): 이 쓰레드에서 실행될 다음 명령어의 주소를 가리키는 포인터(주소)입니다.
  • +
  • 쓰레드 상태(Thread State): 쓰레드가 현재 어떤 상태인지를 나타내는 정보(new, ready, running, waiting, end)입니다.
  • +
  • 레지스터 상태(Register State): 쓰레드의 레지스터 값 세트입니다.
  • +
+

각 프로세스에 대한 중요 정보를 강조하는 특정 정보가 쓰레드 제어 블록에 저장됩니다.

+

프로세스와 쓰레드의 차이

+

프로세스는 각각 독립된 메모리 영역(Code, Data, Heap, Stack)을 할당받고 고유 프로세스 ID를 가지는 특성으로 인해, +프로세스끼리는 서로의 영역에 접근할 수 없습니다. +그래서 한 프로세스가 다른 프로세스의 자원에 접근하려면 IPC(inter-process communication)을 사용해야 합니다.

+

하지만, 쓰레드는 IPC와 같은 별도의 통신 방법 없이도 앞서 언급한 것처럼 프로세스의 Code, Data, Heap 메모리 영역을 공유합니다.

+

이처럼 프로세스들 사이의 통신에 대한 어려움 해소 및 빠른 컨텍스트 스위칭으로 인해 쓰레드가 프로세스보다 더 가벼운 실행 단위로 사용됩니다. +이로 인해 현대에 와서 운영체제의 실행단위는 프로세스에서 쓰레드로 바뀌어 가고 있습니다.

+

동시성 환경에서의 차이

+

동시성 환경에서는 어떤지 알아볼까요? +여러 프로세스를 동시에 실행하는 멀티 프로세스와 한 프로세스에서 여러 쓰레드를 동시에 실행하는 멀티 쓰레드가 있습니다.

+

+ + + img 3 + +

+

여기서 가장 큰 차이점은 프로세스끼리는 기본적으로 공유하지 않지만, 쓰레드끼리는 같은 프로세스 내의 자원을 공유한다는 점입니다.

+

즉, 멀티 프로세스는 여러 프로세스를 동시에 실행해 각각의 독립적인 프로세스 간 자원을 공유하지 않기 때문에 프로세스 간 통신 (IPC) 방식을 써야 합니다. +또한, 메모리에 동일한 내용들이 중복해서 존재하기 때문에 메모리에도 부담이 될 수 있습니다. +그러나 한편으로는 자원을 공유하지 않는 덕분에 하나의 프로세스에 문제가 생겨도 다른 프로세스들에는 문제가 발생하지 않는다는 장점이 있기도 합니다.

+

반면, 멀티 쓰레드는 실행에 필요한 최소한의 정보(PC, 레지스터, 스택)만을 유지한 채 프로세스 자원을 공유하며 실행되기에 +커널의 개입 없이 쓰레드간 통신을 할 수 있고, 메모리에도 부담이 덜합니다. +또한 fork로 인한 생성이 공유하는 부분을 제외한 부분만 복사하면 되기 때문에 프로세스보다 빠릅니다.(쓰레드가 접근하는 공유 데이터에 대해 동기화 작업을 수행해야 합니다) +
+하지만, 하나의 쓰레드에 문제가 생기면 같은 프로세스 내의 다른 쓰레드들에도 문제가 발생할 수 있다는 단점이 있습니다.

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/hs5/index.html b/public/hs5/index.html new file mode 100755 index 0000000..81a5572 --- /dev/null +++ b/public/hs5/index.html @@ -0,0 +1,397 @@ +5. CPU 스케줄링

5. CPU 스케줄링

@jc, 023· September 12, 2025 · 12 min read

기아 상태와 CPU 스케줄링

+

프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다. +그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나, +너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고 +이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다. +이를 컴퓨팅에서는 기아 현상이라고 하는데, +이로 인해 프로세스들에게 CPU 자원 할당을 배분해주는 CPU 스케줄링이 개발되었고, +운영체제에 반드시 필요로 하게 되었습니다.

+
+

기아 현상에 대한 대표적인 해결 방법은 에이징 기법을 이용하는 것입니다. +오랫동안 대기한 프로세스의 우선순위에 대해 가중치를 주어, +처음에 우선순위가 낮아도 언젠가는 우선순위가 높아져 기아 현상을 막을 수 있습니다. +이와 같이 CPU 스케줄링에서는 이러한 문제 해결을 위한 다양한 방식들이 있습니다.

+
+

프로세스 우선 순위

+

스케줄링을 지정하는 것은 순서를 지정하는 것과 같습니다. +그런데 어떻게 프로세스들 간의 순위를 공정하게 지원하고 있을까요?

+

순차방식

+

가장 단순하게 생각해보면 요청이 들어온 순서대로 할당하는 방식입니다. +그러나 이 방식은 빨리 처리해야 하는 프로세스가 있을 수 있는 상황에서 대응하지 못한다는 것입니다.

+

예시로 CPU를 많이 사용하는 프로세스가 I/O 작업을 하는 프로세스 보다 늦게 들어올 경우, +순서상으로는 뒤에 있어야 하지만, CPU 자원을 할당한다는 측면에서 볼 떄에는 앞 순위로 두는 것이 효울적일 것입니다.

+

우선순위 지정 방식

+

위 순차적인 방식이 아닌, 별도의 우선순위를 지정하는 방식도 있습니다. +이때, 우선순위에 대한 정보는 PCB에 저장이 됩니다.

+

이로 인해 프로세스의 중요도에 맞게 프로세스가 CPU를 이용할 수 있도록 운영체제가 부여하는 것이 우선순위이며, +운영체제는 PCB를 기반으로 어떤 프로세스가 CPU를 얼마나 사용하게 될 것인지 등을 결정합니다.

+

프로세스 우선순위는 간단한 명령어나 프로그램 등으로 확인이 가능한데, +일부 우선순위의 경우에는 사용자가 직접 설정 가능한 것도 있습니다.

+

스케줄링 큐

+

프로세스가 여러 개일 경우, 다음 CPU 자원을 이용할 프로세스를 선택하기 위해 매번 모든 프로세스들의 PCB를 다 뒤져보는 것은 매우 비효율적일 것입니다. +또한, CPU 말고도, 메모리, 입출력 장치를 사용하고자 하는 경우에도 비슷한 상황을 겪을 것입니다.

+

때문에 운영체제는 어떤 자원을 이용하고자 할 때 대기 하는 스케줄링 큐를 활용하고 있습니다.

+

이때, 큐라고 해서 반드시 선입선출(FIFO)에 국한되지 않습니다.

+

선점형 스케줄링과 비선점형 스케줄링

+

스케줄링 방식에는 선점형 스케줄링과 비선점형 스케줄링 방식이 있습니다.

+

선점형 스케줄링

+

선점형 스케줄링은 현재 CPU를 사용 중인 프로세스로부터 CPU 자원을 뺴앗아 요청한 프로세스에 할당하는 방법입니다. +어느 한 프로세스의 자원 독점을 막고 프로세스에 골고루 자원을 배분할 수 있으나, 그 만큼 컨텍스트 스위칭 과정에서 오버헤드가 발생할 수 있습니다.

+

비선점형 스케줄링

+

비선점형 스케줄링은 현재 CPU를 사용 중인 프로세스의 작업이 끝날 때까지 기다리는 방식입니다.

+

선점형 스케줄링과 반대되는 개념으로, 컨텍스트 스위칭에서 발생하는 오버헤드가 적지만, 한편으로는 모든 프로세스가 골고루 자원을 이용하기 어렵습니다.

+

CPU 스케줄링 알고리즘

+

선점형 스케줄링과 비선점형 스케줄링을 기반으로 다양한 CPU 스케줄링 알고리즘이 있습니다.

+

선입 선처리 스케줄링

+

FCFS(First Come First Served) 스케줄링으로, 준비 큐에 삽입된 순서대로 처리하는 비선점 스케줄링 방식입니다. +CPU를 먼저 요청한 프로세스부터 CPU를 할당합니다. +이로 인해 프로세스들이 기다리는 시간이 매우 길어질 수 있는 부작용이 있으며, +이를 convoy effect, 호위 효과라고 합니다.

+

최단 작업 우선 스케줄링

+

SJF(Shortest Job First) 스케줄링으로, +사용 시간이 긴 프로세스를 나중에 실행하고, +시간이 짧은 프로세스를 먼저 실행함으로써 평균 대기 시간을 줄일 수 있습니다. +이 알고리즘은 기본적으로는 비선점형 스케줄링 방식에 속하지만, +선점형과 비선점형 스케줄링 방식으로 모두 가능합니다.

+

라운드 로빈 스케줄링

+

RR(Round Robin) 스케줄링으로, +선입 선처리 스케줄링과 시분할 시스템의 타임 슬라이스(time slice) 개념이 결합된 방식입니디. +정해진 타임 슬라이스만큼의 시간 동안 돌아가며 CPU를 이용하게 하는 선점형 스케줄링입니다.

+

최소 잔여 시간 우선 스케줄링

+

SRT(Shortest Remaining Time) 스케줄링으로, +최단 작업 우선 스케줄링과 라운드 로빈 스케줄링이 결합된 형태입니다. +정해진 시간만큼 CPU를 이용하되, +다음으로 CPU를 사용할 프로세스로는 남은 작업 시간이 가장 적은 프로세스를 선택합니다.

+

우선순위 스케줄링

+

프로세스들에 우선순위를 부여하고, 우선순위가 높은 프로세스부터 실행하는 방식입니다. +우선순위가 같은 프로세스들은 선입 선처리 스케줄링으로 돌아가고, +최단 작업 우선 스케줄링이나 최소 잔여 시간 스케줄링은 포괄적인 의미에서 우선순위 스케줄링에 속한다고 할 수 있습니다.

+

다단계 큐 스케줄링

+

멀티 레벨 큐 스케줄링으로도 불리는데, 우선순위 스케줄링의 발전된 형태입니다. +우선순위 별로 준비 큐를 여러 개 사용하고, 우선순위가 높은 큐에 있는 프로세스를 먼저 실행합니다. +우선순위가 높은 큐가 비어 있다면, 그 다음 우선순위 큐에 있는 프로세스를 처리합니다. +이러한 방식은 프로세스 유형별로 우선순위를 구별하게 하여 관리가 쉬워집니다. +큐 별로 타임 슬라이스를 여러 개 지정할 수도 있고, 큐마다 다른 스케줄링 알고리즘을 사용할 수도 있습니다. +기본적으로 큐 간 이동이 불가능하기 때문에, 우선순위가 낮은 프로세스는 계속해서 우선순위가 낮을 수 밖에 없고, +그로 인해 기아 현상을 겪을 수도 있습니다.

+

다단계 피드백 큐 스케줄링

+

멀티 레벨 피드백 큐 스케줄링으로도 불리는 이 방식은 다단계 큐 스케줄링의 발전된 형태로, +큐 간 이동이 가능합니다. +새로 준비 상태로 된 프로세스가 있으면 가장 우선순위가 높은 큐에 삽입합니다. +일정 시간 즉, 타임 슬라이스 만큼 CPU를 사용할 수 있는데, +만약 작업이 끝나지 않았다면, +그때 우선순위가 다음으로 높은 곳에 삽입을 합니다. +작업을 많이 있는 프로세스일수록 우선순위가 점점 낮아지게 되고, +따라서 CPU 집중 프로세스는 상대적으로 우선순위가 낮아지고, 입출력 집중 프로세스는 높아지게 될 겁니다. +일정 시간 이상 낮은 우선순위에서 기다리고 있던 프로세스가 있었다면 이 프로세스의 우선순위를 점차 높임으로써 기아 현상을 방지할 수 있습니다. +다단계 피드백 큐 스케줄링은 CPU 사용 시간이 길면 우선순위가 점점 낮아지고, 동시에 어떤 프로세스가 낮은 우선순위 큐에서 너무 오래 기다리면 우선순위를 높일 수도 있습니다. +다단계 피드백 큐 스케줄링은 복잡하지만, CPU 스케줄링의 가장 일반적인 형태로 알려져 있습니다.

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/icons/icon-144x144.png b/public/icons/icon-144x144.png old mode 100644 new mode 100755 diff --git a/public/icons/icon-192x192.png b/public/icons/icon-192x192.png old mode 100644 new mode 100755 diff --git a/public/icons/icon-256x256.png b/public/icons/icon-256x256.png old mode 100644 new mode 100755 diff --git a/public/icons/icon-384x384.png b/public/icons/icon-384x384.png old mode 100644 new mode 100755 diff --git a/public/icons/icon-48x48.png b/public/icons/icon-48x48.png old mode 100644 new mode 100755 diff --git a/public/icons/icon-512x512.png b/public/icons/icon-512x512.png old mode 100644 new mode 100755 diff --git a/public/icons/icon-72x72.png b/public/icons/icon-72x72.png old mode 100644 new mode 100755 diff --git a/public/icons/icon-96x96.png b/public/icons/icon-96x96.png old mode 100644 new mode 100755 diff --git a/public/index.html b/public/index.html index d8f544b..8a2ae38 100644 --- a/public/index.html +++ b/public/index.html @@ -1,4 +1,4 @@ -CATCH NPE운영체제의 역할과 커널의 기능

운영체제의 역할과 커널의 기능

@jc, 023· September 04, 2025 · 5 min read

운영체제란 무엇일까?

+
+

운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원관리하고, +
프로세스를 관리하는 등 여러가지 일을 수행합니다.

+

이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다.

+

운영체제의 역할

+
+

하드웨어 관리

+
+

운영체제는 CPU, 메모리, 입출력 장치 등 컴퓨터 하드웨어 자원을 관리합니다. +
여기서 말하는 관리란 자원의 충돌을 방지하고 사용자가 하드웨어를 효율적으로 +사용하도록 처리하는것을 의미하게 됩니다.

+
+
+
+

프로세스 관리

+
+

프로세스의 생성과 종료 그리고 CPU 스케줄링을 통해 프로세스의 실행 시간을 관리합니다. +
멀티 태스킹환경에서 프로세스 전환을 관리합니다.

+
+
+
+

메모리 관리

+
+

각 애플리케이션에 충분한 메모리 공간을 할당하는 기능을 합니다. +
또한 가상 메모리를 통해 실제 메모리보다 큰 주소 공간을 제공합니다.

+
+

커널이란 무엇일까?

+
+

커널이란 운영체제의 핵심 기능을 담당하며, 커널은 하드웨어와 소프트웨어 애플리케이션 간 통신을 관리합니다. 커널의 대표적인 기능으로는 +
프로세스 관리, 메모리 관리, 파일 시스템, 입 출력 관리의 역할을 수행하게 됩니다.

+

위 설명 처럼 운영체제의 핵심기능을 커널이 많은 부분을 담당하기 때문에 이전에 설명한 운영체제의 기능이 커널의 기능이라고 생각하면 됩니다.

+

커널이 자원을 관리하는 이유

+
+
+

커널은 어떻게 충돌 없이 자원을 관리할까요?

+
+

이 질문에 대한 대답은 자원을 관리하는 지점을 커널을 통한 단일 진입점으로 만들게 되면서 해결 하게 됩니다. +

+
+

왜 자원을 커널을 통해서만 관리하게 설게 했을까요?

+
+

커널이 자원을 혼자 관리해야 하는 이유를 예시를 들어서 설명하겠습니다.

+

유치원 수업시간에 하나의 바구니에 테이프, 연필, 지우개와 같은 문구용품을 담아두고 선생님이 학생들에게 자율적으로 사용해도 된다고 하게 된다면 어떤일이 벌어질까요?

+

처음에는 아이들이 각자 필요한 문구 용품을 사용하겠지만 얼마 가지 않아서 연필을 찾는 학생, +
테이프를 가지고 누가먼저 쓸지 싸우는 학생, +
혹은 지우개를 망가뜨린 학생등 많은 사고가 있을 것입니다.

+

이러한 문제가 벌어지는 이유는 공용 문구를 사용할때 통제권이 모두에게 있기 떄문입니다. 그렇다면 이를 해결하기 위해서 +모두에게 있는 통제권을 하나로 합쳐서 해결하면 되는 문제이고 이것이 자원을 사용하기 위해 커널의 관리를 받아야 하는 이유입니다.

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc10/index.html b/public/jc10/index.html new file mode 100755 index 0000000..d0b60e1 --- /dev/null +++ b/public/jc10/index.html @@ -0,0 +1,418 @@ +멀티 프로세스와 멀티 쓰레드의 차이 및 장단점

멀티 프로세스와 멀티 쓰레드의 차이 및 장단점

@jc, 023· September 13, 2025 · 8 min read

+ + + + img.png + + +
img.png
+

+

멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술입니다. +보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해 +여러개의 프로세스를 생성하는 것입니다.

+
+
+

어떻게 멀티 프로세스를 생성할까?

+

멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부모 프로세스가 +여러개의 자식 프로세스를 생성합니다.

+

부모 프로세스는 자식 프로세스의 PID를 알고있으며 자식또한 PID와 PPID를 알고있어 +서로 통신이 가능합니다.

+

이런 성질은 각각 독립적이지만 통신이 가능하게 만들었고 멀티 프로세스의 대표적인 예가 +브라우저의 탭이라고 할 수 있습니다.

+

브라우저 탭은 문제가 발생해서 닫아야 하는 상황이여도 다른 탭까지 닫히지 않고 개별적으로 +운용을 할 수 있는걸 기억해보면 독립적이란 말을 더 잘 이해할 수 있을것이다.

+
+
+

멀티 프로세스의 장점

+
+
    +
  1. 안정성
  2. +
+

멀티 프로세스의 안정성은 각각의 프로세스가 독립적이기 떄문에 가능합니다. +대표적인 예로 좀전에 설명을 했던 특정 브라우저 탭이 문제가 발생하여 닫아야 하는 상황에서 +같은 브라우저의 다른 탭까지 닫히지는 않습니다. +이런것이 독립적인 성격에 의한 안정성이라고 할 수 있습니다.

+
+
+

멀티 프로세스의 단점

+
+
    +
  1. 문맥교환 (Context Switching) Overhead
  2. +
+

멀티 태스킹을 이루는 기술인 문맥 교환 과정에서 성능 저하가 발생할 수 있습니다. +프로세스를 컨텍스트 스위칭 하면, CPU는 다음 프로세스의 정보를 불러오기 위해 +메모리를 검색하고, CPU 캐시 메모리를 초기화하며, 프로세스 상태를 저장하고, +불러올 데이터를 준비해야 하기 떄문에, 빈번한 문맥교환이 발생하고 이 비용은 곧 오버헤드로 발생할 수 있습니다.

+
+
+
    +
  1. 자원 공유 비효율성
  2. +
+

프로세스는 독립적인 메모리를 가지고, 멀티 프로세스는 독립적인 메모리 공간의 합일 것입니다. +그렇기 때문에 메모리 비효율성을 초래합니다.

+
+
+

멀티 스레드

+
+

+ + + + img.png + + +
img.png
+

+
+

이전에 보았던 것처럼 스레드는 하나의 프로세스 내에 있는 실행 흐름입니다. +멀티 스레드는 하나의 프로세스 안에 여러개의 실행흐름을 가지는 것입니다. +멀티 스레드 또한 멀티 프로세스 처럼 여러개의 작업을 동시 실행 할 수 있습니다.

+

이전에 보았던 것처럼 멀티 프로세스는 브라우저의 여러개의 탭을 통해 예시를 들었습니다. +하지만, 멀티 스레드는 같은 브라우저라 할지라도 동일탭에 여러 실행 흐름을 말하게 되고 +예를들어 네트워크 처리 스레드, 검색 스레드 와 같이 동일한 프로세스 내 기능들을 말하게 됩니다.

+
+
+

멀티 스레드의 장점

+
+

프로세스보다 스레드가 가벼움

+

스레드는 프로세스보다 용량이 가볍다. 이유는 데이터, 코드, 힙 영역을 +프로세스와 공유해서 사용하기 때문에 내장된 정보다 프로세스보다 작기 떄문입니다. +그렇기 때문에 스레드를 제거하는 작업이 프로세스를 제거하는 작업보다 가볍습니다.

+
+
+

자원의 효율성

+

멀티 스레드는 하나의 프로세스 내에서 스택영역을 제외한 영역을 공유하기 때문에 +프로세스 간 통신을 사용하지 않고도 자원의 공유가 가능하여 자원을 효율적으로 사용할 수 있습니다.

+
+
+

Context Switching 비용 감소

+

스레드 문맥 교환 또한 오버헤드가 존재하지만, 프로세스 문맥교환과 비교했을 때, +상대적으로 오버헤드가 적습니다.

+

이유는 프로세스 컨텍스트 스위칭 비용은 스위칭할 때마다 CPU 캐시에 있는 내용을 모두 초기화하고, +새로운 프로세스 정보를 CPU 캐시에 적재해야 하기 떄문입니다. +하지만, 스레드 문맥교환은 스레드 개별적인 정보만 교체하면 되기 떄문에 비용이 상대적으로 낮습니다.

+
+
+

멀티 스레드의 단점

+

멀티 프로세스는 개별적인 작업으로 인해 독집적이고, 각자의 문제를 전파하지 않는다고 합니다.

+

하지만, 멀티 스레드는 하나의 스레드가 문제가 발생하면 다른 스레드들고 영향을 받아 전체가 종료가 될 수 있습니다.

+
+
+

데드락

+

데드락이란 하나의 자원을 사용하기위해 여러 곳에서 접근했고, 그상황에서 교착상태가 일어났을때 +여러대의 스레드가 서로 대기하면서 무한정 기다리는 현상을 데드락이라고 합니다.

+

예를들어, 스레드 1 은 자원 A을 점유하고 있는 상태에서 자원 B가 필요한 상황입니다. +그리고 스레드 2 는 자원 B를 점유하고 있는 상태에서 자원 A이 필요한 상황입니다. +하지만 스레드 1은 자원 B가 필요한 상황에서 자원 A을 빌려줄 수 있는 상황이 아니고, +스레드 2또한 자원 A이 필요한 상태에서 자원 B를 빌려줄 수 없는 상황인 것입니다. +이처럼 다수의 쓰레드가 같은 lock을 동시에, +다른 명령에 의해 획득하려 할 때 서로 절대 불가능한 일을 계속적으로 기다리는 상황을 이야기 합니다.

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc11/index.html b/public/jc11/index.html new file mode 100755 index 0000000..1588bec --- /dev/null +++ b/public/jc11/index.html @@ -0,0 +1,388 @@ +멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법

멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법

@jc, 023· September 14, 2025 · 4 min read

동시성 이슈란?

+
+
+

+ + + + img.png + + +
img.png
+

+
+

동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다.

+

예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다. +스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때 +스레드 a가 좋아요 카운트를 늘리면 11가 됩니다. 하지만 스레드 a와 b는 좋아요 카운트에 동시에 접근해서 초기값 10을 받은 상태라면 +스레드 b는 늘어난 11라는 숫자대신 10을 기준으로 값을 줄이게 됩니다. 그럼 최종 결과는 10이 아닌 9라는 값으로 나오게 됩니다.

+

이처럼 멀티 스레드 환경에서는 하나의 자원에 동시에 접근하게 되면 이러한 문제가 발생할 수 있습니다.

+
+
+

스레드 안전

+
+

그럼 우리가 추구해야 할 문제는 스레드 안전한 멀티 스레드 프로그래밍을 구현할 수 있어야 한다. 이것을 구현하는 +방법에 대해 이야기 하려고 합니다.

+
+
+

스레드 안전 여부 판단

+
+
    +
  1. 전역 변수나 힙, 파일과 같이 여러 스레드가 동시 접근 가능한 자원을 사용하는가
  2. +
  3. 핸들과 포인터를 통한 데이터의 간접 접근이 가능한가?
  4. +
  5. 부수 효과를 가져오는 코드가 있는가?
  6. +
+
+
+

스레드 안전을 지키기 위한 4가지 방법

+
+
    +
  1. 상호 배제(Mutual Exclusion)
  2. +
+
+
    +
  • 공유 자원에 하나의 Thread만 접근할 수 있도록 세마포어/ 뮤텍스락을 통제하는 방법입니다.
  • +
+
+
    +
  1. 원자 연산(Atomic Operation)
  2. +
+
+
    +
  • 공유 자원에 접근할 때 원자 연산을 이용하거나 원자적으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현하는 방법입니다.
  • +
  • Atomic +
      +
    • 공유 자원 변경에 필요한 연산을 원자적으로 분리한 뒤에 실제로 데이터의 변경이 이루어지는 시점에 Lock을 걸고,
    • +
    +데이터를 변경하는 시간 동안 다른 쓰레드의 접근이 불가능하도록 하는 방법입니다.
  • +
+
+
    +
  1. Thread-Local Storage (스레드 지역 저장소)
  2. +
+
+
    +
  • 공유 자원의 사용을 최대한 줄이고 각가의 쓰레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는 방법입니다.
  • +
  • 일반적으로 공유 상태를 피할 수 없을 때 사용하는 방식이며, 전역 변수 사용을 자제하라는 뜻으로 생각하면 됩니다.
  • +
+
+
    +
  1. Re-entrancy (재진입성)
  2. +
+
+
    +
  • 쓰레드 호출과 상관 없이 프로그램에 문제가 없도록 작성하는 방법입니다.
  • +
  • 어떤 함수가 한 스레드에 의해 호출되어 실행 중이라면 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 옳바르게 주어져야 합니다.
  • +
  • 쓰레드끼리 독립적으로 동작할 수 있도록 코드를 작성하는 것으로 생각하면 됩니다.
  • +
+
+
@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc12/index.html b/public/jc12/index.html new file mode 100755 index 0000000..f31792e --- /dev/null +++ b/public/jc12/index.html @@ -0,0 +1,398 @@ +CPU 스케줄링의 목적과 스케줄러의 종류

CPU 스케줄링의 목적과 스케줄러의 종류

@jc, 023· September 15, 2025 · 6 min read

CPU 할당?

+
+

지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용 +하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등 +CPU사용에 여러 변수가 있습니다.

+

한가지 의문점은, 누가? 어떻게? CPU를 할당하는지 배운적은 없습니다. +여기서 CPU라는 리소스에 대한 사용을 결정짓는건 운영체제입니다. +그리고 오늘 글의 주제인 CPU 스케줄링은 운영체제가 CPU라는 자원을 배분하는 행위를 지칭합니다.

+
+
+

CPU 스케줄링 우선순위

+
+

+ + + + img.png + + +
img.png
+

+

운영체제는 많은 프로세스에게 공정하게 CPU라는 공용자원을 배분하기 위해 고려해야 하는것이 우선순위 입니다. +우선순위라는 기준을 매겨야 하는 이유는 +운영체제는 어떤 프로세스는 당장 처리해야 할 중요성을 띄거나, IO작업이 많거나, CPU 사용시간 자체가 길거나처럼 각자의 사정이 있고, 이 사정 가운대 효율적으로 자원을 배분해야 하기 떄문입니다.

+
+

'우선순위가 높다'라는 표현은 CPU 사용에 우선권을 가집니다. 즉 먼저 처리되어야 한다 라는 뜻입니다. +대표적으로 우선순위가 높은 프로세스는 입출력이 많은 프로세스 입니다. +(입출력 처리가 많은 프로세스가 우선순위가 높은 이유는 아래에서 설명합니다.)

+

대부분의 프로세스는 I/O 작업과 CPU처리를 번갈아가면서 수행하게 됩니다. 이 말은 프로세스 상태 변화에서 실행, 대기를 번갈아 가면서 사용한다는 뜻입니다. +그렇지만 모든 프로세스가 동일한 비율로 I/O와 CPU처리를 하는것은 아닙니다. 여기서 CPU작업의 비율이 많다면 CPU 집중 프로세스라고 하게 되며, 반대로 I/O작업의 +비율이 많다면 입출력 집중 프로세스 라고 부르게 됩니다.

+

CPU집중 프로세스는 실행상태가 많고, 입출력 집중 프로세스는 대기 상태가 많으니 입출력 집중 프로세스를 빠르게 대기 상태로 넘겨주는 것이 CPU사용에 대해서 더 효율적인 +방법일것입니다. 그렇기 떄문에 입출력 처리가 많은 프로세스가 우선순위가 높습니다.

+

여담으로, CPU를 이용하는 작업을 CPU 버스트, 입출력을 이용하는 작업을 입출력 버스트라고 부르게 됩니다.

+
+
+

이러한 우선순위는 PCB에 기록됩니다. PCB 우선순위 기준으로 먼저 처리할 프로세스를 결정하고 처리하게 됩니다.

+
+
+

스케줄링 큐

+
+

+ + + + img.png + + +
img.png
+

+

우선순위는 PCB에 기록되지만, 운영체제가 매 CPU 할당 과정마다 PCB를 확인하고 결정하는건 비효율 적인 방식입니다. +그렇기 때문에 프로세스는 마치 '줄을 서는것'처럼 대기하게 됩니다. 이것을 스케줄링 큐라고 부르게 됩니다.

+
+

+ + + + img.png + + +
img.png
+

+
+

운영체제는 메모리로 적재되고 싶은 프로세스들을 큐에 삽입하여 줄을 세우고, CPU를 사용하고 싶거나, 특정 입출력장치를 사용하거 싶은 프로세스들을 줄세웁니다. +이 과정에서 사용할 자원에 따라 다른 큐에서 대기하게 됩니다.

+

운영체제가 관리하는 큐로는 준비큐대기큐로 이루어 져 있습니다. 준비 큐는 말그대로 CPU를 이용하고 싶은 프로세스들이 대기하게 되고,

+
+

+ + + + img.png + + +
img.png
+

+
+

대기 큐는 +입출력장치를 이용하기 위한 대기 상태에 돌입한 프로세스들이 서는 줄입니다. +큐에 들어와 있다고 해도 항상 순서대로 작동하는 것은 아니고 우선 순위를 고려합니다.

+
+

출처

+
+

이미지 출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc13/index.html b/public/jc13/index.html new file mode 100755 index 0000000..fb8e654 --- /dev/null +++ b/public/jc13/index.html @@ -0,0 +1,395 @@ +선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법

선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법

@jc, 023· September 16, 2025 · 5 min read

선점형? 비선점형? 개요

+
+

CPU 스케줄링은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다.

+

여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다.

+
+
+

선점형 스케줄링

+
+
+

선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다.

+
+

즉, 어떤 프로세스가 CPU라는 자원을 사용하고 있음에도 운영체제가 CPU를 사용중인 프로세스로부터 자원을 강제로 빼앗아 다른 프로세스에 할당할 수 있는 +스케줄링 방식을 의미합니다.

+

다르게 표현한다면 어떠한 프로세스도 CPU를 독점할 수 없다는 말입니다.

+

선점형의 예시중 하나는 지금까지 보았던, 특정 주기마다 CPU에 대한 할당 권한을 다른 프로세스에게 넘겨주는 방식이 있습니다.

+
+

+ + + + img.png + + +
img.png
+

+
+
+

비 선점형 스케줄링

+
+

비선점형 스케줄링이란 하나의 프로세스가 자원을 사용하고 있다면 그 프로세스가 종료되거나 +스스로 대기 상태에 접어들기 전까진 다른 프로세스가 끼어들 수 없는 스케줄링입니다.

+

다르게 표현한다면 특정 프로세스가 CPU를 사용하기 시작했다면 자원 사용을 독점할 수 있는 방식입니다.

+
+

+ + + + img.png + + +
img.png
+

+
+
+

선점, 비선점의 장 단점

+
+

대부분의 운영체제는 선점형 스케줄링를 사용중입니다. 그럼에도 비선점형 스케줄링를 사용하는 곳이 있는데 그것은 각자의 장 단점이 존재하기 때문입니다.

+
+
    +
  • 선점형 스케줄링 장점
  • +
+
+

선점형 스케줄링은 어는 한 프로세스의 자원 독점을 막고 프로세스들에 골고루 자원을 분배 할 수 있다는 장점이 있습니다.

+
+
+
    +
  • 선점형 스케줄링 단점
  • +
+
+

콘텍스트 스위칭이 빈번하기 떄문에 오버헤드가 많이 발생합니다.

+
+
+
+
    +
  • 비 선점형 스케줄링 장점
  • +
+
+

상대적으로 선점형 보다 콘텍스트 스위칭에 대한 오버헤드가 작게 발생합니다.

+
+
+
    +
  • 선점형 스케줄링 단점
  • +
+
+

하나의 프로세스가 작업이 끝나기를 기다려야 하기 때문에, 모든 프로세스가 골고루 자원을 사용할 수 없습니다.

+
+
+
+

기아 상태(Starvation)

+
+

기아 상태란 우선순위가 밀린 프로세스가 영원히 자신의 우선순위까지 순서가 오지 못해 실행되지 못하는 상태를 기아 상태라고 합니다.

+
+
+

기아 상태 해결법

+
+

이러한 기아 상태를 해결하기 위한 방법으로는

+

에이징 기법을 활용하는 것입니다.

+

기아 상태가 발생하는 이유는 항상 자신보다 높은 우선순위를 가지는 프로세스가 존재하기 떄문입니다.

+

에이징 기법은 준비큐에서 대기가 길어진 프로세스들에게 우선순위를 조금씩 높여주는 방식을 사용합니다. +결국 조금씩 우선순위가 높아진다면 언젠가는 해당 프로세스가 실행될 수 있게 됩니다.

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc14/index.html b/public/jc14/index.html new file mode 100755 index 0000000..c1c15b5 --- /dev/null +++ b/public/jc14/index.html @@ -0,0 +1,450 @@ +CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)

CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)

@jc, 023· September 17, 2025 · 7 min read

스케줄링 알고리즘 개요

+
+

스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다.

+
+
    +
  • 비선점 스케줄링 +
      +
    • 선입 선처리 스케줄링 (FCFS)
    • +
    • 최단 작업 우선 스케줄링 (SJF)
    • +
    +
  • +
+
+
    +
  • 선점 스케줄링 +
      +
    • 라운드 로빈 스케줄링
    • +
    • 최소 잔여 시간 우성 스케줄링 (SRT)
    • +
    • 우선순위 스케줄링
    • +
    +
  • +
+
+

비 선점 스케줄링

+
+
+

선입 선처리 스케줄(FCFS)

+
+

+ + + + img.png + + +
img.png
+

+
+

FCFS는 준비 큐에 들어가있는 순서대로 CPU를 할당하는 간단한 스케줄링 입니다.

+

하지만, FCFS 방식에는 호위 효과라는 문제가 있습니다.

+

그림을 보면 프로세스 A, B, C순서대로 실행되며 각각 실행 시간이 17, 5, 2 ms가 걸리게 됩니다. +이상황에서 프로세스 B는 실행 상태가 되기 위해 최소 17ms를 기다려야 하며, 프로세스 c는 22ms를 기다리게 됩니다.

+
+

이러한 현상을 호위 효과(Convoy effect) 라고 하며 이것이 FCFS 스케줄링의 단점입니다.

+
+
+
+

하지만, 이러한 FCFS 방식도 배치 처리 시스템이나 작업 길이가 거의 비슷하고 사용자와 상호 작용이 필요하지 않는 환경에는 +적합하며, 멀티프로그래밍이나 실시간 시스템에서는 부적합합니다.

+
+
+

최단 작업 우선 스케줄링(SJF)

+
+

+ + + + img.png + + +
img.png
+

+
+

최단작업 우선 스케줄링(SJF)는 이전 FCFS방식에서 호위 효과를 억제하기 위해 사용하는 방식입니다.

+

호위 효과는 실행시간이 긴 프로세스 때문에 다른 프로세스가 기다리는 시간이 길다는 문제가 있고, +이러한 문제를 실행시간이 짧은 프로세스를 먼저 시행되게 하여 해결하는 방식입니다.

+

그림을 통해 보면 FCFS방식의 평균 대기시간은 13ms인 반면에 SJF방식의 편균대기 시간은 3ms로 줄어든것을 +확인할 수 있습니다.

+
+

즉 SJF방식은 호위효과를 줄여 프로세스들의 평균대기시간을 줄이는 방법으로 이해하면 됩니다.

+
+

하지만, 이러한 방식도 문제가 있는데, 실행 시간이 긴 프로세스가 기아상태에 빠지기 쉽다는 것입니다.

+

이러한 방식은 평균 대기 시간을 중요하게 여기는 시스템에 적합하며, 실시간 시스템이나 사용자 대화형 시스템에 부적합하게 됩니다.

+
+
+

선점 스케줄링

+
+
+

라운드 로빈 스케줄링

+
+

+ + + + img.png + + +
img.png
+

+
+

라운드 로빈 스케줄링은 선입 선처리 방식(FCFS)방식에서 타임 슬라이스가 더해진 방식입니다. +여기서 말하는 타임 슬라이스는 CPU를 사용할 수 있는 정해진 시간을 의미합니다.

+

그림에서처럼 타임 슬라이스가 4ms이면 한번에 4ms까지 CPU를 할당받을 수 있고, 그 이후는 큐 가장 뒤로 들어가며 +콘텍스트 스위칭이 일어나게 됩니다.

+
+
+

라운드 로빈 방식의 중요한 포인트는 슬라이스 크기입니다.

+
+

만약 슬라이스 크기가 지나치게 크다면 FCFS방식과 다를게 없을 것이고, 지나치게 작다면 콘텍스트 스위칭으로 인한 +오버헤드가 많이 발생할 것입니다.

+
+
+

최소 잔여 시간 우선 스케줄링 (SRT)

+
+

+ + + + img.png + + +
img.png
+

+
+

최단 작업 우선 알고리즘(SJF) 그리고 라운드 로빈 알고리즘을 합친 형태입니다. +즉 작업 시간이 짧은 프로세스를 먼저 실행하되, 타임슬라이스 보다 큰 프로세스는 다시 큐 뒤로 보내고 작업을 이어가는 방식입니다.

+

위 알고리즘은 특이한 점이 있어서 상세히 설명하겠습니다.

+
+

SRT 동작 방식

+
    +
  1. 새로운 프로세스가 도착하면 그 프로세스의 남은 실행 시간을 계산합니다
  2. +
  3. 준비 큐에 있는 프로세스 중에서 현재 실행 중인 프로세스를 포함하여 가장 짧은 실행 시간을 가진 프로세스에 CPU를 할당합니다
  4. +
  5. 만약 새로운 프로세스가 도착하고 현재 실행 중인 프로세스 보다 남은 실행 시간이 더 짧다면 현재 프로세스는 중단되고 CPU는 새 프로세스에 할당되는 '선점'이 발생합니다.
  6. +
  7. 선점이 발생하면 운영체제는 콘텍스트 스위칭으로 CPU자원을 현재 프로세스에서 새 프로세스로 교체합니다.
  8. +
  9. 선점된 프로세스는 준비 큐로 이동합니다.
  10. +
+
+

SRT또한 SJF와 비슷한 장 단점을 공유하는데, 평균 대기 시간을 최소화 하는 장점을 가지지만, 작업 시간이 긴 +프로세스는 CPU 할당을 받기 어렵다는 단점이 있습니다.

+
+
+

우선 순위 스케줄링

+
+

우선순위 스케줄링은 우선순위를 부여하고, 가장 높은 우선순위를 가진 프로세스부터 실행하는 알고리즘 입니다. +만약 같은 우선순위가 있다면 선입 선처리로 처리 됩니다.

+

이러한 우선순위 알고리즘 방식은 기아(Starvation) 현상을 동반하며 이는 에이징 방식으로 해결가능 하다고 이전 파트에서 설명했으니 +넘어가겠습니다.

+

출처

+
+

이미지 출처

+

SRT 출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc15/index.html b/public/jc15/index.html new file mode 100755 index 0000000..f3e869d --- /dev/null +++ b/public/jc15/index.html @@ -0,0 +1,367 @@ +멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링

멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링

@jc, 023· September 18, 2025 · 5 min read

다단계 큐 스케쥴링(Multilevel queue scheduling)

+
+

멀티 레벨 스케줄링은 우선순위 스케줄링의 발전된 형태입니다. +아래 그림을 통해 설명 하면,

+
+

+ + + + img.png + + +
img.png
+

+
+

이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데, +멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다.

+

가장 높은 우선순위에 있는 큐들을 처리하고, 가장 높은 우선순위 큐가 비게 된다면 그 아래 우선순위의 큐를 처리하게 됩니다. +그림을 통해 이해하자면, 우선순위 0 -> 우선순위 1 -> 우선순위 2 이렇게 처리하게 되는것입니다.

+

멀티레벨 큐의 특징으로는 각각의 큐들을 개별적으로 핸들링 할 수 있습니다. +예를들어, 특정 큐의 타임 슬라이드와 다른 큐의 타임 슬라이드를 다르게 처리 한다던가, 혹은 스케줄링 방식 자체를 +FCFS를 적용하고 다른 곳에서는 라운드로빈을 적용하는것 처럼 개별적인 핸들링이 가능합니다.

+
+
+

다단계 큐 스케쥴링 문제점

+
+

다단계 큐 스케줄링의 문제점으로는 기아 현상이 있습니다.

+

멀티레벨 큐 방식에서는 큐간의 이동이 불가능합니다. 그렇기 떄문에 우선순위가 낮은 곳에 배정받은 프로세스들은 +이전에 보았던 에이징방식을 사용할수 없습니다. 그렇기 때문에 이러한 방식은 우선순위가 올때 까지 기다려야 하는 +기아 현상을 문제로 가지고 있습니다.

+

이러한 방식의 해결법은 아래 설명할 다단계 피드백 큐 스케줄링으로 해결이 가능합니다.

+
+
+

다단계 피드백 큐 스케줄링(multilevel feedback queue scheduling)

+
+

+ + + + img.png + + +
img.png
+

+
+

다단계 피드백 큐 스케줄링 같은경우는 프로세스들이 큐 사이로 이동할 수 있습니다. 그렇기 때문에 이전 방식에서 보았던 +기아현상을 직접적으로 해결할 수 있습니다.

+
+

다단계 피드백 큐 스케줄링 특징

+

이러한 이동가능한 점 때문에 멀티 레벨 큐와 다른 점이 있습니다. +멀티 레벨 피드백 큐는 처음 생성된 프로세스가 우선순위가 가장 높은 큐로 삽입이 됩니다. 그 이후 CPU를 할당받고 +타임슬라이드 동안 실행되며, 이 실행이 끝나게 된다면 다음 우선순위 큐로 넘어 갑니다(우선순위가 낮아짐). 또 다음 우선순위 +큐에서 실행이 끝나지 않는다면 또 다음 우선순위로 넘어가고 이 과정을 반복합니다.

+

이렇게 우선순위가 낮아지는 방식을 사용함으로써 자동으로 CPU 버스트가 많은 프로세스는 우선순위가 낮아지고, +IO 버스트가 많은 프로세스는 상대적으로 우선순위가 높아질것입니다.

+

기아 해결

+

또한, 프로세스들이 이동가능 하기 때문에 우선순위가 낮아져 기아상태에 빠진 프로세스에는 에이징기법을 적용해 +다시 우선순위를 높이게 됩니다.

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc16/index.html b/public/jc16/index.html new file mode 100755 index 0000000..9084108 --- /dev/null +++ b/public/jc16/index.html @@ -0,0 +1,415 @@ +병행성과 병렬성의 차이 및 프로세스 동기화의 필요성

병행성과 병렬성의 차이 및 프로세스 동기화의 필요성

@jc, 023· September 19, 2025 · 6 min read

병행성(Concurrency)

+
+

+ + + + img.png + + +
img.png
+

+

병행성은 다른 말로 동시성이라고 부르는 용어입니다. +이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 컨텍스트 스위칭을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다. +이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실행되는 것은 아닙니다.

+

동시성의 핵심 키워드는 동시에 처리되게 보이는것입니다.

+
+
+

병렬성(Parallelism)

+
+

+ + + + img.png + + +
img.png
+

+

병렬 처리는 프로그램의 독립적인 작업을 동시에 실행할 수 있는 능력입니다. 이러한 작업은 +다른 프로세스 코어 단위에서, 혹은 분산 시스템 처럼 완전히 다른 컴퓨터에서 동시에 실행될 수 도 있습니다.

+

병렬성의 핵심 키워드는 실제로 동시에 처리되고 있는것입니다.

+
+
+

동기화

+
+

동시다발적으로 실행되는 프로세스들은 공동의 목적을 수행하기 위해 서로 협력하며 영향을 주고 받기도 합니다. +조금 전 설명했던 동시성, 병렬성 모두 동시다발적으로 수행되는 환경입니다.

+

이런 환경의 예시를 하나들면, 워드 프로세스가 있습니다. 해당 프로세스는 글을 쓸수도 있고, 쓰여진 글을 읽을 수도 있고, +맞춤법을 검사하는 기능도 있습니다. 하지만 해당 프로세스가 따로 동작하는 것이 아닌 모두 하나의 프로그램처럼 보여지고 있습니다.

+

이런 상황을 동시 다발적이란 표현을 통해 하고, 이런 동시 다발적인 상황의 수행 시기를 맞춰주는 것이 +동기화라고 합니다.

+
+

수행 시기를 맞추다?

+

이전에 설명한 수행 시기를 맞추다는 말은 추상적입니다.

+

이를 두가지 관점으로 볼 수 있습니다.

+
    +
  1. 실행 순서 제어: 프로세스를 올바른 순서대로 실행하는것
  2. +
  3. 상호 배제: 동시에 접근해서는 안 되는 자원에 하나의 프로세스만 접근하는 것
  4. +
+

다시 말해 동기화는 실행 순서를 제어하는 동기화와, 상호 배제를 위한 동기화가 있습니다.

+
+
+

1. 실행 순서를 제어하는 동기화

+
+

+ + + + img.png + + +
img.png
+

+

실행 순서를 제어한다는 것은 요리 레시피 순서를 지키는것과 같습니다. +재료를 준비하고, 손질하고, 요리하는 이런 일련의 과정을 지켜 보았을 때 +재료 손질이 준비보다 먼저일 수 없고, 요리또한 손질보다 먼저일 수 없습니다.

+

프로세스도 마찬가지로 무언가를 읽게 하였는데 읽은 대상이 생성 되어있고, 작성되어있어야 합니다. +이런 것을 실행 순서라고 표현하며 이것을 지키게 하는 것을 동기화라고 표현합니다.

+
+
+

2. 상호 배제를 위한 동기화

+
+

상호 배제란 공유가 불가능한 자원의 동시 사용을 피하기 위해 사용하는 알고리즘입니다. +여기서 말하는 공유가 불가능한 자원은 실제로 공유하면 안되는 자원이 아닌, 동시 사용하는 경우 문제가 발생하는 +자원입니다.

+

아래 예시를 통해서 보면

+

+ + + + img.png + + +
img.png
+

+

프로세스A는 현재 잔고에서 2만원을 더하고, 프로세스B는 현재 잔고에서 5만원을 더합니다. +이러한 경우 총합 7만원을 더하는 형태가 될것입니다.

+

하지만 프로세스A가 값을 더하고(12만원) 저장하기 전에 콘텍스트 스위칭이 일어난다면 다음 프로세스B는 +저장하기 전 값을 조회하고(10만원) 자신의 값을 저장할것 입니다(15만원). +다시 프로세스 A로 돌아오면 12만원을 저장하고 프로세스 B로 돌아오면 15만원을 저장합니다. +이과정에서 서로의 결과를 무시하는 방향으로 진행되고 최종적으로 마지막에 저장한 값은 다른 프로세스의 결과를 +반영하지 않는 상태가 됩니다.

+

이런 상황은 동시에 사용하는 자원에 대해 동기화를 이루지 못해서 발생한 경우이고, 이 경우 상호 배제를 위한 동기화 +를 진행해야 합니다.

+
+
+

출처

+
+

동시성, 병렬성 출처 +이미지 출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc17/index.html b/public/jc17/index.html new file mode 100644 index 0000000..173cc12 --- /dev/null +++ b/public/jc17/index.html @@ -0,0 +1,340 @@ +임계구역과 경쟁상태

임계구역과 경쟁상태

@jc, 023· September 20, 2025 · 2 min read

공유자원

+
+

동시에 실행되는 프로세스에서 공통으로 사용하는 자원을 우리는 공유자원이라고 부릅니다.

+
+
+

임계구역(Critical Section)

+
+

공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 임계 구역이라고 부릅니다.

+

두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한 프로세스의 +작업이 마무리되면 그제서야 기다렸던 프로세스가 임계 구역에 진입 합니다.

+

+ + + + img.png + + +
img.png
+

+
+
+

경쟁상태(Race Condition)

+
+

임계 구역은 두 개 이상의 프로세스가 동시에 실행되면 안 되는 영역이지만, 잘못된 실행으로 여러 프로세스가 +공유 자원을 사용하는 경우에 문제가 발생합니다. +이러한 문제를 경쟁 상태라고 합니다.

+

이러한 경쟁 상태는 데이터의 일관성이 깨지는 문제를 발생시킵니다.

+
+
+

운영체제가 임계구역 문제를 해결하는 세가지 원칙

+
+

1. 상호배제: 한 프로세스가 임계 구역에 진입했다면 다른 프로세스가 들어올 수 없다.

+

2. 진행: 임계구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세는 들어갈 수 있어야 한다.

+

3. 유한 대기: 한 프로세스가 임계구역에 진입하고 싶다면 언젠가는 임계구역에 들어갈 수 있어야 한다.(무한정 대기x)

+

출처

+
+

이미지 출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc18/index.html b/public/jc18/index.html new file mode 100755 index 0000000..8c877fe --- /dev/null +++ b/public/jc18/index.html @@ -0,0 +1,490 @@ +상호배제와 동기화 기법

상호배제와 동기화 기법

@jc, 023· September 21, 2025 · 11 min read

상호배제(Mutual Exclusion)

+
+

상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다.

+

일상생활에서 비유하면, 화장실 사용과 같습니다. +한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다. +컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 프로세스만 사용할 수 있어야 합니다.

+
+

왜 상호배제가 필요할까?

+

현대 운영체제는 멀티태스킹 환경에서 여러 프로세스가 동시에 실행됩니다. +이때 프로세스들이 공유하는 자원(메모리, 파일, 데이터베이스 등)에 동시에 접근하면 다음과 같은 문제가 발생할 수 있습니다.

+

1.경쟁 상황(Race Condition)

+

두 프로세스가 동시에 같은 데이터를 수정하려 할 때, 실행 순서에 따라 결과가 달라지는 상황입니다. +예를 들어, 은행 계좌 잔액을 동시에 업데이트하는 두 거래가 있다면, 최종 잔액이 예상과 다를 수 있습니다.

+

2. 데이터 일관성 파괴

+

여러 프로세스가 동시에 데이터를 수정하면 데이터의 무결성이 깨질 수 있습니다. 이는 시스템 전체의 신뢰성에 큰 영향을 미칩니다.

+
+
+

동기화 기법

+
+

이런 상호 배제에 대해 방지하는 방법으로는 뮤텍스, 세마포어, 모니터 기법이 있습니다.

+
+
+

뮤텍스 락(Mutex lock)

+
+

뮤텍스 락의 풀네임은 Mutual Exclusion Lock입니다. 즉 상호 배제 단어에 lock을 붙인 단어와 일치합니다.

+

이 말은 상호배제를 구현하기 위해 Locking방식을 사용하는 방법입니다.

+

뮤텍스 락은 화장실 사용에 비유해보겠습니다.

+

+ + + + img.png + + +
img.png
+

+
+

화장실은 한칸에 한사람만 받을 수 있습니다. 칸에 사람이 들어가있다면 해당 칸에 다른 사람이 들어올 수 없습니다. +다른 사람이 들어오는 시점은 먼저 사용하던 사람이 해당 칸을 나가게 되면 사용할 수 있습니다.

+

이 내용을 설명하는 이유는, 위 방식의 흐름이 뮤텍스 락과 동일하기 때문입니다.

+

간단한 뮤텍스락을 코드를 통해서 보겠습니다.

+

자물쇠에 해당하는 전역변수 하나, 그리고 해당 자물쇠를 잠구고, 푸는 두가지 함수만 있으면 구현가능합니다.

+
+
+
acquire(){
+    while (lock == true){
+        .....
+        }
+    
+    lock = true;
+}
+
release(){
+    lock = false;
+        }
+
+

해당 함수들은 차례대로 화장실 문이 잠겼는지 확인하고 잠기지 않았다면 들어가서 잠구는 함수 Acquire, +그리고 화장실을 나올때 잠금을 해제 하는 Release로 볼 수 있습니다.

+

이 함수를 아래 수도코드 처럼, 임계 구역 들어가기전, 나온 후 에 사용하게 되면

+
acquire();
+// 임계 구역
+release();
+

lock여부를 확인 한 후, 들어가도 되면 본인이 lock을 걸고 이미 lock이 걸려있다면 +임계 구역 코드 전에서 계속 기다리게 됩니다.

+
+

뮤텍스 락의 단점

+

하지만, 이런 방식에는 큰 문제가 있는데 바쁜대기(Busy Wait) 을 수행하게 됩니다. +명칭 그대로 대기를 하는 상황임에도 바쁘게 행동하는 것을 말하게 됩니다.

+

대기를 하는 상황에 행동을 하는것은 lock 확인작업에 CPU를 사용하겠다는 것을 의미하고, +이런 기다림은 해당 lock 이 풀릴떄까지 지속됩니다. 즉, 비효율적입니다.

+
+
+

세마포(semaphore)

+
+

세마포는 동기화 방식중 하나입니다. 뮤텍스 락과 비교하면 공유자원의 갯수를 다루는 방식이 다릅니다. +뮤텍스 락은 공유자원이 하나라고 가정하고 라킹을 수행하지만, 세마포는 공유 자원이 여러 개 있을경우 +각 프로세스는 해당 공유자원에 접근이 가능합니다.

+

마치 공중화장실에서 화장신 칸 수 만큼 공유자원이 있고, 각 칸에 사람이 들어가는 것을 관리하는 방식입니다.

+

+ + + + img.png + + +
img.png
+

+

세마포는 사진과 같은 철도 신호기에서 유래한 단어 입니다. 그렇기 때문에 철도 신호와 같은 방식을 사용합니다.

+

뮤텍스 락은 공유 자원을 잠금, 해제를 수행하면서 해당 자원을 관리하지만,

+

세마포의 경우 빨간불, 초록불 처럼 가도 되는지, 멈춰야 하는지 상태를 알려줍니다.

+

세마포도 간단하게 코드로 구현이 가능합니다.

+

먼저 공유자원의 갯수를 나타내는 전역 변수 한개와, 임계구역에 들어가도 되는지, 기다려야 할지 알려주는 함수 Wait, +그리고 기다리고 있는 프로세스에게 이제 출발하라를 나타내는 Signal함수가 있습니다.

+
+
wait() {
+    while(S <= 0){
+        
+        }
+    S--;
+}
+
signal() {
+    S++;
+}
+

위 코드를 차례대로 Wait, Signal함수를 구현한것이고 전역 변수 S의 값이 양수, 즉 사용해도 되는 +공유자원이 있을 경우 Wait함수의 while문을 탈출합니다.

+

그 경우 사용가능한 공유 자원 갯수를 하나 줄입니다.

+
wait();
+// 임계 구역
+signal();
+

임계 구역을 나오게 되면 signal이 수행될것이고, 사용가능한 자원을 하나 반납하게 될것입니다.

+
+

근데 while문이 있다면 뮤텍스락처럼 바쁜 대기 상태가 발생할 수 있다는걸 암시하게 됩니다. +하지만 이는 세마포가 CPU를 사용하지 않게 구현하며 해결할 수 있습니다.

+
+

세마포가 busy wait를 해결하는 방법

+
+

아래 두가지 함수를 통해서 세마포는 busy wait를 해결합니다.

+
wait(){
+    S--;
+    if ( S < 0){
+        add this process to Queue;
+        sleep();
+    }
+}
+
signal(){
+    S++
+    if ( S <= 0){
+        remove a process p from Queue;
+        wakeup(p);
+        }        
+}
+

위 방식은 이전처럼 while문을 통한 접근 가능여부를 체크하는 것이 아닌 만약 접근 불가능 한경우(사용가능한 공유 자원이 없을떄) +해당 프로세스의 PCB세마포를 위한 대기 큐에 넣습니다.

+

프로세스는 대기 큐에 들어가게 되면서 이후 해당 PCB준비 큐로 돌리기 전까지 CPU자원을 잡아 먹지 않게 됩니다.

+
+
+

모니터

+
+

세마포 기법 자체는 동기화도구로써 좋은 효능을 보여주지만, 사용자 측면에서 불편한 점이 있다. +임계 구역에 앞뒤로 wait, signal 함수를 사용하고 휴먼에러로 인한 실수가 발생한다면 예기치 못한 결과를 발생시킬 수 있기 때문이다.

+

이에 모니터라는 동기화 도구가 생기게 된다.

+

모니터는 공유 자원과, 공유 자원에 접근하기 위한 인터페이스를 묶어 관리합니다.

+
+

+ + + + img.png + + +
img.png
+

+
+

이를 위해 모니터를 통해 공유 자원에 접근하고자 하는 프로세스를 큐에 삽입하고, 큐에 삽입된 순서대로 하나씩 공유 자원을 이용하도록 합니다. +모니터는 공유 자원을 다루는 인터페이스에 접근하기 위한 큐를 만들고, 모니터 안에 항상 하나의 프로세스만 들어오도록 하여 상호 배제를 수행합니다.

+

또한, 모니터는 실행 순서를 제어하는 동기화 또한 수횅합니다. 조건 변수를 사용해서 실행 순서를 제어하게 됩니다.

+
+

+ + + + img.png + + +
img.png
+

+
+

해당 그림처럼 기존 상호 배제를 위한 큐가 아닌 조건 변수에 대한 큐가 있습니다. 이 조건 변수는 기존처럼 wait, signal 연산을 +수횅할 수 있습니다.

+

상호 배제를 위한 큐에서 가장 선두에 있는 프로세스A보다 특정 프로세스B가 더 먼저 시행되어야 한다면, B가 수행되기 전까지 앞선 프로세스들은 wait 연산을 통해 +조건 변수에 대한 큐에서 대기하게 되고, 그렇게 대기를 하게되면 최우선 시행되는 프로세스는 B가 될것입니다. 이런 형태로 모니터는 실행 순서를 제어합니다.

+

출처

+
+

이미지 출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc19/index.html b/public/jc19/index.html new file mode 100755 index 0000000..30070b4 --- /dev/null +++ b/public/jc19/index.html @@ -0,0 +1,432 @@ +교착상태와 해결 방법

교착상태와 해결 방법

@jc, 023· September 22, 2025 · 10 min read

교착상태란?(Dead Lock)

+
+

교착상태란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다.

+

교착상태를 설명하는 대표적인 예시로 식사하는 철학자 문제라는게 있습니다.

+
+

식사하는 철학자

+
+

+ + + + img.png + + +
img.png
+

+
+

식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습니다. +식사를 하려면 두개의 포크를 들어야 하는 상황입니다.

+

이를 순서도로 표현하면

+
    +
  1. 생각을 하다가 왼쪽 포크를 들 수 있다면 든다.
  2. +
  3. 생각을 하다가 오른쪽 포크를 들 수 있다면 든다.
  4. +
  5. 왼쪽, 오른쪽 포크를 모두 집어들면 정해진 시간동안 식사를 한다.
  6. +
  7. 식사 시간이 끝나면 오른쪽 포크를 내려놓는다.
  8. +
  9. 나머지 왼쪽 포크도 내려놓는다.
  10. +
  11. 1번부터 반복한다.
  12. +
+
+

위와같은 상황일때 모든 철학자가 왼쪽 포크를 들고 있거나, 반대쪽 포크를 들고 있다면 식사는 영원히 끝나지 않습니다. 이유는 포크라는 자원은 +철학자의 수만큼 존재하고 각 철학자는 두개의 포크를 원하는 상태에서 모든 포크를 얻을때까지 가디라기 떄문에, 모든 철학자가 포크를 기다리기만 하는 +상황이 발생합니다.

+

이러한 문제는 일어나지 않을 사건을 기다리며 진행이 멈춰 버리는 교착상태와 같습니다.

+

여기서 철학자를 프로세스 혹은 스레드 포크를 자원 그리고 생각하는 행위가 자원을 기다리는 것이라고 생각한다면, 프로세스와 스레드는 +자원을 사용하기 위해 기다리는 행위만 계속하는 상황이 되는것입니다.

+
+
+

교착상태 발생조건

+
+

교착상태가 발생할 조건에는 네가지가 있습니다. 차례대로 상호배제, 점유와 대기, 비선점, 원형 대기입니다. 해당 조건은 +모두 만족해야지 교착상태가 발생하고 하나라도 해당하지 않는다면 교착상태는 발생하지 않습니다.

+
+

1. 상호 배제

+

교착 상태가 발생한 근본적인 원인은 해당 자원을 하나의 프로세스만 사용하기 때문입니다. 프로세스도 마찬가지로 한 프로세스가 사용하는 자원을 다른 프로세스가 +사용할 수 없을때, 교착상태가 발생합니다.

+

2. 점유와 대기

+

프로세스는 자원을 할당받은 상태에서 다른 자원을 할당받기를 기다린다면 교착 상태가 발생할 수 있습니다. 이렇게 자원을 할당받은 상태에서 다른 자원을 +할당받기를 기다리는 상태점유와 대기라고 합니다.

+

3. 비선점

+

이전에 선점, 비선점이라는 개념을 보았습니다. 비선점이란 프로세스나 스레드가 자원을 할당받으면 그 작업이 끝나기전까지 자원을 뻇어갈수 없다는 +특징이 있었습니다. 교착상태가 발생하는 원인은 점유와 대기상태중 필요한 자원을 선점할수 없이 계속 기다리기만 하여서 발생하는 문제 입니다.

+

4. 원형 대기

+

자원 할당 그래프가 원의 형태로 그려지면 교착 상태가 발생할 수 있습니다. 이렇게 프로세스들이 원의 형태로 자원을 대기하는 것을 원형 대기라고 합니다.

+
+
+

교착상태 해결방법

+
+

교착상태를 해결하는 방법은 크게 세가지로 나눌수 있습니다.

+
+
    +
  1. 예방
  2. +
  3. 회피
  4. +
  5. 검출 후 회복
  6. +
+
+
+
+

예방을 통한 해결

+
+

예방이란 교착상태 발생 조건에 부합하지 않게 자원을 분배하는 방식입니다.

+

이전에 말한 교착상태발생 조건에 해당하는 네 가지 중 하나를 충족 하게 되면 교착 상태를 해결할 수 있습니다.

+

상호 배제를 없애는 방식

+
+

이론적으로는 가능하나, 모든 자원이 상호 배제를 없애기는 어렵기 때문에 비현실적이다.

+
+
+

점유와 대기를 없애는 방식

+
+

특정 자원이 먼저 점유를 수행하여 작업을 끝내고, 다른 프로세스에게 자원을 몰아주는 방식으로 해결이 가능합니다.

+

하지만 이런 방식은 자원 활용률이 낮아 진다는 문제가 있습니다.

+
+
+

비선점 조건을 없애는 방식

+
+

비선점 방식으로 작업을 다루게 되면 교착상태가 발생해도 자원을 뺏어 해결 할 수 있습니다.

+

하지만, 이런방식의 문제점은 모든 자원이 비선점 기능을 사용할 수 없다는 점에 있습니다.

+

예를들어, 프린터는 비선점 방식을 수행하는 자원입니다.

+
+
+

원형 대기 조건을 없애는 방식

+
+

모든 자원에 번홀을 붙이고 오름차순으로 자원을 할당하면 원형 대기는 방생하지 않습니다. +마치 원형이 아닌, 선형으로 자원을 나열하는 방식입니다.

+

이런 방식은 자원에 일일이 번호를 붙여야 한다는점과, 특정 번호는 자원 활용률이 떨어질수 있다는 문제가 있습니다.

+
+
+
+

회피를 통한 해결

+
+

회피 방식에서는 교착 상태 발생이 한정된 자원을 무분별하게 할당하였서 그렇다고 가정합니다. 그렇기 때문에 회피방식은 자원을 신중하게 할당하는 방식으로 +해결합니다.

+

즉, 교착 상태가 발생하지 않을 정도의 양만큼만 자원을 배분하는 방법을 교착 상태 회피라고 부릅니다.

+

안정 상태, 불안전 상태가 있습니다. 각각 교착상태가 발생하지 않는 상태를 안정상태, 발생할 가능성이 있는 상태를 불안정 상태라고 부릅니다.

+

회피를 통해 교착상태를 해결하기 위해 안전 순서열을 고려해서 문제를 해결합니다.

+
+

안전순서열: 교착 상태 없이 안전하게 프로세스들에 자원을 할당할 수 있는 순서를 의미합니다.

+
+
+

내용을 종합하면 안전 순서열이 있고 그것을 사용할때 상태를 안정상태, 안전 순서열이 없을 때 상태는 불안정상태라고 부르게 됩니다.

+
+
+

교착 상태 검출 후 회복

+
+

마지막으로, 교착상태를 피하기 위해서는 검출, 회복 방식을 사용합니다.

+

두가지 방식을 고려할 수 있는데,

+
    +
  1. 선점을 통한 회복
  2. +
  3. 프로세스 강제종료
  4. +
+
+

선점을 통한 회복

+

교착 상태가 해결될 때까지 한 프로세스씩 자원을 몰아주는 방식입니다. 교착 상태가 해결될 떄까지 다른 프로세스로부터 자원을 빼앗고 할당하는 방식입니다.

+
+

강제종료를 통한 회복

+

교착 상태에 놓인 순간 모든 프로세스를 종료 하는 방법 혹은 프로세스를 하나씩 종료해서 확인해보는 방법이 있습니다.

+

전자는 가장 확실하지만 모든 작업에 대한 진행사항을 잃을 가능성이 있고, 후자는 전자보다 손실에 대한 부담은 적지만 오버헤드가 커진다는 단점이 있습니다.

+

출처

+
+

이미지 출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc2/index.html b/public/jc2/index.html new file mode 100644 index 0000000..8315a02 --- /dev/null +++ b/public/jc2/index.html @@ -0,0 +1,334 @@ +CPU 스케줄링, 시스템 자원 관리

CPU 스케줄링, 시스템 자원 관리

@jc, 023· September 05, 2025 · 2 min read

CPU 스케줄링

+
+

CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며, +
모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다.

+

CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다. +

+

CPU 스케줄링 원칙

+
+

CPU는 스케줄링을 하면서 두가지 원칙을 중요시 하게 됩니다. +

+
    +
  1. 공정함: 특정 프로세스 실행이 무한정 대기하지 않도록 기간을 보장합니다.
  2. +
  3. 우선순위: 우선순위가 높은 작업에 우선권을 제공 합니다.
  4. +
+
+

CPU 스케줄링 평가 기준

+
+

CPU는 객관적인 스케줄링을 위해 아래와 같은 평가 기준을 사용합니다.

+
+
    +
  1. CPU 사용률 - CPU가 작업을 수행하는데 사용하는 시간의 비율
  2. +
  3. 처리량 - 시스템이 단위 시간당 완료할 수 있는 작업의 양
  4. +
  5. 응답 시간 - 시스템이 사용자의 요청에 반응하여 첫 번째 응답을 생성하기 시작하는데 걸리는 시간
  6. +
  7. 대기 시간 - 프로세스가 실행되기 위해 CPU를 할당받아 준비 상태에서 대기하는 시간의 총합
  8. +
  9. 처리 시간 - 특정 작업이 시작되었을 때부터 그 작업이 완전히 끝나는데 걸리는 시간의 총합
  10. +
@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc20/index.html b/public/jc20/index.html new file mode 100755 index 0000000..5494d89 --- /dev/null +++ b/public/jc20/index.html @@ -0,0 +1,379 @@ +물리주소, 논리주소 그리고 메모리 분할 방식

물리주소, 논리주소 그리고 메모리 분할 방식

@jc, 023· September 23, 2025 · 6 min read

물리주소와 논리주소

+
+

+ + + + img.png + + +
img.png
+

+

메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다. +이 저장된 메모리의 데이터를 CPU 혹은 실행중인 프로그램이 읽어 실행하게 됩니다.

+

해당 그림은 두가지 관점으로 주소를 나누고 사용하는 방식을 그림으로 나타낸 것입니다.

+

왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요?

+
+

이유는 메모리에 저장되어 있는 정보는 변화가 빠르고 이를 시시각각 알기어렵기 때문에

+
+

가령 프로그램이 새롭게 실행될때, 삭제 될때 혹은 같은 프로그램일지라도 실행될때마다 실행되는 주소가 다르기 때문입니다.

+

그렇기때문에 주소를 두가지 관점으로 나눠서 사용하게 됩니다.

+
+

물리주소란 실제로 정보가 저장된 하드웨어상 주소를 의미합니다.

+
+
+

논리주소란 실행중인 프로그램에 부여된 0번지부터 시작되는 주소를 의미합니다.

+
+

여기서 주의할점은 논리주소는 0번지 부터 시작하는 논리적 주소이기 때문에, 고유성이 없습니다. 하지만 물리주소는 +하드웨어상 주소기 때문에 고유성이 있습니다.

+
+
+

메모리 할당 방식

+
+

메모리 할당이란 주기억 장치에 프로세스를 저장하는 과정입니다. +이러한 과정은 크게 두가지로 나누어집니다.

+
    +
  1. 연속 할당
  2. +
  3. 불연속 할당
  4. +
+
+

연속할당

+
+

연속 할당은 프로세스가 연속된 메모리 영역에 할당되는 방법을 말합니다. +각 프로세스는 연속적인 메모리 주소 범위 내에 위치하게 됩니다. 이렇게 연속할당을 하게 되면 +빈공간보다 프로세스 공간이 더 작은 경우가 있는데 이러한 현상을 단편화라고 합니다.

+

연속할당의 종류로는 고정 크기 파티셔닝, 가변 크기 파티셔닝이 있습니다.

+
+

고정 크기 파티셔닝

+

고정 크기 파티셔닝은 메모리를 고정된 크기의 파티션으로 나누어 각 파티션에 프로세스를 할당하는 방식입니다. +예를들어, 모든 파티션을 10MB로 설정하고 파티션마다 프로세스를 할당하는 방식을 사용할 수 있습니다.

+

이러한 방식은 모든 프로세스가 지정한 파티션 크기만큼 떨어지는것이 아니기 떄문에 효율적이지 못한 단점이 있습니다.

+
+

가변 크기 파티셔닝

+

가변 크기 파티셔닝은 파티션의 크기를 유동적으로 조절하는 메모리 할당 방식입니다. +이러한 방식은 고정 크기 파티셔닝보다는 효율적이지만, 메모리 공간에 어떤 프로세스를 저장해야 할지 결정하는게 +복잡합니다.

+
+
+

불연속 할당

+
+

불연속 할당은 한 프로세스를 메모리 여러 곳에 분산 저장하는 방법입니다. 페이징, 세그멘테이션 이 있습니다.

+
+

페이징

+

페이징은 프로세스의 주소 공간을 페이지라는 동일한 크기의 구획으로 나누고, 주기억 장치도 페이지와 동일한 크기의 +프레임이라는 구획으로 나눕니다. 이후 한 페이지를 한 프레임에 적재하는 방식입니다.

+

자세한 내용은 이후에 다루게 됩니다.

+
+

세그멘테이션

+

프로세스의 주소공간을 세그먼트라는 단위로 나누어 주기억 장치에 적재합니다. +프로세스는 코드, 데이터, 스택 등으로 구성되기 때문에 각각을 한 세그먼트로 나누어서 메모리에 적재합니다.

+

이 과정에서, base주소와, limit주소를 이용하여 프로세스가 자신에게 할당된 메모리 영역만 사용하게 합니다.

+
+

출처

+
+

이미지 출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc21/index.html b/public/jc21/index.html new file mode 100755 index 0000000..686a961 --- /dev/null +++ b/public/jc21/index.html @@ -0,0 +1,476 @@ +메모리 배치기법 그리고 단편화에 대해

메모리 배치기법 그리고 단편화에 대해

@jc, 023· September 24, 2025 · 8 min read

연속 메모리 할당

+
+

+ + + + img.png + + +
img.png
+

+

연속 메모리 할당이란 메모리에 프로세스가 그림처럼 연속적으로 배치되는 상황을 가정합니다.

+

프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다.

+

이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 스와핑과 관련이 있습니다.

+
+

스와핑이란?

+
+

메모리는 실행시킬 프로세스를 적재하게 됩니다. 하지만, 이런 프로세스들 중에 현재 실행되지 않는 프로세스는 처리해줘야 합니다. +메모리 리소스가 한정적이기 때문입니다.

+

여기서 말하는 실행되지 않는 프로세스의 예시는 I/O작업, 오랫동안 사용되지 않는 프로세스가 이에 해당합니다.

+
+

+ + + + img.png + + +
img.png
+

+
+

그렇다면 이러한 프로세스를 메모리에서 처리하는 방법이 필요한데 그 방법이 스와핑 입니다.

+

스와핑은, 두가지 행위를 통해서 수행할 수 있습니다.

+
+

스왑 아웃: 현재 실행되지 않는 프로세스가 메모리에서 스왑 영역으로 옮겨지는 것 (메모리 -> 스왑 영역)

+
+
+

스왑 인: 스왑영역에 있던 프로세스가 다시 메모리로 옮겨지는 것 (스왑 영역 -> 메모리)

+
+

또한 메모리에서 보조기억장치로 옮겨질때 스왑영역으로 프로세스를 옮겨두는데 그 영역을 스왑 영역이라고 합니다.

+
+
+

메모리 할당 방식

+
+

프로세스는 메모리 속 비어있는 공간에 적재되어야 합니다. 비어 있는 메모리 공간에 프로세스를 연속적으로 할당하기 위해 +세가지 방법을 고려할 수 있습니다.

+
    +
  1. 최초 적합(first fit)
  2. +
  3. 최적 적합(best fit)
  4. +
  5. 최악 적합(worst fit)
  6. +
+

각방식을 아래 예시를 통해 들어보려 합니다.

+

프로세스 A,B,C는 이미 적재되어있고, 빈 공간 A,B,C가 있습니다. 앞으로 적재할 프로세스는 20MB크기를 가지고 있으며 +적재 방식에 따라 이를 어디에 적재할지 달라지게 됩니다.

+

+ + + + img.png + + +
img.png
+

+
+

최초 적합

+
+

최초 적합은 메모리 내의 빈 공간을 순서대로 검색하다가 적재할 수 있는 공간을 발견하면 그 공간에 프로세스를 배치하는 방식입니다. +이전 그림에서 운영체제가 빈공간 A,B,C 순서대로 검색을 하였다면 가장 먼저 검색된 A 빈공간에 적재되는 방식입니다.

+

+ + + + img.png + + +
img.png
+

+

적재후 모습은 그림과 같으며 해당 방식은 검색을 최소화 하며 빠른 할당을 가능하게 하는 장점이 있습니다. +하지만, 이후에 보게 될 외부 단편화가 생길 가능성이 높아지게 됩니다.

+
+
+

최적 적합

+
+

최적 적합은 운영체제가 빈공간을 모두 검색한 후 프로세스가 적재될 수 있는 공간 중 가장 작은 공간에 프로세스를 +배치하는 방식입니다. +이전 그림에서는 빈 공간 C가 가장 적합한 크기를 가진 공간이기 때문에 그곳에 적재 됩니다.

+

+ + + + img.png + + +
img.png
+

+

적재후 모습은 그림과 같으며 해당 방식은 적재할 프로세스 크기를 고려한 방식이기 때문에 외부 단편화를 +최소화 할 수 있다는 장점이 있지만, 모든공간을 검색하는 행위가 오버헤드를 발생시키기 때문에 느려집니다.

+
+
+

최악 적합

+
+

최악 적합은 운영체제가 빈 공간을 모두 검색한 후, 가장 큰 공간에 프로세스를 적재하는 방식입니다.

+

+ + + + img.png + + +
img.png
+

+

적재 후 모습은 가장 빈공간의 크기가 큰 B에 적재되는 것을 확인할 수 있습니다. 이러한 방식은 +외부 단편화의 발생 빈도도 크며, 모든 공간을 검색한다는 비효율적인 측면도 가지고 있습니다.

+
+

지금까지 외부 단편화라는 용어가 단점으로 설명했습니다. +그렇다면, 외부 단편화는 어떠한 문제일까요?

+
+

단편화

+
+

단편화는 크게 두가지로 나눌 수 있습니다.

+
    +
  1. 내부 단편화
  2. +
  3. 외부 단편화
  4. +
+
+

내부 단편화

+

+ + + + img.png + + +
img.png
+

+

내부 단편화 문제는 이전 최초 적합 사례에서 볼 수 있습니다. +빈공간A의 크기는 30MB인데 적재한 프로세스는 20MB입니다. 이런경우 10MB의 빈공간이 생기게 되고 이러한 비어있는 +공간을 내부 단편화가 발생했다고 표현합니다.

+
+

외부 단편화

+

+ + + + img.png + + +
img.png
+

+

외부 단편화 문제는 이전 최초 적합 사례를 이어서 설명하겠습니다. +현재 그림속 비어있는 공간은 80MB입니다. 하지만 해당 공간에 80MB크기의 프로세스를 적재할 수 없습니다. +이유는, 빈 공간이 연속적인것이 아닌 프로세스C에 의해 끊어져있기 때문입니다.

+

이처럼, 프로세스를 할당하기 어려울 만큼 작은 메모리 공간들로 인해 메모리가 낭비되는 현상을 지칭합니다.

+

이러한 외부 단편화를 해결할 수 있는 대표적인 방안은 메모리를 압축하는 방법이 있습니다.

+
+

압축

+
+

압축이란 흩어져 있는 빈 공간들을 하나로 모으는 방식으로 메모리 내에 저장된 프로세스를 재배치 시켜 빈 공간을 +하나의 큰 빈 공간으로 만드는 방법입니다.

+

이러한 방식은 단점이 있는데, 메모리의 빈공간을 모으는 작업은 시스템을 중지 시킨다는 문제가 있습니다. +또한, 메모리를 옮기는 작업이 큰 오버헤드를 만들고, 최적화 방법에 대한 정답을 고르기가 어렵습니다.

+

출처

+
+

이미지 출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc22/index.html b/public/jc22/index.html new file mode 100755 index 0000000..ddb3e28 --- /dev/null +++ b/public/jc22/index.html @@ -0,0 +1,506 @@ +페이징

페이징

@jc, 023· September 25, 2025 · 12 min read

연속 할당의 문제점

+
+

연속적 할당의 대표적인 문제점은 외부 단편화가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해 +필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다.

+

이러한 문제를 해결하기 위해서는 불연속 할당 방식 중 대표적인 페이징기법을 사용할 수 있습니다.

+
+
+

페이징이란?

+
+

+ + + + img.png + + +
img.png
+

+

페이징 기법은 프로세스를 일정한 단위로 자릅니다. 또한 프로세스가 들어갈 메모리 공간 또한 일정한 단위로 자릅니다.

+

여기서 프로세스를 일정한 단위로 자르면 일정한 논리 주소 공간이 생기는데 이것을 페이지라고 부르며, +일정한 단위로 잘린 메모리 물리 주소 공간프레임이라고 부르게 됩니다.

+

여기서 프레임, 페이지의 일정한 단위는 동일한 크기로 자르게 됩니다.

+

이렇게 만들어진 페이지프레임에 할당하는 가상 메모리 관리 기법을 페이징기법이라고 부르게 됩니다.

+

이렇게 일정한 크기를 정하고 불연속 할당을 수행하면 외부 단편화 문제를 줄일 수 있습니다.

+
+

페이징에서 스와핑

+

+ + + + img.png + + +
img.png
+

+

페이징에서도 이전과 마찬가지로 스와핑이 사용됩니다. 차이가 있다면 기존 연속 할당 방식 스와핑은 +프로세스 전체가 스왑영역으로 넘어가지만, 페이징 스와핑은 사용하지 않는 특정 페이지만 스왑아웃 +시킬 수 있습니다.

+

이러한 방식은 이후 가상메모리 방식을 사용하는데 핵심이 됩니다.

+
+

페이지 테이블

+
+

불연속 할당 방식에는 실행순서에 대한 문제가 하나 있습니다. +연속적 할당 방식에서는 실행순서를 CPU에게 알려줄 필요가 없습니다. 왜냐하면 실제로 물리 메모리에 연속적으로 +프로세스에 대한 정보가 있기 때문에 순서대로 실행시키면 되기 때문입니다.

+

하지만, 불연속 할당은 상황이 다릅니다. 메모리상 프로세스에 대한 정보가 연속적이지 않기 떄문에 +이를 실행시키는 CPU입장에서는 어떤 프로세스를 실행시켜야 할지 알기 어렵습니다.

+
+

+ + + + img.png + + +
img.png
+

+
+

이를 해결하기 위해서 페이지 테이블이란것을 사용합니다.

+

페이지 테이블페이지 번호, 프레임 번호를 짝지어 줍니다. 그렇게 되면 CPU입장에서는 +페이지 번호만 알고있다면 페이지 테이블을 통해 프레임으로 접근이 가능하기 때문입니다.

+

페이지 테이블은 프로세스마다 각자의 페이지 테이블을 가지게 됩니다.

+
+
+

페이지 테이블 베이스 레지스터(PTBR)

+
+

페이지 테이블은 프로세스마다 가지고 있고, 이는 메모리에 저장됩니다.

+

하지만, CPU 입장에서는 결국 페이지 테이블의 위치를 알아야 합니다. 이러한 기능을 수행하는게 +CPU내의 존재하는 PTBR입니다.

+

PTBRCPU내에 존재하고 페이지 테이블의 위치를 기록합니다.

+

+ + + + img.png + + +
img.png
+

+

해당 그림처럼 특정 프로세스 작업을 수행하기 위해서 CPU는 해당 PTBR내부 프로세스의 페이지 테이블을 +조회합니다. 이후 메모리내부 해당 페이지 테이블 주소로 넘어가서 특정 프로세스의 페이지 까지 접근하게 됩니다.

+
+
+

비효율적인 접근

+
+

이전 페이지 테이블을 참조하는데 한가지 문제가 있습니다.

+

CPU페이지 테이블로 접근하고, 해당 값들을 통해 실제 페이지로 접근합니다.

+

즉, 하나의 조회에 대해 두가지 접근을 수행하게 됩니다. 이러한 방식은 비효율적입니다. +그렇기 때문에 캐싱기능을 통해 이를 해결하고 이러한 기능을 수행하는게 TLB입니다.

+
+

TLB(Translation Lookaside Buffer)

+
+

+ + + + img.png + + +
img.png
+

+

TLB는 CPU 곁에 존재하며 이는 페이지 테이블에 대한 캐시 메모리입니다. +참조 지역성에 근거해 주로 최근에 사용된 페이지 위주로 가져와서 저장합니다.

+

여타한 캐싱 기능과동일하게 리소스가 TLB를 통해서 나오게 되면, 히트했다. 그것이 아니라면 +미스했다 라고 표현합니다.

+
+
+

페이징에서의 주소 변환

+
+

특정 주소에 접근하기 위해서는 두가지 관점의 정보가 필요하게 됩니다.

+
    +
  1. 어떤 페이지 혹은 프레임에 접근하고 싶은지
  2. +
  3. 접근하려는 주소가 그 페이지 혹은 프레임으로부터 얼마나 떨어져 있을지
  4. +
+
+

이중에서 1번은 기존 페이지 번호를 통해서 해결할 수 있습니다. +하지만, 2번의 말은 조금 애매하게 들리는데 이를 풀어서 설명하면, +하나의 주소내에서도 논리 혹은 물리주소에 따른 순차적인 주소가 있습니다.

+

n번지, n+1번지, n+2번지.... 처럼 세부적인 지점을 의미합니다.

+

1번 주소를 통해서 페이지혹은 프레임에 접근한다면 그 중 명확한 지점을 식별해야 하기 때문에

+

페이징 시스템에서는 페이지번호, 변위를 이용합니다.

+

자세한 예시는 아래 그림을 통해서 하겠습니다.

+
+

+ + + + img.png + + +
img.png
+

+

페이지, 페이지 테이블, 프레임을 나타내는 그림입니다. 이러한 그림은 특정 페이지에 접근하기 위해 +페이지 테이블을 참조하고 프레임 번호를 얻어 실제 메모리 프레임에 접근하는 시퀀스 입니다.

+

만약 CPU가 5번페이지에 변위가 2인 곳에 접근하려고 하면 10번지로 접근하게 될것입니다.

+
    +
  1. 5번 페이지는 1번 프레임에 있다.
  2. +
  3. 1번 프레임의 시작 번지수는 8번지이다
  4. +
  5. 8번지에 변위 2를 더해서 최종주소는 10이 된다.
  6. +
+

여기서 주의 할점은, 논리주소의 변위를 최종 물리 주소상 프레임 번지에 더하였다는 것입니다.

+
+

이말은, 논리주소의 변위 == 물리주소의 변위 입니다.

+
+

이것이 가능한 이유는 처음 페이징 방식을 사용할때 페이지와 프레임 변환과정에서 특정 크기로 나누게 되고, +그 간격이 같기 때문에 논리주소의 변위랑 물리주소의 변위는 같다는 결론이 나옵니다.

+
+
+

페이지 테이블 엔트리

+
+

페이지 테이블 엔트리는 페이지 테이블 row를 지칭하는 단위입니다.

+

+ + + + img.png + + +
img.png
+

+

지금까지는 이러한 페이지 테이블에는 페이지 번호, 프레임 번호만 존재 한다고 설명했습니다. +하지만, 다른 중요한 정보들도 있습니다.

+
    +
  1. 유효 비트
  2. +
  3. 보호 비트
  4. +
  5. 참조 비트
  6. +
  7. 수정 비트
  8. +
+
+

유효 비트

+

유효비트는 해당 페이지에 접근 가능한지 여부를 알려줍니다. 대표적으로 접근 불가능 한 경우는 +스와핑으로 인한 해당 페이지스왑영역으로 들어간 경우입니다.

+

이러한 경 페이지 폴트라는 예외가 발생하며, 하드웨어 인터럽트 처럼 처리 됩니다.

+
    +
  1. CPU는 기존 작업 내역을 백업합니다.
  2. +
  3. 페이지 폴트 처리 루틴을 실행합니다.
  4. +
  5. 페이지 처리 루틴은 원하는 페이지를 메모리로 가져온 뒤 유효 비트를 1로 변경해줍니다.
  6. +
  7. 페이지 폴트를 처리했다면 이제 CPU는 해당 페이지에 접근할 수 있게 됩니다.
  8. +
+
+

보호 비트

+

보호비트는 페이지 보호 기능을 위해 존재합니다. 리눅스의 읽기 쓰기 권한을 생각하면 됩니다. +해당 페이지가 읽기 전용 페이지라면 보호비트는 0을 나타내고, 읽고 쓰기가 가능하다면 1을 나타냅니다.

+
+

참조 비트

+

CPU가 접근한적 있는지 여부를 나타냅니다. 참조된 비트라면 1을 나타내며, 그렇기 않다면 0으로 유지됩니다.

+
+

수정 비트

+

해당 페이지에 데이터를 쓴 적이 있는 여부를 나타냅니다. 수정 여부를 확인해야 하는 이유는 스와핑 떄문입니다. +만약 CPU가 페이지에 대한 내용을 수정했다면, 스와핑 과정에서 보조 기억장치에 있는 데이터 또한 수정해야 하기 때문입니다.

+

출처

+
+

이미지 출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc23/index.html b/public/jc23/index.html new file mode 100755 index 0000000..7bb1480 --- /dev/null +++ b/public/jc23/index.html @@ -0,0 +1,530 @@ +요구페이징을 잘 수행하기 위해서 필요한 것들

요구페이징을 잘 수행하기 위해서 필요한 것들

@jc, 023· September 26, 2025 · 17 min read

서론

+
+

지금까지 가상 메모리를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다. +이러한 행위는 한정된 메모리를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다.

+

그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다.

+
    +
  1. 불필요한 페이지를 선별스왑 아웃 한다.
  2. +
  3. 프로세스에게 적절한 프레임을 할당한다.
  4. +
+

각각 페이지 교체 알고리즘, 프레임 할당이라고 부릅니다.

+

또한, 이러한 작업은 요구 페이징(demand paging) 이라는 작업을 더 효율적으로 할 수 있게 돕습니다.

+

이 글은 요구 페이징에 대해서 알아보고, 요구 페이징이 안정적으로 작동하기 위해 필연적인 페이지 교체 알고리즘과, 프레임 할당을 설명합니다.

+
+
+

요구 페이징(demand paging)

+
+

프로세스를 메모리에 적재할 떄 처음부터 모든 페이지를 적재하지 않고 필요한 페이지만을 메모리에 적재하는 방식을 +요구 페이징이라고 부릅니다.

+

요구 페이징은 다음과 같은 플로우로 진행됩니다.

+
    +
  1. CPU가 특정 페이지에 접근하는 명령어를 내린다.
  2. +
  3. 페이지가 메모리에 존재하면 유효비트 1을 나타내며 해당 프레임에 접근한다.
  4. +
  5. 존재 하지 않는다면 유효비트 0을 나타내며 페이지 폴트가 발생한다.
  6. +
  7. 페이지 폴트가 발생하면 해당 페이지를 메모리로 적재하고 유효비트를 1로 설정한다.
  8. +
  9. 1번을 다시 시행한다.
  10. +
+

이러한 요구 페이징은 필요한 페이지만 그때그때 불러서 적재 후 사용한다는 의미를 나타냅니다.

+

요구 페이징을 안정적으로 수행하기 위해서는 크게 두가지를 고려해야 합니다. +첫번째는, 요구 페이징은 메모리 기준 Input작업 입니다. +그렇다면 반대로 Output작업도 필요하게 됩니다.

+

왜냐하면 메모리는 한정되고 상대적으로 덜 필요한 페이지를 스왑아웃하는 작업도 필요하기 때문입니다.

+

이러한 방식을 페이지 교체 라고 부르며, 그중 여러가지 방식이 있기 때문에 페이지 교체 알고리즘으로 분류하고 명명합니다.

+

두번째는, 한정된 프레임을 잘 배분하는 것으로 스왑 아웃자체를 줄일 수 있기 때문에 프레임 할당 또한 +요구 페이징을 수행하기 위해 중요합니다.

+
+
+

페이지 교체 알고리즘

+
+

페이지 교체 알고리즘은 스왑 아웃할 페이지를 선별하는 알고리즘입니다. +그렇기 때문에 어떤 선별 기준에 따라 알고리즘을 나누게 됩니다.

+

일반적으로 기준페이지 폴트 발생 비율입니다. 페이지 폴트는 보조기억장치로 부터 +정보를 가져와서 메모리로 할당하여 그 정보를 불러와야 하는 비효율적인 시퀀스를 가지고 있습니다. +이러한 페이지 폴트 발생 비율이 적은 교체 알고리즘을 좋다고 평가합니다.

+

그리고 페이지 폴트 횟수페이지 참조열을 통해서 진행합니다.

+

가령,

+
+

2 2 2 3 5 5 5 3 3 7

+
+

이라는 페이지 참조가 발생한다면 페이지 참조열은 여기서 연속된 중복을 제거한 순서입니다.

+
+

2 3 5 3 7

+
+

이 해당 순서에 페이지 참조열이 됩니다. 이렇게 중복을 제거하는 이유는 연속된 참조는 페이지 폴트대상이 +아니기 때문입니다.

+
+
+

FIFO 페이지 교체 알고리즘

+

FIFO 페이지 교체 알고리즘은 이름 그대로 먼저 들어온 페이지를 먼저 내보내는 방식입니다.

+

+ + + + img.png + + +
img.png
+

+

해당 그림을 통해 설명하면 2,3,1 번의 순서대로 프레임에 쌓이게 되며 마지막 1번 페이지가 적재 된 이후에는 +프레임이 가득차게 됩니다. 이후 3번은 이미 적재된 페이지이기 때문에 넘어갑니다.

+

5번 페이지가 적재 되는 시점에 프레임은 가득 차있고, 5번페이지는 적재 되어있지 않기 때문에 선별교체하는 +작업이 필요합니다.

+

여기서 FIFO방식은 가장 먼저들어온 페이지를 내보낸다라고 설명드린것처럼 처음들어온 2페이지 스왑아웃 시키게 됩니다. +빈 공간에 필요한 5페이지를 넣게 됩니다.

+

이렇게 먼저 들어온 페이지를 먼저 내보내는것을 FIFO 교체 알고리즘이라고 명명합니다.

+

하지만 이러한 방식에는 큰 단점이 있는데, 먼저 들어온 페이지가 실행 내내 사용 될 수도 있습니다. +즉, 먼저 들어왔다고 해서 교체에 대상이 되기는 합당한 이유가 아니기 때문입니다.

+
+
+

2차 기회 페이지 교체 알고리즘

+
+

해당 알고리즘은 FIFO방식을 개선한 알고리즘 입니다. 이름 처럼 한번의 기회를 더 주는 방식입니다. +두가지 케이스가 있습니다. 기본적으로 가장 오래된 페이지를 스왑 아웃한다는 방식은 같습니다. +만약 스왑 아웃 시점이 오게 되면, 해당 참조 비트를 확인합니다.

+

CPU에 의해서 참조 된적이 있다면, 해당 참조 비트를 0으로 바꾸고 적재 시간을 현재로 변경하며, +참조 비트가 0이라면 오래되면서 참조된적도 없기 떄문에 바로 스왑 아웃 시켜버립니다.

+
+
+

최적 페이지 교체 알고리즘

+
+

최적 페이지 교체 방식은 이름그대로 최적의 방안을 찾는 알고리즘입니다. +미래를 통해 오랫동안 사용되지 않을 페이지를 스왑아웃 시키면서 문제를 해결합니다.

+

+ + + + img.png + + +
img.png
+

+

해당 그림을 통해 설명하면 5번 페이지를 요청할때 페이지 폴트가 발생하고 그 과정에서 이후 미래를 고려해서 +1번이 사용되지 않는다고 판단해 1번을 스왑 아웃하는 방식입니다.

+

해당 알고리즘은 페이지 폴트가 가장 낮습니다. +그렇지만, 현실적인 구현이 어렵습니다. 미래를 예측하는건 어려운 작업입니다. 그렇기 떄문에 현실적으로 가능한 +알고리즘으로 여기기 보단, 페이지 폴트가 가장 낮다는 점을 고려하여 상대적인 성능 평가를 목적으로 사용합니다.

+

다른 교체 알고리즘의 하한선으로 잡고 비교대상으로 쓰여집니다.

+
+
+

LRU 페이지 교체 알고리즘 (Least Recently Used Page Algorithm)

+
+

해당 알고리즘은 최적 페이지 교체 알고리즘을 변형해 미래를 예측하는것이 아닌, 과거를 통해 +사용되지 않은 페이지를 스왑아웃하는 방식을 차용합니다.

+

'최근에 사용되지 않은 페이지는 앞으로도 사용되지 않을 것이다' 라는 점을 토대로 구성됩니다.

+

+ + + + img.png + + +
img.png
+

+

페이지마다 마지막으로 사용한 시간을 토대로 최근에 가장 사용이 적었던 페이지를 교체합니다. +해당 그림에서는 5번 페이지가 적재될 시기에 가장 오래 사용되지 않는 2스왑아웃 시키는것을 +알 수 있습니다.

+
+
+

스래싱과 프레임 할당

+
+

요구 페이징을 잘 수행하기 위해 페이지 폴트를 줄이는 방식을 이야기 했습니다. +이러한 페이지 폴트를 줄이기 위해 교체 알고리즘을 적절하게 선택하는것이 중요하단것을 알게 되었습니다.

+

하지만, 페이지 폴트를 발생시키는 이유에는 프레임 수의 한정이라는 문제가 있습니다. +프레임이 무지막지 하게 많다면 모든 프로세스를 할당할 수 있을것이고, 그렇게 되면 스왑 아웃이 발생할 이유도 없을것입니다.

+

그렇기 때문에 페이지 폴트의 발생을 줄이기 위해 적절하게 프레임을 할당하는 것또한, 중요합니다.

+

역으로 자원을 효율적으로 사용하고, 가상메모리와 같은 기법을 사용하면서 페이징에 프로세스 실제 실행시간보다 +더큰 리소스를 사용하는 문제가 생길 수도 있습니다.

+

이렇게 배보다 배꼽이 큰 상황, 플어서 이야기하면

+
+

페이징 시간이 프로세스 실제 실행보다 더 길어지는 상황

+
+

스레싱이라고 부르게 됩니다.

+
+

멀티 프로그래밍 정도

+

+ + + + img.png + + +
img.png
+

+

해당 그래프는 세로축 CPU 이용률, 가로축 메모리에 올라와 있는 프로세스 수를 나타냅니다. +그래프에서 알 수 있듯이 프로세스수가 증가하면, CPU이용률 또한 증가합니다 하지만 일정 가로축을 넘어가면 +CPU이용률이 줄어드는 것을 알게 됩니다.

+

즉, 프로세스가 너무 많이 발생하면 각 프로세스에 할당된 프레임이 부족하고 그런 문제로 인해 페이지 폴트가 +자주 발생하게 됩니다.

+

CPU를 아무리 좋은것을 사용해도 메모리 공간이 부족하면 컴퓨터 성능이 안좋아지는 이유가 이런이유입니다.

+
+
+

프레임 할당

+
+

스래싱의 근본적 이유는 각 프로세스가 필요로 하는 프레임이 부족하기 때문입니다. 그렇기 떄문에 +운영체제는 프레임을 적절하게 할당할 수 있어야 합니다.

+

이러한 프레임 할당을 크게 두가지로 나눌수 있습니다.

+
    +
  1. 정적 할당 방식
  2. +
  3. 동적 할당 방식
  4. +
+
+
+

정적 할당 방식

+
+

정적할당방식은 두가지로 나누어집니다.

+
    +
  1. 균등할당
  2. +
  3. 비례할당
  4. +
+
+

균등할당

+

균등할당은 이름에서 알 수 있듯이 모든 프로세스에 프레임을 균등하게 할당하는 방식입니다. +프로세스가 3개가 있고, 프레임이 300개가 있다면 각 프로세스는 100개의 프레임을 할당받게 됩니다.

+

이러한 방식은 프로세스 크기도 각자 다른 상황에서 합리적이지 못한 선택입니다.

+
+

비례할당

+

크기가 큰 프로세스에 더 많은 프레임을 할당하는 방식을 비례할당이라고 부릅니다. +하지만 이러한 방식은 정적이라는 한계점을 가지고 있습니다.

+

실제 프로세스를 실행해보면 크기와 상관없이 더 많은 프레임을 필요로 하거나 그렇지 않은 프로세스들이 존재합니다. +이러한 문제 떄문에 비례할당도 합리적이라고 할 수 없습니다.

+
+

동적 할당 방식

+
+

동적할당방식에는 크게 두가지로 나누어집니다.

+
    +
  1. 작업 직합 모델(working set model)
  2. +
  3. 페이지 폴트 빈도(PFF: page fault frequency)
  4. +
+
+

작업 집합 모델

+

작업 집합 모델에서는 '프로세스가 일정 기간 동안 참조한 페이지 집합'을 기억하며 빈번한 페이지 교체를 방지합니다. +예를 들어 프로세스가 3초동안 20개의 페이지를 집중적으로 참조했다면 20개의 프레임을 할당하면 효율적일 것입니다.

+

이렇게 실행 중인 프로세스가 일정 시간 동안 참조한 페이지의 집합을 작업 집합이라고 합니다.

+
+
+

페이지 폴트 빈도

+

+ + + + img.png + + +
img.png
+

+

페이지 폴트 빈도 방식은 해당 그래프를 통해 이루어 집니다. +가로축은 할당된 프레임을 나타내며 세로축은 페이지 폴트율을 나타냅니다. +할당된 프레임은 적으면 페이지 폴트가 많이 발생하는 형상이 됩니다.

+

이러한 그래프에서 상한과 하한을 정한다음 해당 적정 구간에 들어올 수 있도록 프레임을 할당해주는 +방식을 페이지 폴트 빈도방식이라고 합니다.

+

출처

+
+

이미지 출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc3/index.html b/public/jc3/index.html new file mode 100755 index 0000000..fd0be60 --- /dev/null +++ b/public/jc3/index.html @@ -0,0 +1,384 @@ +유저모드와 커널모드 전환, 시스템 콜의 동작 원리

유저모드와 커널모드 전환, 시스템 콜의 동작 원리

@jc, 023· September 06, 2025 · 4 min read

이중모드

+
+

운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다.

+
+

그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요?

+
+

이에 대한 답은 이중 모드 입니다.

+
+

+ + + + img.png + + +
img.png
+

+
+

위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드커널 모드로 나누어 사용하게 됩니다.

+
+

사용자 모드

+

사용자 모드는 운영체제 서비스를 제공받을 수 없는 실행 모드입니다. +
CPU가 해당 모드인 경우, 입출력 명령어와 같은 하드웨어 자원 접근 명령을 실행할 수 없습니다. 일반 프로그램은 기본적으로 사용자 모드로 실행됩니다.

+
+

커널 모드

+

커널모드는 운영체제 서비스를 제공받을 수 있는 실행 모드로 커널 영역의 코드를 실행할 수 있습니다. +
CPU가 커널 모드로 명령어를 실행하면 자원에 접근하는 명령어를 비롯한 모든 명령어를 실행할 수 있으며, 운영체제는 커널 모드로 실행됩니다.

+
+

요약 하자면 일반 응용프로그램은 평소에 사용자 모드를 통해서 실행 되다가 실제 운영체제의 코드를 실행하여야 하는 순간이 오면 커널 모드로 전환하여 실행하다가 +운영체제의 코드 실행 지점이 끝난다면 다시 사용자 모드로 전환되게 됩니다.

+

이러한 방식으로 자원을 운영 체제로 하여금 독자적으로 관리할 수 있게 합니다.

+
+
+

사용자 모드에서 어떻게 커널모드로 전환할까?

+
+

사용자 모드에서 커널모드로 전환하는 방식은 시스템 콜에 의해서 발생합니다.

+
+

+ + + + img.png + + +
img.png
+

+
+

그림처럼 사용자 모드로 실행되는 프로그램이 자원에 접근해야 할때 운영체제에 커널 모드로 요청을 보내게 되고 이것을 시스템 콜이라고 부르게 됩니다.

+

시스템 호출소프트 웨어 인터럽트에 속합니다. 이러한 특징 때문에 CPU시스템 호출을 처리하는 순서가 인터럽트 처리 순서와 비슷합니다.

+

시스템 호출이 발생하면 지금까지의 작업을 백업 하고, 커널 영역 내의 호출 하여야 하는 코드를 실행 한 뒤 다시 돌아와 기존 프로그램을 계속 실행합니다.

+
+

+ + + + img.png + + +
img.png
+

+
+

그림을 통해서 이해를 하게 되면,

+
    +
  1. 응용 프로그램은 일반적인 작업을 수행중 운영체제 코드를 실행 하여야 하는 작업에 도달하게 됩니다.
  2. +
  3. 그러면 응용프로그램은 운영체제에게 자원 접근에 대한 시스템 콜을 날리게 된다.
  4. +
  5. 현재 작업을 백업하게 됩니다.
  6. +
  7. 이후 응용프로그램은 운영체제의 코드를 실행합니다.
  8. +
  9. 작업이 끝나면 다시 사용자 영역으로 돌아와 멈춰둔 작업을 진행합니다.
  10. +
+

이런 세부적인 순서를 진행하게 됩니다.

+

출처

+

사진출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc4/index.html b/public/jc4/index.html new file mode 100755 index 0000000..0ed9deb --- /dev/null +++ b/public/jc4/index.html @@ -0,0 +1,387 @@ +멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념

멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념

@jc, 023· September 07, 2025 · 4 min read

단일 프로세스

+
+

초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다. +이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나, +끝날때 까지 기다려야 합니다.

+
+

+ + + + img.png + + +
img.png
+

+
+CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 IO작업동안 CPU는 멈추게 +될것이고 그 상황에서 CPU가 놀고 있게 되는 시간이 늘어나는 것입니다. +
+

멀티 프로그래밍

+

+ + + + img.png + + +
img.png
+

+

이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다. +이를 멀티 프로그래밍이라고 부르며 그림처럼 CPU 사용률을 높이기 위한 목적이었습니다.

+

하지만 이러한 방식의 문제는 앞선 프로세스가 길어질 수록 즉 IO사용처럼 비는 시간없이 순수하게 많은 시간을 +쓰게 된다면 이후 프로세스가 계속 기다려야 하는 문제가 있었습니다.

+
+

멀티 태스킹

+

+ + + + img.png + + +
img.png
+

+

멀티 프로그래밍 방식에서 더 나아가 모든 프로세스가 공정하게 특정 짧은 시간만 실행되게 반복한다면 길게 시행되는 +프로세스 뒤에 오는 프로세스가 기다리는 문제가 없을 것이다. 이것이 멀티태스킹을 사용하는 이유입니다.

+

프로세스1에서 프로세스2로 작업을 스위칭 하는것을 문맥 교환(Context Switching)이라고 +부르게 되는데 이러한 문맥교환은 값싼 작업이 아니고 이러한 작업이 자주 일어나게 된다면 비효율 적인 단점이 부각되다 보니 +새로운 방식을 사용하게 됩니다.

+
+

멀티 프로세싱

+

멀티 프로세싱이란 이전 멀티 태스킹과 이름은 비슷 하지만 완전히 다른 방식입니다.

+

이전 방식은 하나의 CPU를 어떻게 쪼개서 사용할까라는 목적이였다면, 멀티 프로세싱CPU 작업단위인 +코어 자체를 늘려서 여러 CPU코어가 동시에 작업하는것을 멀티 프로세싱이라고 부르게 됩니다.

+

+ + + + img.png + + +
img.png
+

+

멀티 프로세싱은 CPU코어 수를 늘리는 방법이기 때문에, 이를 어떻게 처리할까에 대한 내용은 멀티 프로세싱 자체의 내용이 아니고 앞서 나왔던 방법론을 도입할 수 있습니다. +그림처럼 하나의 프로세스를 여러 코어가 담당하는 방법이나, 여러 프로세스를 여러 코어가 담당 할 수 도 있습니다.

+

출처

+

사진출처

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc5/index.html b/public/jc5/index.html new file mode 100644 index 0000000..23c6c08 --- /dev/null +++ b/public/jc5/index.html @@ -0,0 +1,369 @@ +인터럽트와 DMA를 통한 효율적 입출력 처리

인터럽트와 DMA를 통한 효율적 입출력 처리

@jc, 023· September 08, 2025 · 4 min read

인터럽트 기반 입출력

+
+

인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한 +방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다.

+

인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트를 발생시킨 +주체가 무엇인가에 따라 나뉘게 된다.

+

대표적인 하드웨어 인터럽트는 I/O완료, 대표적인 소프트웨어 인터럽트는 시스템 콜이 있다.

+
+
+

+ + + + img.png + + +
img.png
+

+

이러한 인터럽트 기반 입출력의 순서를 설명하자면

+
    +
  1. CPU가 입출력 장치에 대해 입출력 요청을 보낸다.
  2. +
  3. CPU는 요청이후 다른 작업을 수행한다.
  4. +
  5. 입출력 장치가 준비되면 인터럽트를 발생시킨다.
  6. +
  7. CPU는 현재 실행 중인 작업을 중단하고 인터럽트 서비스 루틴(ISR)을 실행한다.
  8. +
  9. 데이터를 처리한 후 , CPU는 원래 수행하던 작업을 계속 실행한다.
  10. +
+

이러한 인터럽트 기반 입출력의 단점은 인터럽트가 많이 발생하는 상황에서 CPU가 부하될 수 있다는 단점이 있다.

+
+
+

DMA(Direct Memory Access 직접 메모리 접근)

+
+

DMA방식은 이름에서 볼 수 있듯이 CPU를 사용하지 않고 입출력 장치가 직접 메로리와 데이터를 교환합니다.

+

이것이 가능한 이유는 DMA 컨트롤러가 존재해, 메모리와 입출력 장치 사이의 데이터를 관리하기 때문입니다.

+

DMA에서는 CPU가 전송할 데이터의 위치, 포인터, 바이트 크기만 DMA 컨트롤러에 전달하면, +DMA가 입출력 작업을 대신 처리하고 전체 작업이 완료될 때만 CPU에 인터럽트를 보냅니다. +이로 인해 CPU와 여러 입출력 장치가 직접 연결되던 기존 구조에서 CPU-DMA-입출력 장치 구조로 변화했고, +CPU의 가용 시간이 현저히 증가하는 효과를 얻었습니다. +이는 교수가 조교에게 학생 관리를 맡기고 최종 결과만 확인하는 것에 비유할 수 있으며, +현재 DMA는 많은 컴퓨터 장치에서 보편적으로 사용되는 기술이 되었습니다.

+
+
+

+ + + + img.png + + +
img.png
+

+
+DMA 방식을 순서로 설명하자면 +
    +
  1. CPU가 DMA 컨트롤러에게 입출력 요청합니다.
  2. +
  3. DMA 컨트롤러가 메모리와 입출력 장치 간의 데이터 전송을 직접 수행합니다.
  4. +
  5. 데이터 전송이 완료되면 DMA 컨트롤러가 인터럽트를 발생 시켜 CPU에게 완료를 알립니다.
  6. +
  7. CPU는 인터럽트를 받아서 필요한 후처리 수행합니다.
  8. +
@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc6/index.html b/public/jc6/index.html new file mode 100644 index 0000000..1497ed4 --- /dev/null +++ b/public/jc6/index.html @@ -0,0 +1,378 @@ +동기식/비동기식 I/O의 차이와 활용 사례

동기식/비동기식 I/O의 차이와 활용 사례

@jc, 023· September 09, 2025 · 5 min read

IO란

+

개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를 +주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다.

+

예시를 들어서

+
    +
  • 파일 읽기/쓰기 (문서를 열거나 저장하는 행위)
  • +
  • 네트워크 통신(웹사이트 접속, 이메일 전송)
  • +
  • 데이터베이스 조회(회원 정보 검색)
  • +
+

이런 일련의 행위는 공통적인 특징이 있는데, 물리적인 시간이 걸린다는 점입니다. +그렇기 떄문에 IO를 어떻게 다룰까에 대한 방법또한 여러가지 존재합니다.

+
+
+

동기와 비동기란

+

IO를 다루는 방법에는 동기, 비동기에 대한 개념이 등장합니다. +이러한 개념을 사전에 정의 하고 내려가겠습니다.

+

동기 (Synchronous)

+

프로그램에서 말하는 동기란 하나의 작업에 대해서 요청과 응답 과정을 기다리는 행위입니다. +예를들어, WAS가 데이터베이스에 조회 요청을 하고 데이터베이스는 요청받은 데이터를 돌려줄것입니다. +이 과정에서 WAS는 요청직후 부터 응답을 받을때 까지 과정에서 데이터베이스의 응답을 기다리게 됩니다. 이것이 동기입니다.

+
+

동기의 특징

+

순차적 실행: 한 작업이 완료되어야 다음 작업이 시작 +블로킹: 현재 작업이 끝날 때까지 다른 작업은 대기 +예측 가능: 코드가 위에서 아래로 순서대로 실행

+
+
+

비동기 (Asynchronous)

+

그렇다면 비동기는 하나의 작업에 대해서 요청과 응답 과정을 기다리지 않는 행위입니다. +예를들어, WAS가 데이터베이스에 조회 요청을 하게 되면 데이터베이스가 이를 수행하고 응답할것입니다. +이 과정 사이에 시간동안 WAS는 본인의 다른 작업을 수행하다가 데이터베이스의 응답을 받게 됩니다. +즉 요청과 응답 사이 기간동안 WAS는 본인의 일을 하며 무작정 기다리지 않는 것입니다.

+
+

비동기의 특징

+

동시 실행: 여러 작업을 동시에 시작 가능 +논블로킹: 작업 완료를 기다리지 않고 다른 작업 진행 +콜백/Promise: 작업 완료 시 결과를 알려주는 방식

+
+

동기식 I/O

+

+ + + + img.png + + +
img.png
+

+
+

동기식IO는 IO요청이 발생하였을 때 이전 동기 설명처럼 IO요청이 끝날때 까지 기다리는 방식입니다. +프로그램이 IO작업을 요청하게 되면, 다른 동작을 수행하지 않고 멈춰서 IO작업이 리턴되기 까지 기다립니다. +I/O작업이 완료되면 인터럽트를 통해 완료를 알리게 됩니다. 이후 CPU 제어권이 기존 프로그램에게 넘어가게 됩니다.

+

이러한 방식의 특징은 구현이 쉽다는 특징이 있지만, 연산에 대한 기다림으로 인해 자원 낭비를 하는 특징이 있습니다.

+

비동기식 I/O

+

+ + + + img.png + + +
img.png
+

+

비동기식IO는 IO요청이 발생하였을 떄 이전 비동기 설명처럼 IO요청을 기다리지 않는 방식입니다. +프로그램이 IO 작업을 요청하고, 그 작업이 완료되기를 기다리지 않고 즉시 다음 작업으로 넘어가는 방식입니다.

+

이러한 방식의 특징은 구현의 복잡성이 높다는 것이지만, 대용량 데이터를 처리하는데 여러 IO작업을 동시에 처리해야 할 떄 유용합니다.

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc7/index.html b/public/jc7/index.html new file mode 100644 index 0000000..4206dd8 --- /dev/null +++ b/public/jc7/index.html @@ -0,0 +1,431 @@ +프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기

프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기

@jc, 023· September 10, 2025 · 9 min read

프로세스란 무엇일까?

+
+

우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다.

+

여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다.

+
+
+

+ + + + img.png + + +
img.png
+

+
+위 사진처럼 보이는 것보다 더 많은 프로세스가 작동하고 있는데, 여기서 사용자가 볼 수 있는 프로세스를 포그라운드 프로세스 라며 명하며, +보이지 않는 프로세스를 백그라운드 프로세스라고 부르게 됩니다. +

백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는 다는 뜻은 아닌데 백그라운드 프로세스 중에서 사용자와 상호작용 하지 않고 자신의 일만을 수행하기 위해 존재하는 +프로세스를 데몬(daemon) 프로세스라고 명합니다.

+
+

프로세스 제어 블록(PCB)

+
+

CPU자원이 한정되어 있는 반면에, 모든 프로세스는 실행을 위해 CPU를 사용하여야 합니다. +그렇기 떄문에 프로세스들은 한정된 시간 만 CPU를 사용하며 자신의 차례를 기다립니다.

+

운영체제는 빠르게 번갈아 수행되는 프로세스의 실행 순서를 관리하고, 프로세스에 CPU와 여러가지 자원을 배분합니다. +이를 위해 운영체제는 프로세스 제어 블록(PCB)를 이용합니다.

+
+

PCB는 커널 영역에 생성되고, 수많은 프로세스를 PCB를 통해 태그처럼 사용해 특정 프로세스를 식별하며 해당 프로세스를 처리하는데 필요한 정보를 판단합니다.

+

즉, 가게 주인이 물건을 태그를 통해 판단하고 가격을 알 수 있고, 생산지를 알 수 있는 것처럼 PCB는 운영체제가 수 많은 프로세스를 식별하고 그 프로세스의 정보를 판단하게 돕습니다.

+
+
+

PCB의 구조

+
+
+

+ + + + img.png + + +
img.png
+

+

사진 출처

+
+

위 그림처럼 PCB는 프로세스를 식별하기 위해 여러가지 정보를 담고 있습니다. 프로세스의 ID나, +레지스터의 값 혹은 상태같이 많은 정보를 담고있으며 이를 알아보고자 합니다.

+
+

프로세스 ID

+

+ + + + img.png + + +
img.png
+

+

프로세스 ID(PID)는 프로세스를 식별하기 위해 존재하는 고유 ID입니다. 메모장을 두개 킨다고 할지라도 다른 프로세스ID가 +만들어지는 것처럼 중복된 활동이여도 하나의 프로세스는 고유한 ID를 가지게 됩니다.

+
+

레지스터 값

+

프로세스는 자신의 실행 차례가 돌아오면 이전까지 사용했던 레지스터의 중간값들을 모두 복원합니다. +여기에는 프로그램 카운터가 속하게 됩니다.

+
+

프로세스 상태

+

현재 프로세스가 어떤 상태인 기록합니다. 입출력장치를 사용하기 위해 기다리는지 혹은 CPU를 사용하고 있는 상태인지 와 같은 +상태를 기록하며 자세한 상태는 다음장에서 설명합니다.

+
+

CPU 스케줄링 정보

+

프로세스가 언제, 어떤 순서로 CPU를 할당받을지에 대한 정보도 PCB에 기록됩니다.

+
+

메모리 관리 정보

+

프로세스마다 메모리에 저장된 위치가 다릅니다. 그렇기 떄문에 PCB에는 해당 프로세스가 저장된 메모리 위치를 기록해야 합니다.

+
+
+

프로세스의 메모리 영역

+
+

프로세스가 생성되면 커널 영역에 PCB가 생성됩니다. 그렇다면 커널 영역이 아닌 사용자 영역에는 어떤 데이터가 들어갈까요?

+

+ + + + img.png + + +
img.png
+

+

사진출처

+

위 그림처럼 하나의 프로세스는 크게 코드영역(Text), 데이터 영역(Bss,Gvar), 힙 영역(Heap), 스택 영역(Stack) 4가지로 나뉩니다.

+

차례대로 설명하자면,

+
+
+

코드영역 or 텍스트영역(Text)

+

이곳에는 실행할 수 있는 기계어로 이루어진 명령어가 저장됩니다. 가공할 수 있는 데이터가 아닌 +CPU가 실행해야 하는 명령어가 담겨있기 때문에 읽기모드만 지원합니다.

+
+

데이터 영역

+

프로그램을 실행하는 동안 유지되어야 하는 데이터가 저장되는 공간입니다. 대표적은 전역 변수가 이곳에 해당합니다.

+
+

코드영역 & 데이터 영역 공통점

+

위 두 영역은 크기가 변하지 않습니다. 프로그램을 구성하는 명령어가 작동중에 코드 양이 늘어나는 경우가 없으니 +이 두가지 영역을 정적 할당 영역이라고 부릅니다.

+
+

힙 영역

+

프로그래머가 직접 할당할 수 있는 공간입니다. 프로그래밍 과정에서 힙 영역에 데이터를 할당했다면 언젠가는 이 영역에 +데이터를 반환해야 합니다. 그렇지 않다면 메모리 용량은 점점 줄어들어 장애가 발생할 수 있습니다.

+

이런 문제를 메모리를 할당받고 해제 하지 않았다고 하여 누수가 발생했다. 즉 메모리 누수라고 부릅니다.

+
+

스택 영역

+

스택 영역은 데이터를 일시적으로 저장하는 공간입니다. +데이터 영역에 담기는 값과는 다르게 잠깐 쓸 데이터를 담아두는 공간입니다. +함수를 실행하는 동안 필요한 지역변수, 매개 변수가 이곳에 해당합니다. +그렇기 떄문에 함수가 종료되면 스택 영역에서 해당 함수에 쓰였던 변수들도 같이 없어지게 됩니다.

+
+
+

힙 영역 & 스택 영역 공통점

+

위 두 영역은 실시간으로 그 크기가 변할 수 있고 그렇기 떄문에 동적 할당 영역이라고 부르게 됩니다.

+

그림을 보면 unused memory영역이 있는데, 스택 영역과 힙 영역이 동적이기 떄문에 힙은 아래에서 위로, 스택은 +위에서 아래로 주소를 할당하게 됩니다. 그렇게 되면 서로 충돌없이 동적으로 값을 할당할 수 있기 때문입니다.

+

여기서 만약에 힙이나 스택에 많은 정보가 담겨서 서로의 지점을 충돌 할 수 있는데, 그럴때 각각 stack overflow, +heap overflow라고 부르게 됩니다.

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc8/index.html b/public/jc8/index.html new file mode 100644 index 0000000..64b90d0 --- /dev/null +++ b/public/jc8/index.html @@ -0,0 +1,439 @@ +문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기

문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기

@jc, 023· September 11, 2025 · 8 min read

문맥교환(Context Switching)

+
+

하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요?

+

프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를 +저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야 +이후 자신의 차례가 왔을 때 이 과정을 이어받아 작업을 수행할 수 있습니다.

+

여기서 하나의 프로세스를 실행하기 위해 필요한 정보들을 문맥(Context)라고 부르게 됩니다. +이러한 문맥값들은 PCB속에 저장됩니다.환

+
+

+ + + img.png + +
img.png
+
+사진출처

+

결국 프로세스 A에서 B로 프로세스가 넘어가는 순간에 프로세스 A정보를 백업하고 그작업이 끝난다면 +프로세스 B의 문맥을 불러오게 되며 이 것이 프로세스를 교대하는 방법입니다.

+

문맥교환을 통해 여러개의 프로세스가 병렬적으로 시행되는 것 처럼 보이게 하지만 이러한 문맥교환은 +오버헤드가 발생할 수 있기 때문에 문맥교환이 자주일어나면 오버헤드를 신경써야 합니다.

+
+
+

프로세스 상태

+
+

이전에 PCB에 기록되는 정보 중 프로세스 상태가 있다고 합니다. 여기서 말하는 프로세스 상태는 생성이 되었는지 +혹은 CPU를 사용하는지와 같은 정보를 통칭해서 프로세스 상태라고 부르게 됩니다.

+
+

프로세스 상태는 크게 다섯가지로 나뉠 수 있습니다.

+

+ + + img.png + +
img.png
+
+사진출처

+
+

1. 생성 상태

+

프로세스를 생성 중인 상태를 생성 상태라고 부릅니다. 메모리에 적재되어 PCB를 할당받은 상태를 생성상태라고 부르게 됩니다. +생성 상태가 끝난다고 곧바로 실행되는 것이 아닌 준비 상태가 되어 실행되기를 기다리게 됩니다.

+
+

2. 준비 상태

+

준비 상태는 당장 CPU를 할당받아 실행될 수 있지만, 차례가 오지않아 기다리고 있는 상태입니다. +이 상태에서 준비가 되면 실행 상태로 넘어 갑니다. 그리고 다른 상태에서 다시 준비 상태로도 전환이 가능합니다.

+

준비 상태인 프로세스를 실행 상태로 전환하는 것을 디스패치 라고 부릅니다.

+
+

3. 실행 상태

+

실행 상태는 CPU를 할당받아 실행 중인 상태를 지칭 합니다. 실행 상태인 프로세스는 할당된 시간 동안 CPU를 사용할 수 있습니다. +이때 제한된 시간내 프로세스를 완료하지 못한경우 준비 상태로 전환이 되며, I/O입력처럼 대기해야 하는 상황이 생기면 +대기 상태로 넘어가게 됩니다.

+
+

4. 대기 상태

+

실행 상태에서 I/O입력과 같이 프로세스가 대기해야 하는 상황이 온다면 대기 상태로 진입하게 됩니다. +대기 상태가 끝난다고 해도 실행 상태가 되는것이 아닌 준비 상태로 넘어가게 됩니다.

+
+

5. 종료 상태

+

프로세스가 종료된 상태입니다. 이 상태에 도달하면 운영체제는 PCB와 프로세스가 사용한 메모리를 정리합니다.

+
+
+

프로세스 계층 구조

+
+

프로세스는 실행 도중 시스템 호출을 통해 다른 프로세스를 생성할 수 있습니다.

+

이때 새 프로세스를 생성한 프로세스를 부모 프로세스라고 부르게 되며, 생성 된 프로세스를 자식 프로세스라고 +부르게 됩니다. +부모의 프로세스와 자식의 프로세스는 각각 고유한 PID를 가지며 자식프로세스에서 부모프로세스 PID를 PPID로 가지고 있기도 합니다.

+
+

+ + + + img.png + + +
img.png
+
+[사진 출처: 혼자 공부하는 운영체제 저자:강민철]

+
+
+

프로세스 생성기법

+
+

그렇다면 부모 프로세스가 어떻게 자식 프로세스를 생성 할까요?

+

그 방법은 fork, exec라는 명령어를 통해서 생성하게 됩니다.

+

부모 프로세스는 fork를 통해 자신의 복사본을 자식 프로세스로 생성해내고, 그 복사본은 exec명령어를 통해 +자신의 메모리 공간을 다른 프로그램으로 교체합니다.

+
+

+ + + + img.png + + +
img.png
+

+
+

좀더 자세히 설명하면 fork, exec 모두 시스템 호출로 분류 됩니다. +부모 프로세스는 fork 시스템 호출을 통해 자신의 복사본을 자식으로써 생성합니다.

+

여기서 자식은 부모의 복사본이기 때문에 부모 프로세스의 자원들, 예를들면 메모리의 내용, 열린 파일의 목록등을 +상속하게 됩니다. 그렇다고 해서 모든 정보가 같지는 않습니다.

+

왜냐하면, PID나 메모리 저장구조는 고유한 정보이기 때문에 fork로 만들어진 자식은 PID, 메모리 저장위치 +처럼 고유한 정보에 대해서는 개별적인 값을 가지고 있습니다.

+
+

+ + + + img.png + + +
img.png
+

+
+

fork만 사용한 프로세스는 완전한 자식 프로세스라고 명하기는 조금 어렵습니다. +PID와 같은 고유한 값을 제외한다면 부모가 가진 리소스를 동일하게 사용하는 대체품이기 때문입니다.

+

그렇기 때문에 자식 프로세스는 자신의 프로세스를 가지기 위해 exec 시스템 호출을 하게 됩니다.

+

exec 호출을 진행하게 되면 자신의 메모리 공간을 새로운 프로그램으로 덮어쓰게 됩니다.

+

코드 영역과 데이터 영역의 내용이 실행한 프로그램으로 바뀌게 되고, 나머지 영역은 초기화 됩니다.

@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/jc9/index.html b/public/jc9/index.html new file mode 100755 index 0000000..f5dcd08 --- /dev/null +++ b/public/jc9/index.html @@ -0,0 +1,492 @@ +쓰레드의 개념, 메모리 공유 구조 및 TCB

쓰레드의 개념, 메모리 공유 구조 및 TCB

@jc, 023· September 12, 2025 · 7 min read

스레드란?

+
+

+ + + + img.png + + +
img.png
+

+
+

스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다.

+

또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면 +하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다.

+

마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과 +같이 여러 기능을 수행할 수 있습니다.

+
+

프로세스와 스레드

+
+

스레드를 이해하기 위해서는 프로세스와 엮어서 설명하고자 합니다. +전통적인 CPU는 하나의 프로세스만 처리할 수 있었습니다. 메모장, 워드, 게임등 많은 프로세스가 하나의 실행 +흐름을 가지고 한 번의 하나의 부분만 실행되는 프로세스입니다.

+

+ + + + img.png + + +
img.png
+

+

이런 프로세스를 단일 스레드 프로세스라고 부릅니다.

+
+

하지만, 스레드라는 개념이 도입되면서 하나의 프로세스가 한 번에 여러가지 일을 동시에 처리하는 것이 가능해졌습니다. +프로세스를 구성하는 명령어를 동시에 처리하는것이 가능해졌습니다.

+

+ + + + img.png + + +
img.png
+

+
+

그림을 통해 스레드를 보게 되면 스레드는 '프로세스를 구성하는 실행의 흐름 단위'라고 표현 가능 할 것입니다.

+

왜냐하면, 하나의 프로세스 안에 여러가지 스레드가 있고 각각의 작업 흐름을 가지며 프로세스가 하는 일을 병렬적으로 만들어 +주기 때문입니다.

+
+
+

스레드 메모리 구조

+
+

+ + + + img.png + + +
img.png
+

+

스레드의 메모리 구조를 이해하기 위해서는 이전 프로세서의 구조를 상기해봐야 합니다.

+

프로세스는 스택, 힙, 데이터, 코드 영역을 각자 가진다고 합니다. +스레드는 '프로세스를 구성하는 실행 흐름의 단위'라고 했고, 이 떄문에 스레드는 프로세스의 메모리 구조의 대부분을 공유해서 +사용한다. 그렇기 때문에 여러 스레드의 작업이 하나의 프로세스 안에서 이루어져도 동시작업이 가능한 이유입니다.

+
+

그렇다면 어떻게 스레드는 프로세스와 스레드간 데이터를 공유하는 것일까? +아래 그림을 통해서 보게되면

+
+

+ + + img.png + +
img.png
+
+사진출처

+
+

우선 하나의 프로세스안에 코드, 데이터, 힙, 스택 영역이 존재합니다. 그리고 프로세스 내부의 개별적인 스레드가 존재합니다.

+

스레드가 레지스터, 프로그램 카운터, 스택을 개별적으로 가지는 핵심 이유는 독립적인 실행 흐름을 보장하기 위해서입니다.

+

프로그램 카운터는 각 스레드가 서로 다른 코드 위치에서 실행될 수 있도록 현재 실행 지점을 개별 추적하고,

+

레지스터는 각 스레드의 작업 데이터를 독립적으로 저장합니다. +이를 통해 CPU가 스레드 간 전환할 때 현재 상태를 저장하고 복원하여 중단된 지점에서 정확히 재개할 수 있습니다. +스택 영역을 따로 가지는 이유는 각 스레드가 독립적인 함수 호출 흐름을 가져야 하기 때문입니다.

+

스택은 함수 호출 시 지역 변수, 매개변수, 리턴 주소를 저장하는데, 만약 스레드들이 스택을 공유한다면 한 스레드의 +함수 호출이 다른 스레드의 함수 실행에 영향을 주어 실행 흐름이 꼬이게 됩니다. 따라서 각 스레드는 독립적인 스택을 가져 서로 다른 함수를 안전하게 호출하고 실행할 수 있습니다. +결과적으로 이런 구조를 통해 스레드들은 힙과 데이터 영역은 공유하면서도 각자 독립적인 실행 흐름을 유지할 수 있어 +, 하나의 프로세스 내에서 여러 작업을 동시에 효율적으로 처리할 수 있게 됩니다.

+
+
+

TCB란

+
+

+ + + + img.png + + +
img.png
+

+

스레드 제어 블록은 운영체제가 각 스레드를 관리하기 위해 유지하는 데이터 구조체입니다. +프로세스 제어 블록(PCB)과 유사하지만 스레드 수준에서 필요한 정보들을 담고 있습니다. +링크드 리스트 형태로 구현되어 PCB안에 해당 스레드의 TCB를 내포하고 있는 형태로 저장됩니다.

+
+

+ + + + img.png + + +
img.png
+

+

+ + + + img.png + + +
img.png
+

+
+
+

TCB는 사진과 같은 형태로 저장되며, 아래와 같은 정보를 가진다.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
정보설명
스레드 식별자각 스레드를 식별하는 고유한 식별자
스레드 상태실행 준비 대기 등 스레드의 현재 상태
프로그램 카운터스레드가 다음에 실행할 명령어의 주소
레지스터스레드가 현재 사용하고 있는 CPU 레지스터의 값을 저장
스레드 우선순위스케줄링 결정에 사용되는 스레드의 우선순위
스레드 스택 포인터스택 내에서 현재 작업의 위치를 가리키는 레지스터
스레드 문맥 정보문맥 교환 시 저장되고 복원되어야 할 정보
@jc, 023
CATCH NPE tech blog
+ + \ No newline at end of file diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest old mode 100644 new mode 100755 diff --git a/public/og-image.png b/public/og-image.png old mode 100644 new mode 100755 diff --git a/public/page-data/1/page-data.json b/public/page-data/1/page-data.json deleted file mode 100644 index 95de662..0000000 --- a/public/page-data/1/page-data.json +++ /dev/null @@ -1 +0,0 @@ -{"componentChunkName":"component---src-templates-post-jsx","path":"/1/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"86bebffe-ff00-58c2-a118-12a9ba3dffb6","excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","html":"

운영체제란 무엇일까?

\n
\n

운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원관리하고,\n
프로세스를 관리하는 등 여러가지 일을 수행합니다.

\n

이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다.

\n

운영체제의 역할

\n
\n

하드웨어 관리

\n
\n

운영체제는 CPU, 메모리, 입출력 장치 등 컴퓨터 하드웨어 자원을 관리합니다.\n
여기서 말하는 관리란 자원의 충돌을 방지하고 사용자가 하드웨어를 효율적으로\n사용하도록 처리하는것을 의미하게 됩니다.

\n
\n
\n
\n

프로세스 관리

\n
\n

프로세스의 생성과 종료 그리고 CPU 스케줄링을 통해 프로세스의 실행 시간을 관리합니다.\n
멀티 태스킹환경에서 프로세스 전환을 관리합니다.

\n
\n
\n
\n

메모리 관리

\n
\n

각 애플리케이션에 충분한 메모리 공간을 할당하는 기능을 합니다.\n
또한 가상 메모리를 통해 실제 메모리보다 큰 주소 공간을 제공합니다.

\n
\n

커널이란 무엇일까?

\n
\n

커널이란 운영체제의 핵심 기능을 담당하며, 커널은 하드웨어와 소프트웨어 애플리케이션 간 통신을 관리합니다. 커널의 대표적인 기능으로는\n
프로세스 관리, 메모리 관리, 파일 시스템, 입 출력 관리의 역할을 수행하게 됩니다.

\n

위 설명 처럼 운영체제의 핵심기능을 커널이 많은 부분을 담당하기 때문에 이전에 설명한 운영체제의 기능이 커널의 기능이라고 생각하면 됩니다.

\n

커널이 자원을 관리하는 이유

\n
\n
\n

커널은 어떻게 충돌 없이 자원을 관리할까요?

\n
\n

이 질문에 대한 대답은 자원을 관리하는 지점을 커널을 통한 단일 진입점으로 만들게 되면서 해결 하게 됩니다.\n

\n
\n

왜 자원을 커널을 통해서만 관리하게 설게 했을까요?

\n
\n

커널이 자원을 혼자 관리해야 하는 이유를 예시를 들어서 설명하겠습니다.

\n

유치원 수업시간에 하나의 바구니에 테이프, 연필, 지우개와 같은 문구용품을 담아두고 선생님이 학생들에게 자율적으로 사용해도 된다고 하게 된다면 어떤일이 벌어질까요?

\n

처음에는 아이들이 각자 필요한 문구 용품을 사용하겠지만 얼마 가지 않아서 연필을 찾는 학생,\n
테이프를 가지고 누가먼저 쓸지 싸우는 학생,\n
혹은 지우개를 망가뜨린 학생등 많은 사고가 있을 것입니다.

\n

이러한 문제가 벌어지는 이유는 공용 문구를 사용할때 통제권이 모두에게 있기 떄문입니다. 그렇다면 이를 해결하기 위해서\n모두에게 있는 통제권을 하나로 합쳐서 해결하면 되는 문제이고 이것이 자원을 사용하기 위해 커널의 관리를 받아야 하는 이유입니다.

","frontmatter":{"title":"1. 운영체제의 역할과 커널의 기능","date":"September 04, 2025","update":"September 04, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/1/","readingTime":{"minutes":4.585}}},"seriesList":{"edges":[{"node":{"id":"86bebffe-ff00-58c2-a118-12a9ba3dffb6","fields":{"slug":"/1/"},"frontmatter":{"title":"1. 운영체제의 역할과 커널의 기능"}}},{"node":{"id":"4df66f0c-fb47-581a-8541-4336bdf66a9c","fields":{"slug":"/2/"},"frontmatter":{"title":"2. CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"83591dea-9474-596e-a50c-9686920054ff","fields":{"slug":"/3/"},"frontmatter":{"title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"77088a89-4f41-5fd9-935b-ed7406bb0e20","fields":{"slug":"/4/"},"frontmatter":{"title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"359416d8-e0ed-5c0b-a589-90cbc4a84fc0","fields":{"slug":"/5/"},"frontmatter":{"title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"0fed2fcc-c794-558d-ab3f-4fbb91b7721d","fields":{"slug":"/6/"},"frontmatter":{"title":"6. 동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":null,"next":{"fields":{"slug":"/2/"},"frontmatter":{"title":"2. CPU 스케줄링, 시스템 자원 관리"}}},"pageContext":{"id":"86bebffe-ff00-58c2-a118-12a9ba3dffb6","series":"운영체제 기본 개념","previousPostId":null,"nextPostId":"4df66f0c-fb47-581a-8541-4336bdf66a9c"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/10/page-data.json b/public/page-data/10/page-data.json deleted file mode 100644 index b2d41c2..0000000 --- a/public/page-data/10/page-data.json +++ /dev/null @@ -1 +0,0 @@ -{"componentChunkName":"component---src-templates-post-jsx","path":"/10/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"2e4f9ff2-e2bf-57e3-aaad-7eb2f7fd16b2","excerpt":"img.png 멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술이다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것이다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세…","html":"

\"img.png\"

\n

멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술이다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것이다.

\n
\n
\n

어떻게 멀티 프로세스를 생성할까?

\n

멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부모 프로세스가\n여러개의 자식 프로세스를 생성한다.

\n

부모 프로세스는 자식 프로세스의 PID를 알고있으며 자식또한 PID와 PPID를 알고있어\n서로 통신이 가능하다.

\n

이런 성질은 각각 독립적이지만 통신이 가능하게 만들었고 멀티 프로세스의 대표적인 예가\n브라우저의 탭이라고 할 수 있다.

\n

브라우저 탭은 문제가 발생해서 닫아야 하는 상황이여도 다른 탭까지 닫히지 않고 개별적으로\n운용을 할 수 있는걸 기억해보면 독립적이란 말을 더 잘 이해할 수 있을것이다.

\n
\n
\n

멀티 프로세스의 장점

\n
\n
    \n
  1. 안정성
  2. \n
\n

멀티 프로세스의 안정성은 각각의 프로세스가 독립적이기 떄문에 가능하다.\n대표적인 예로 좀전에 설명을 했던 특정 브라우저 탭이 문제가 발생하여 닫아야 하는 상황에서\n같은 브라우저의 다른 탭까지 닫히지는 않는다.\n이런것이 독립적인 성격에 의한 안정성이라고 할 수 있다.

\n
\n
\n

멀티 프로세스의 단점

\n
\n
    \n
  1. 문맥교환 (Context Switching) Overhead
  2. \n
\n

멀티 태스킹을 이루는 기술인 문맥 교환 과정에서 성능 저하가 발생할 수 있다.\n프로세스를 컨텍스트 스위칭 하면, CPU는 다음 프로세스의 정보를 불러오기 위해\n메모리를 검색하고, CPU 캐시 메모리를 초기화하며, 프로세스 상태를 저장하고,\n불러올 데이터를 준비해야 하기 떄문에, 빈번한 문맥교환이 발생하고 이 비용은 곧 오버헤드로 발생할 수 있다.

\n
\n
\n
    \n
  1. 자원 공유 비효율성
  2. \n
\n

프로세스는 독립적인 메모리를 가지고, 멀티 프로세스는 독립적인 메모리 공간의 합일 것이다.\n그렇기 때문에 메모리 비효율성을 초래한다.

\n
\n
\n

멀티 스레드

\n
\n

\"img.png\"

\n
\n

이전에 보았던 것처럼 스레드는 하나의 프로세스 내에 있는 실행 흐름이다.\n멀티 스레드는 하나의 프로세스 안에 여러개의 실행흐름을 가지는 것이다.\n멀티 스레드 또한 멀티 프로세스 처럼 여러개의 작업을 동시 실행 할 수 있다.

\n

이전에 보았던 것처럼 멀티 프로세스는 브라우저의 여러개의 탭을 통해 예시를 들었다.\n하지만, 멀티 스레드는 같은 브라우저라 할지라도 동일탭에 여러 실행 흐름을 말하게 되고\n예를들어 네트워크 처리 스레드, 검색 스레드 와 같이 동일한 프로세스 내 기능들을 말하게 된다.

\n
\n
\n

멀티 스레드의 장점

\n
\n

프로세스보다 스레드가 가벼움

\n

스레드는 프로세스보다 용량이 가볍다. 이유는 데이터, 코드, 힙 영역을\n프로세스와 공유해서 사용하기 때문에 내장된 정보다 프로세스보다 작기 떄문이다.\n그렇기 때문에 스레드를 제거하는 작업이 프로세스를 제거하는 작업보다 가볍다.

\n
\n
\n

자원의 효율성

\n

멀티 스레드는 하나의 프로세스 내에서 스택영역을 제외한 영역을 공유하기 때문에\n프로세스 간 통신을 사용하지 않고도 자원의 공유가 가능하여 자원을 효율적으로 사용할 수 있다.

\n
\n
\n

Context Switching 비용 감소

\n

스레드 문맥 교환 또한 오버헤드가 존재하지만, 프로세스 문맥교환과 비교했을 때,\n상대적으로 오버헤드가 적다.

\n

이유는 프로세스 컨텍스트 스위칭 비용은 스위칭할 때마다 CPU 캐시에 있는 내용을 모두 초기화하고,\n새로운 프로세스 정보를 CPU 캐시에 적재해야 하기 떄문이다.\n하지만, 스레드 문맥교환은 스레드 개별적인 정보만 교체하면 되기 떄문에 비용이 상대적으로 낮다.

\n
\n
\n

멀티 스레드의 단점

\n

멀티 프로세스는 개별적인 작업으로 인해 독집적이고, 각자의 문제를 전파하지 않는다고 하였다.

\n

하지만, 멀티 스레드는 하나의 스레드가 문제가 발생하면 다른 스레드들고 영향을 받아 전체가 종료가 될 수 있다.

\n
\n
\n

데드락

\n

데드락이란 하나의 자원을 사용하기위해 여러 곳에서 접근했고, 그상황에서 교착상태가 일어났을때\n여러대의 스레드가 서로 대기하면서 무한정 기다리는 현상을 데드락이라고 한다.

\n

예를들어, 스레드 1 은 자원 A을 점유하고 있는 상태에서 자원 B가 필요한 상황이다.\n그리고 스레드 2 는 자원 B를 점유하고 있는 상태에서 자원 A이 필요한 상황이다.\n하지만 스레드 1은 자원 B가 필요한 상황에서 자원 A을 빌려줄 수 있는 상황이 아니고,\n스레드 2또한 자원 A이 필요한 상태에서 자원 B를 빌려줄 수 없는 상황인 것이다.\n이처럼 다수의 쓰레드가 같은 lock을 동시에,\n다른 명령에 의해 획득하려 할 때 서로 절대 불가능한 일을 계속적으로 기다리는 상황을 이야기 한다.

","frontmatter":{"title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","date":"September 13, 2025","update":"September 13, 2025","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"},"fields":{"slug":"/10/","readingTime":{"minutes":8.185}}},"seriesList":{"edges":[{"node":{"id":"260ee945-dda8-544a-907f-08886cb18912","fields":{"slug":"/7/"},"frontmatter":{"title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},{"node":{"id":"b775e483-4005-578f-8b56-bc4cf3f18a77","fields":{"slug":"/8/"},"frontmatter":{"title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},{"node":{"id":"c2d81bbc-3b4c-5c89-b193-1807200e7f30","fields":{"slug":"/9/"},"frontmatter":{"title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},{"node":{"id":"2e4f9ff2-e2bf-57e3-aaad-7eb2f7fd16b2","fields":{"slug":"/10/"},"frontmatter":{"title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},{"node":{"id":"6b2d0bc1-f501-5533-becc-2e0d0340e9e6","fields":{"slug":"/11/"},"frontmatter":{"title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}}]},"previous":{"fields":{"slug":"/9/"},"frontmatter":{"title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB"}},"next":{"fields":{"slug":"/11/"},"frontmatter":{"title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}},"pageContext":{"id":"2e4f9ff2-e2bf-57e3-aaad-7eb2f7fd16b2","series":"프로세스와 쓰레드에 대해서 알아보기","previousPostId":"c2d81bbc-3b4c-5c89-b193-1807200e7f30","nextPostId":"6b2d0bc1-f501-5533-becc-2e0d0340e9e6"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/11/page-data.json b/public/page-data/11/page-data.json deleted file mode 100644 index 9f86974..0000000 --- a/public/page-data/11/page-data.json +++ /dev/null @@ -1 +0,0 @@ -{"componentChunkName":"component---src-templates-post-jsx","path":"/11/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"6b2d0bc1-f501-5533-becc-2e0d0340e9e6","excerpt":"동시성 이슈란? img.png 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면…","html":"

동시성 이슈란?

\n
\n
\n

\"img.png\"

\n
\n

동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다.

\n

예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면 11가 됩니다. 하지만 스레드 a와 b는 좋아요 카운트에 동시에 접근해서 초기값 10을 받은 상태라면\n스레드 b는 늘어난 11라는 숫자대신 10을 기준으로 값을 줄이게 됩니다. 그럼 최종 결과는 10이 아닌 9라는 값으로 나오게 됩니다.

\n

이처럼 멀티 스레드 환경에서는 하나의 자원에 동시에 접근하게 되면 이러한 문제가 발생할 수 있다.

\n
\n
\n

스레드 안전

\n
\n

그럼 우리가 추구해야 할 문제는 스레드 안전한 멀티 스레드 프로그래밍을 구현할 수 있어야 한다. 이것을 구현하는\n방법에 대해 이야기 하려고 한다.

\n
\n
\n

스레드 안전 여부 판단

\n
\n
    \n
  1. 전역 변수나 힙, 파일과 같이 여러 스레드가 동시 접근 가능한 자원을 사용하는가
  2. \n
  3. 핸들과 포인터를 통한 데이터의 간접 접근이 가능한가?
  4. \n
  5. 부수 효과를 가져오는 코드가 있는가?
  6. \n
\n
\n
\n

스레드 안전을 지키기 위한 4가지 방법

\n
\n
    \n
  1. 상호 배제(Mutual Exclusion)
  2. \n
\n
\n
    \n
  • 공유 자원에 하나의 Thread만 접근할 수 있도록 세마포어/ 뮤텍스락을 통제하는 방법이다.
  • \n
\n
\n
    \n
  1. 원자 연산(Atomic Operation)
  2. \n
\n
\n
    \n
  • 공유 자원에 접근할 때 원자 연산을 이용하거나 원자적으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현하는 방법이다.
  • \n
  • Atomic\n
      \n
    • 공유 자원 변경에 필요한 연산을 원자적으로 분리한 뒤에 실제로 데이터의 변경이 이루어지는 시점에 Lock을 걸고,
    • \n
    \n데이터를 변경하는 시간 동안 다른 쓰레드의 접근이 불가능하도록 하는 방법이다.
  • \n
\n
\n
    \n
  1. Thread-Local Storage (스레드 지역 저장소)
  2. \n
\n
\n
    \n
  • 공유 자원의 사용을 최대한 줄이고 각가의 쓰레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는 방법이다.
  • \n
  • 일반적으로 공유 상태를 피할 수 없을 때 사용하는 방식이며, 전역 변수 사용을 자제하라는 뜻으로 생각하면 된다.
  • \n
\n
\n
    \n
  1. Re-entrancy (재진입성)
  2. \n
\n
\n
    \n
  • 쓰레드 호출과 상관 없이 프로그램에 문제가 없도록 작성하는 방법이다.
  • \n
  • 어떤 함수가 한 스레드에 의해 호출되어 실행 중이라면 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 옳바르게 주어져야 한다.
  • \n
  • 쓰레드끼리 독립적으로 동작할 수 있도록 코드를 작성하는 것으로 생각하면 된다.
  • \n
\n
\n
","frontmatter":{"title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","date":"September 14, 2025","update":"September 14, 2025","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"},"fields":{"slug":"/11/","readingTime":{"minutes":4.365}}},"seriesList":{"edges":[{"node":{"id":"260ee945-dda8-544a-907f-08886cb18912","fields":{"slug":"/7/"},"frontmatter":{"title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},{"node":{"id":"b775e483-4005-578f-8b56-bc4cf3f18a77","fields":{"slug":"/8/"},"frontmatter":{"title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},{"node":{"id":"c2d81bbc-3b4c-5c89-b193-1807200e7f30","fields":{"slug":"/9/"},"frontmatter":{"title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},{"node":{"id":"2e4f9ff2-e2bf-57e3-aaad-7eb2f7fd16b2","fields":{"slug":"/10/"},"frontmatter":{"title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},{"node":{"id":"6b2d0bc1-f501-5533-becc-2e0d0340e9e6","fields":{"slug":"/11/"},"frontmatter":{"title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}}]},"previous":{"fields":{"slug":"/10/"},"frontmatter":{"title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}},"next":null},"pageContext":{"id":"6b2d0bc1-f501-5533-becc-2e0d0340e9e6","series":"프로세스와 쓰레드에 대해서 알아보기","previousPostId":"2e4f9ff2-e2bf-57e3-aaad-7eb2f7fd16b2","nextPostId":null}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/2/page-data.json b/public/page-data/2/page-data.json deleted file mode 100644 index 91133e8..0000000 --- a/public/page-data/2/page-data.json +++ /dev/null @@ -1 +0,0 @@ -{"componentChunkName":"component---src-templates-post-jsx","path":"/2/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"4df66f0c-fb47-581a-8541-4336bdf66a9c","excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","html":"

CPU 스케줄링

\n
\n

CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n
모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다.

\n

CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n

\n

CPU 스케줄링 원칙

\n
\n

CPU는 스케줄링을 하면서 두가지 원칙을 중요시 하게 됩니다.\n

\n
    \n
  1. 공정함: 특정 프로세스 실행이 무한정 대기하지 않도록 기간을 보장합니다.
  2. \n
  3. 우선순위: 우선순위가 높은 작업에 우선권을 제공 합니다.
  4. \n
\n
\n

CPU 스케줄링 평가 기준

\n
\n

CPU는 객관적인 스케줄링을 위해 아래와 같은 평가 기준을 사용합니다.

\n
\n
    \n
  1. CPU 사용률 - CPU가 작업을 수행하는데 사용하는 시간의 비율
  2. \n
  3. 처리량 - 시스템이 단위 시간당 완료할 수 있는 작업의 양
  4. \n
  5. 응답 시간 - 시스템이 사용자의 요청에 반응하여 첫 번째 응답을 생성하기 시작하는데 걸리는 시간
  6. \n
  7. 대기 시간 - 프로세스가 실행되기 위해 CPU를 할당받아 준비 상태에서 대기하는 시간의 총합
  8. \n
  9. 처리 시간 - 특정 작업이 시작되었을 때부터 그 작업이 완전히 끝나는데 걸리는 시간의 총합
  10. \n
","frontmatter":{"title":"2. CPU 스케줄링, 시스템 자원 관리","date":"September 05, 2025","update":"September 05, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/2/","readingTime":{"minutes":2.05}}},"seriesList":{"edges":[{"node":{"id":"86bebffe-ff00-58c2-a118-12a9ba3dffb6","fields":{"slug":"/1/"},"frontmatter":{"title":"1. 운영체제의 역할과 커널의 기능"}}},{"node":{"id":"4df66f0c-fb47-581a-8541-4336bdf66a9c","fields":{"slug":"/2/"},"frontmatter":{"title":"2. CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"83591dea-9474-596e-a50c-9686920054ff","fields":{"slug":"/3/"},"frontmatter":{"title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"77088a89-4f41-5fd9-935b-ed7406bb0e20","fields":{"slug":"/4/"},"frontmatter":{"title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"359416d8-e0ed-5c0b-a589-90cbc4a84fc0","fields":{"slug":"/5/"},"frontmatter":{"title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"0fed2fcc-c794-558d-ab3f-4fbb91b7721d","fields":{"slug":"/6/"},"frontmatter":{"title":"6. 동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":{"fields":{"slug":"/1/"},"frontmatter":{"title":"1. 운영체제의 역할과 커널의 기능"}},"next":{"fields":{"slug":"/3/"},"frontmatter":{"title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},"pageContext":{"id":"4df66f0c-fb47-581a-8541-4336bdf66a9c","series":"운영체제 기본 개념","previousPostId":"86bebffe-ff00-58c2-a118-12a9ba3dffb6","nextPostId":"83591dea-9474-596e-a50c-9686920054ff"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/3/page-data.json b/public/page-data/3/page-data.json deleted file mode 100644 index 1e94115..0000000 --- a/public/page-data/3/page-data.json +++ /dev/null @@ -1 +0,0 @@ -{"componentChunkName":"component---src-templates-post-jsx","path":"/3/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"83591dea-9474-596e-a50c-9686920054ff","excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. img.png 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비…","html":"

이중모드

\n
\n

운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다.

\n
\n

그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요?

\n
\n

이에 대한 답은 이중 모드 입니다.

\n
\n

\"img.png\"

\n
\n

위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드커널 모드로 나누어 사용하게 됩니다.

\n
\n

사용자 모드

\n

사용자 모드는 운영체제 서비스를 제공받을 수 없는 실행 모드입니다.\n
CPU가 해당 모드인 경우, 입출력 명령어와 같은 하드웨어 자원 접근 명령을 실행할 수 없습니다. 일반 프로그램은 기본적으로 사용자 모드로 실행됩니다.

\n
\n

커널 모드

\n

커널모드는 운영체제 서비스를 제공받을 수 있는 실행 모드로 커널 영역의 코드를 실행할 수 있습니다.\n
CPU가 커널 모드로 명령어를 실행하면 자원에 접근하는 명령어를 비롯한 모든 명령어를 실행할 수 있으며, 운영체제는 커널 모드로 실행됩니다.

\n
\n

요약 하자면 일반 응용프로그램은 평소에 사용자 모드를 통해서 실행 되다가 실제 운영체제의 코드를 실행하여야 하는 순간이 오면 커널 모드로 전환하여 실행하다가\n운영체제의 코드 실행 지점이 끝난다면 다시 사용자 모드로 전환되게 됩니다.

\n

이러한 방식으로 자원을 운영 체제로 하여금 독자적으로 관리할 수 있게 합니다.

\n
\n
\n

사용자 모드에서 어떻게 커널모드로 전환할까?

\n
\n

사용자 모드에서 커널모드로 전환하는 방식은 시스템 콜에 의해서 발생합니다.

\n
\n

\"img.png\"

\n
\n

그림처럼 사용자 모드로 실행되는 프로그램이 자원에 접근해야 할때 운영체제에 커널 모드로 요청을 보내게 되고 이것을 시스템 콜이라고 부르게 됩니다.

\n

시스템 호출소프트 웨어 인터럽트에 속합니다. 이러한 특징 때문에 CPU시스템 호출을 처리하는 순서가 인터럽트 처리 순서와 비슷합니다.

\n

시스템 호출이 발생하면 지금까지의 작업을 백업 하고, 커널 영역 내의 호출 하여야 하는 코드를 실행 한 뒤 다시 돌아와 기존 프로그램을 계속 실행합니다.

\n
\n

\"img.png\"

\n
\n

그림을 통해서 이해를 하게 되면,

\n
    \n
  1. 응용 프로그램은 일반적인 작업을 수행중 운영체제 코드를 실행 하여야 하는 작업에 도달하게 됩니다.
  2. \n
  3. 그러면 응용프로그램은 운영체제에게 자원 접근에 대한 시스템 콜을 날리게 된다.
  4. \n
  5. 현재 작업을 백업하게 됩니다.
  6. \n
  7. 이후 응용프로그램은 운영체제의 코드를 실행합니다.
  8. \n
  9. 작업이 끝나면 다시 사용자 영역으로 돌아와 멈춰둔 작업을 진행합니다.
  10. \n
\n

이런 세부적인 순서를 진행하게 됩니다.

\n

출처

\n

사진출처

","frontmatter":{"title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리","date":"September 06, 2025","update":"September 06, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/3/","readingTime":{"minutes":4.46}}},"seriesList":{"edges":[{"node":{"id":"86bebffe-ff00-58c2-a118-12a9ba3dffb6","fields":{"slug":"/1/"},"frontmatter":{"title":"1. 운영체제의 역할과 커널의 기능"}}},{"node":{"id":"4df66f0c-fb47-581a-8541-4336bdf66a9c","fields":{"slug":"/2/"},"frontmatter":{"title":"2. CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"83591dea-9474-596e-a50c-9686920054ff","fields":{"slug":"/3/"},"frontmatter":{"title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"77088a89-4f41-5fd9-935b-ed7406bb0e20","fields":{"slug":"/4/"},"frontmatter":{"title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"359416d8-e0ed-5c0b-a589-90cbc4a84fc0","fields":{"slug":"/5/"},"frontmatter":{"title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"0fed2fcc-c794-558d-ab3f-4fbb91b7721d","fields":{"slug":"/6/"},"frontmatter":{"title":"6. 동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":{"fields":{"slug":"/2/"},"frontmatter":{"title":"2. CPU 스케줄링, 시스템 자원 관리"}},"next":{"fields":{"slug":"/4/"},"frontmatter":{"title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},"pageContext":{"id":"83591dea-9474-596e-a50c-9686920054ff","series":"운영체제 기본 개념","previousPostId":"4df66f0c-fb47-581a-8541-4336bdf66a9c","nextPostId":"77088a89-4f41-5fd9-935b-ed7406bb0e20"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/4/page-data.json b/public/page-data/4/page-data.json deleted file mode 100644 index 169aade..0000000 --- a/public/page-data/4/page-data.json +++ /dev/null @@ -1 +0,0 @@ -{"componentChunkName":"component---src-templates-post-jsx","path":"/4/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"77088a89-4f41-5fd9-935b-ed7406bb0e20","excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. img.png 멀티 프로그래밍 img.png 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하…","html":"

단일 프로세스

\n
\n

초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다.

\n
\n

\"img.png\"

\n
\nCPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 IO작업동안 CPU는 멈추게\n될것이고 그 상황에서 CPU가 놀고 있게 되는 시간이 늘어나는 것입니다.\n
\n

멀티 프로그래밍

\n

\"img.png\"

\n

이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다.\n이를 멀티 프로그래밍이라고 부르며 그림처럼 CPU 사용률을 높이기 위한 목적이었습니다.

\n

하지만 이러한 방식의 문제는 앞선 프로세스가 길어질 수록 즉 IO사용처럼 비는 시간없이 순수하게 많은 시간을\n쓰게 된다면 이후 프로세스가 계속 기다려야 하는 문제가 있었습니다.

\n
\n

멀티 태스킹

\n

\"img.png\"

\n

멀티 프로그래밍 방식에서 더 나아가 모든 프로세스가 공정하게 특정 짧은 시간만 실행되게 반복한다면 길게 시행되는\n프로세스 뒤에 오는 프로세스가 기다리는 문제가 없을 것이다. 이것이 멀티태스킹을 사용하는 이유입니다.

\n

프로세스1에서 프로세스2로 작업을 스위칭 하는것을 문맥 교환(Context Switching)이라고\n부르게 되는데 이러한 문맥교환은 값싼 작업이 아니고 이러한 작업이 자주 일어나게 된다면 비효율 적인 단점이 부각되다 보니\n새로운 방식을 사용하게 됩니다.

\n
\n

멀티 프로세싱

\n

멀티 프로세싱이란 이전 멀티 태스킹과 이름은 비슷 하지만 완전히 다른 방식입니다.

\n

이전 방식은 하나의 CPU를 어떻게 쪼개서 사용할까라는 목적이였다면, 멀티 프로세싱CPU 작업단위인\n코어 자체를 늘려서 여러 CPU코어가 동시에 작업하는것을 멀티 프로세싱이라고 부르게 됩니다.

\n

\"img.png\"

\n

멀티 프로세싱은 CPU코어 수를 늘리는 방법이기 때문에, 이를 어떻게 처리할까에 대한 내용은 멀티 프로세싱 자체의 내용이 아니고 앞서 나왔던 방법론을 도입할 수 있습니다.\n그림처럼 하나의 프로세스를 여러 코어가 담당하는 방법이나, 여러 프로세스를 여러 코어가 담당 할 수 도 있습니다.

\n

출처

\n

사진출처

","frontmatter":{"title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","date":"September 07, 2025","update":"September 07, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/4/","readingTime":{"minutes":3.94}}},"seriesList":{"edges":[{"node":{"id":"86bebffe-ff00-58c2-a118-12a9ba3dffb6","fields":{"slug":"/1/"},"frontmatter":{"title":"1. 운영체제의 역할과 커널의 기능"}}},{"node":{"id":"4df66f0c-fb47-581a-8541-4336bdf66a9c","fields":{"slug":"/2/"},"frontmatter":{"title":"2. CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"83591dea-9474-596e-a50c-9686920054ff","fields":{"slug":"/3/"},"frontmatter":{"title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"77088a89-4f41-5fd9-935b-ed7406bb0e20","fields":{"slug":"/4/"},"frontmatter":{"title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"359416d8-e0ed-5c0b-a589-90cbc4a84fc0","fields":{"slug":"/5/"},"frontmatter":{"title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"0fed2fcc-c794-558d-ab3f-4fbb91b7721d","fields":{"slug":"/6/"},"frontmatter":{"title":"6. 동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":{"fields":{"slug":"/3/"},"frontmatter":{"title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}},"next":{"fields":{"slug":"/5/"},"frontmatter":{"title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리"}}},"pageContext":{"id":"77088a89-4f41-5fd9-935b-ed7406bb0e20","series":"운영체제 기본 개념","previousPostId":"83591dea-9474-596e-a50c-9686920054ff","nextPostId":"359416d8-e0ed-5c0b-a589-90cbc4a84fc0"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/404.html/page-data.json b/public/page-data/404.html/page-data.json old mode 100644 new mode 100755 diff --git a/public/page-data/404/page-data.json b/public/page-data/404/page-data.json old mode 100644 new mode 100755 diff --git a/public/page-data/5/page-data.json b/public/page-data/5/page-data.json deleted file mode 100644 index cef5472..0000000 --- a/public/page-data/5/page-data.json +++ /dev/null @@ -1 +0,0 @@ -{"componentChunkName":"component---src-templates-post-jsx","path":"/5/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"359416d8-e0ed-5c0b-a589-90cbc4a84fc0","excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","html":"

인터럽트 기반 입출력

\n
\n

인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다.

\n

인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트를 발생시킨\n주체가 무엇인가에 따라 나뉘게 된다.

\n

대표적인 하드웨어 인터럽트는 I/O완료, 대표적인 소프트웨어 인터럽트는 시스템 콜이 있다.

\n
\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

이러한 인터럽트 기반 입출력의 순서를 설명하자면

\n
    \n
  1. CPU가 입출력 장치에 대해 입출력 요청을 보낸다.
  2. \n
  3. CPU는 요청이후 다른 작업을 수행한다.
  4. \n
  5. 입출력 장치가 준비되면 인터럽트를 발생시킨다.
  6. \n
  7. CPU는 현재 실행 중인 작업을 중단하고 인터럽트 서비스 루틴(ISR)을 실행한다.
  8. \n
  9. 데이터를 처리한 후 , CPU는 원래 수행하던 작업을 계속 실행한다.
  10. \n
\n

이러한 인터럽트 기반 입출력의 단점은 인터럽트가 많이 발생하는 상황에서 CPU가 부하될 수 있다는 단점이 있다.

\n
\n
\n

DMA(Direct Memory Access 직접 메모리 접근)

\n
\n

DMA방식은 이름에서 볼 수 있듯이 CPU를 사용하지 않고 입출력 장치가 직접 메로리와 데이터를 교환합니다.

\n

이것이 가능한 이유는 DMA 컨트롤러가 존재해, 메모리와 입출력 장치 사이의 데이터를 관리하기 때문입니다.

\n

DMA에서는 CPU가 전송할 데이터의 위치, 포인터, 바이트 크기만 DMA 컨트롤러에 전달하면,\nDMA가 입출력 작업을 대신 처리하고 전체 작업이 완료될 때만 CPU에 인터럽트를 보냅니다.\n이로 인해 CPU와 여러 입출력 장치가 직접 연결되던 기존 구조에서 CPU-DMA-입출력 장치 구조로 변화했고,\nCPU의 가용 시간이 현저히 증가하는 효과를 얻었습니다.\n이는 교수가 조교에게 학생 관리를 맡기고 최종 결과만 확인하는 것에 비유할 수 있으며,\n현재 DMA는 많은 컴퓨터 장치에서 보편적으로 사용되는 기술이 되었습니다.

\n
\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\nDMA 방식을 순서로 설명하자면\n
    \n
  1. CPU가 DMA 컨트롤러에게 입출력 요청합니다.
  2. \n
  3. DMA 컨트롤러가 메모리와 입출력 장치 간의 데이터 전송을 직접 수행합니다.
  4. \n
  5. 데이터 전송이 완료되면 DMA 컨트롤러가 인터럽트를 발생 시켜 CPU에게 완료를 알립니다.
  6. \n
  7. CPU는 인터럽트를 받아서 필요한 후처리 수행합니다.
  8. \n
","frontmatter":{"title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리","date":"September 08, 2025","update":"September 08, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/5/","readingTime":{"minutes":4.025}}},"seriesList":{"edges":[{"node":{"id":"86bebffe-ff00-58c2-a118-12a9ba3dffb6","fields":{"slug":"/1/"},"frontmatter":{"title":"1. 운영체제의 역할과 커널의 기능"}}},{"node":{"id":"4df66f0c-fb47-581a-8541-4336bdf66a9c","fields":{"slug":"/2/"},"frontmatter":{"title":"2. CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"83591dea-9474-596e-a50c-9686920054ff","fields":{"slug":"/3/"},"frontmatter":{"title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"77088a89-4f41-5fd9-935b-ed7406bb0e20","fields":{"slug":"/4/"},"frontmatter":{"title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"359416d8-e0ed-5c0b-a589-90cbc4a84fc0","fields":{"slug":"/5/"},"frontmatter":{"title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"0fed2fcc-c794-558d-ab3f-4fbb91b7721d","fields":{"slug":"/6/"},"frontmatter":{"title":"6. 동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":{"fields":{"slug":"/4/"},"frontmatter":{"title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}},"next":{"fields":{"slug":"/6/"},"frontmatter":{"title":"6. 동기식/비동기식 I/O의 차이와 활용 사례"}}},"pageContext":{"id":"359416d8-e0ed-5c0b-a589-90cbc4a84fc0","series":"운영체제 기본 개념","previousPostId":"77088a89-4f41-5fd9-935b-ed7406bb0e20","nextPostId":"0fed2fcc-c794-558d-ab3f-4fbb91b7721d"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/6/page-data.json b/public/page-data/6/page-data.json deleted file mode 100644 index a258dd3..0000000 --- a/public/page-data/6/page-data.json +++ /dev/null @@ -1 +0,0 @@ -{"componentChunkName":"component---src-templates-post-jsx","path":"/6/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"0fed2fcc-c794-558d-ab3f-4fbb91b7721d","excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","html":"

IO란

\n

개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다.

\n

예시를 들어서

\n
    \n
  • 파일 읽기/쓰기 (문서를 열거나 저장하는 행위)
  • \n
  • 네트워크 통신(웹사이트 접속, 이메일 전송)
  • \n
  • 데이터베이스 조회(회원 정보 검색)
  • \n
\n

이런 일련의 행위는 공통적인 특징이 있는데, 물리적인 시간이 걸린다는 점입니다.\n그렇기 떄문에 IO를 어떻게 다룰까에 대한 방법또한 여러가지 존재합니다.

\n
\n
\n

동기와 비동기란

\n

IO를 다루는 방법에는 동기, 비동기에 대한 개념이 등장합니다.\n이러한 개념을 사전에 정의 하고 내려가겠습니다.

\n

동기 (Synchronous)

\n

프로그램에서 말하는 동기란 하나의 작업에 대해서 요청과 응답 과정을 기다리는 행위입니다.\n예를들어, WAS가 데이터베이스에 조회 요청을 하고 데이터베이스는 요청받은 데이터를 돌려줄것입니다.\n이 과정에서 WAS는 요청직후 부터 응답을 받을때 까지 과정에서 데이터베이스의 응답을 기다리게 됩니다. 이것이 동기입니다.

\n
\n

동기의 특징

\n

순차적 실행: 한 작업이 완료되어야 다음 작업이 시작\n블로킹: 현재 작업이 끝날 때까지 다른 작업은 대기\n예측 가능: 코드가 위에서 아래로 순서대로 실행

\n
\n
\n

비동기 (Asynchronous)

\n

그렇다면 비동기는 하나의 작업에 대해서 요청과 응답 과정을 기다리지 않는 행위입니다.\n예를들어, WAS가 데이터베이스에 조회 요청을 하게 되면 데이터베이스가 이를 수행하고 응답할것입니다.\n이 과정 사이에 시간동안 WAS는 본인의 다른 작업을 수행하다가 데이터베이스의 응답을 받게 됩니다.\n즉 요청과 응답 사이 기간동안 WAS는 본인의 일을 하며 무작정 기다리지 않는 것입니다.

\n
\n

비동기의 특징

\n

동시 실행: 여러 작업을 동시에 시작 가능\n논블로킹: 작업 완료를 기다리지 않고 다른 작업 진행\n콜백/Promise: 작업 완료 시 결과를 알려주는 방식

\n
\n

동기식 I/O

\n

\"img.png\"

\n
\n

동기식IO는 IO요청이 발생하였을 때 이전 동기 설명처럼 IO요청이 끝날때 까지 기다리는 방식입니다.\n프로그램이 IO작업을 요청하게 되면, 다른 동작을 수행하지 않고 멈춰서 IO작업이 리턴되기 까지 기다립니다.\nI/O작업이 완료되면 인터럽트를 통해 완료를 알리게 됩니다. 이후 CPU 제어권이 기존 프로그램에게 넘어가게 됩니다.

\n

이러한 방식의 특징은 구현이 쉽다는 특징이 있지만, 연산에 대한 기다림으로 인해 자원 낭비를 하는 특징이 있습니다.

\n

비동기식 I/O

\n

\"img.png\"

\n

비동기식IO는 IO요청이 발생하였을 떄 이전 비동기 설명처럼 IO요청을 기다리지 않는 방식입니다.\n프로그램이 IO 작업을 요청하고, 그 작업이 완료되기를 기다리지 않고 즉시 다음 작업으로 넘어가는 방식입니다.

\n

이러한 방식의 특징은 구현의 복잡성이 높다는 것이지만, 대용량 데이터를 처리하는데 여러 IO작업을 동시에 처리해야 할 떄 유용합니다.

","frontmatter":{"title":"6. 동기식/비동기식 I/O의 차이와 활용 사례","date":"September 09, 2025","update":"September 09, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/6/","readingTime":{"minutes":4.99}}},"seriesList":{"edges":[{"node":{"id":"86bebffe-ff00-58c2-a118-12a9ba3dffb6","fields":{"slug":"/1/"},"frontmatter":{"title":"1. 운영체제의 역할과 커널의 기능"}}},{"node":{"id":"4df66f0c-fb47-581a-8541-4336bdf66a9c","fields":{"slug":"/2/"},"frontmatter":{"title":"2. CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"83591dea-9474-596e-a50c-9686920054ff","fields":{"slug":"/3/"},"frontmatter":{"title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"77088a89-4f41-5fd9-935b-ed7406bb0e20","fields":{"slug":"/4/"},"frontmatter":{"title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"359416d8-e0ed-5c0b-a589-90cbc4a84fc0","fields":{"slug":"/5/"},"frontmatter":{"title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"0fed2fcc-c794-558d-ab3f-4fbb91b7721d","fields":{"slug":"/6/"},"frontmatter":{"title":"6. 동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":{"fields":{"slug":"/5/"},"frontmatter":{"title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리"}},"next":{"fields":{"slug":"/7/"},"frontmatter":{"title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},"pageContext":{"id":"0fed2fcc-c794-558d-ab3f-4fbb91b7721d","series":"운영체제 기본 개념","previousPostId":"359416d8-e0ed-5c0b-a589-90cbc4a84fc0","nextPostId":"260ee945-dda8-544a-907f-08886cb18912"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/7/page-data.json b/public/page-data/7/page-data.json deleted file mode 100644 index e965bb6..0000000 --- a/public/page-data/7/page-data.json +++ /dev/null @@ -1 +0,0 @@ -{"componentChunkName":"component---src-templates-post-jsx","path":"/7/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"260ee945-dda8-544a-907f-08886cb18912","excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. ![img.png](실행중인 프로세스.png) 백그라운드…","html":"

프로세스란 무엇일까?

\n
\n

우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다.

\n

여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다.

\n
\n
\n

![img.png](실행중인 프로세스.png)

\n
\n위 사진처럼 보이는 것보다 더 많은 프로세스가 작동하고 있는데, 여기서 사용자가 볼 수 있는 프로세스를 포그라운드 프로세스 라며 명하며,\n보이지 않는 프로세스를 백그라운드 프로세스라고 부르게 됩니다. \n

백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는 다는 뜻은 아닌데 백그라운드 프로세스 중에서 사용자와 상호작용 하지 않고 자신의 일만을 수행하기 위해 존재하는\n프로세스를 데몬(daemon) 프로세스라고 명합니다.

\n
\n

프로세스 제어 블록(PCB)

\n
\n

CPU자원이 한정되어 있는 반면에, 모든 프로세스는 실행을 위해 CPU를 사용하여야 합니다.\n그렇기 떄문에 프로세스들은 한정된 시간 만 CPU를 사용하며 자신의 차례를 기다립니다.

\n

운영체제는 빠르게 번갈아 수행되는 프로세스의 실행 순서를 관리하고, 프로세스에 CPU와 여러가지 자원을 배분합니다.\n이를 위해 운영체제는 프로세스 제어 블록(PCB)를 이용합니다.

\n
\n

PCB는 커널 영역에 생성되고, 수많은 프로세스를 PCB를 통해 태그처럼 사용해 특정 프로세스를 식별하며 해당 프로세스를 처리하는데 필요한 정보를 판단합니다.

\n

즉, 가게 주인이 물건을 태그를 통해 판단하고 가격을 알 수 있고, 생산지를 알 수 있는 것처럼 PCB는 운영체제가 수 많은 프로세스를 식별하고 그 프로세스의 정보를 판단하게 돕습니다.

\n
\n
\n

PCB의 구조

\n
\n
\n

\n \n \n \n \n \n
img.png
\n

\n

사진 출처

\n
\n

위 그림처럼 PCB는 프로세스를 식별하기 위해 여러가지 정보를 담고 있습니다. 프로세스의 ID나,\n레지스터의 값 혹은 상태같이 많은 정보를 담고있으며 이를 알아보고자 합니다.

\n
\n

프로세스 ID

\n

\"img.png\"

\n

프로세스 ID(PID)는 프로세스를 식별하기 위해 존재하는 고유 ID입니다. 메모장을 두개 킨다고 할지라도 다른 프로세스ID가\n만들어지는 것처럼 중복된 활동이여도 하나의 프로세스는 고유한 ID를 가지게 됩니다.

\n
\n

레지스터 값

\n

프로세스는 자신의 실행 차례가 돌아오면 이전까지 사용했던 레지스터의 중간값들을 모두 복원합니다.\n여기에는 프로그램 카운터가 속하게 됩니다.

\n
\n

프로세스 상태

\n

현재 프로세스가 어떤 상태인 기록합니다. 입출력장치를 사용하기 위해 기다리는지 혹은 CPU를 사용하고 있는 상태인지 와 같은\n상태를 기록하며 자세한 상태는 다음장에서 설명합니다.

\n
\n

CPU 스케줄링 정보

\n

프로세스가 언제, 어떤 순서로 CPU를 할당받을지에 대한 정보도 PCB에 기록됩니다.

\n
\n

메모리 관리 정보

\n

프로세스마다 메모리에 저장된 위치가 다릅니다. 그렇기 떄문에 PCB에는 해당 프로세스가 저장된 메모리 위치를 기록해야 합니다.

\n
\n
\n

프로세스의 메모리 영역

\n
\n

프로세스가 생성되면 커널 영역에 PCB가 생성됩니다. 그렇다면 커널 영역이 아닌 사용자 영역에는 어떤 데이터가 들어갈까요?

\n

\"img.png\"

\n

사진출처

\n

위 그림처럼 하나의 프로세스는 크게 코드영역(Text), 데이터 영역(Bss,Gvar), 힙 영역(Heap), 스택 영역(Stack) 4가지로 나뉩니다.

\n

차례대로 설명하자면,

\n
\n
\n

코드영역 or 텍스트영역(Text)

\n

이곳에는 실행할 수 있는 기계어로 이루어진 명령어가 저장됩니다. 가공할 수 있는 데이터가 아닌\nCPU가 실행해야 하는 명령어가 담겨있기 때문에 읽기모드만 지원합니다.

\n
\n

데이터 영역

\n

프로그램을 실행하는 동안 유지되어야 하는 데이터가 저장되는 공간입니다. 대표적은 전역 변수가 이곳에 해당합니다.

\n
\n

코드영역 & 데이터 영역 공통점

\n

위 두 영역은 크기가 변하지 않습니다. 프로그램을 구성하는 명령어가 작동중에 코드 양이 늘어나는 경우가 없으니\n이 두가지 영역을 정적 할당 영역이라고 부릅니다.

\n
\n

힙 영역

\n

프로그래머가 직접 할당할 수 있는 공간입니다. 프로그래밍 과정에서 힙 영역에 데이터를 할당했다면 언젠가는 이 영역에\n데이터를 반환해야 합니다. 그렇지 않다면 메모리 용량은 점점 줄어들어 장애가 발생할 수 있습니다.

\n

이런 문제를 메모리를 할당받고 해제 하지 않았다고 하여 누수가 발생했다. 즉 메모리 누수라고 부릅니다.

\n
\n

스택 영역

\n

스택 영역은 데이터를 일시적으로 저장하는 공간입니다.\n데이터 영역에 담기는 값과는 다르게 잠깐 쓸 데이터를 담아두는 공간입니다.\n함수를 실행하는 동안 필요한 지역변수, 매개 변수가 이곳에 해당합니다.\n그렇기 떄문에 함수가 종료되면 스택 영역에서 해당 함수에 쓰였던 변수들도 같이 없어지게 됩니다.

\n
\n
\n

힙 영역 & 스택 영역 공통점

\n

위 두 영역은 실시간으로 그 크기가 변할 수 있고 그렇기 떄문에 동적 할당 영역이라고 부르게 됩니다.

\n

그림을 보면 unused memory영역이 있는데, 스택 영역과 힙 영역이 동적이기 떄문에 힙은 아래에서 위로, 스택은\n위에서 아래로 주소를 할당하게 됩니다. 그렇게 되면 서로 충돌없이 동적으로 값을 할당할 수 있기 때문입니다.

\n

여기서 만약에 힙이나 스택에 많은 정보가 담겨서 서로의 지점을 충돌 할 수 있는데, 그럴때 각각 stack overflow,\nheap overflow라고 부르게 됩니다.

","frontmatter":{"title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","date":"September 10, 2025","update":"September 10, 2025","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"},"fields":{"slug":"/7/","readingTime":{"minutes":9.175}}},"seriesList":{"edges":[{"node":{"id":"260ee945-dda8-544a-907f-08886cb18912","fields":{"slug":"/7/"},"frontmatter":{"title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},{"node":{"id":"b775e483-4005-578f-8b56-bc4cf3f18a77","fields":{"slug":"/8/"},"frontmatter":{"title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},{"node":{"id":"c2d81bbc-3b4c-5c89-b193-1807200e7f30","fields":{"slug":"/9/"},"frontmatter":{"title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},{"node":{"id":"2e4f9ff2-e2bf-57e3-aaad-7eb2f7fd16b2","fields":{"slug":"/10/"},"frontmatter":{"title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},{"node":{"id":"6b2d0bc1-f501-5533-becc-2e0d0340e9e6","fields":{"slug":"/11/"},"frontmatter":{"title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}}]},"previous":{"fields":{"slug":"/6/"},"frontmatter":{"title":"6. 동기식/비동기식 I/O의 차이와 활용 사례"}},"next":{"fields":{"slug":"/8/"},"frontmatter":{"title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},"pageContext":{"id":"260ee945-dda8-544a-907f-08886cb18912","series":"프로세스와 쓰레드에 대해서 알아보기","previousPostId":"0fed2fcc-c794-558d-ab3f-4fbb91b7721d","nextPostId":"b775e483-4005-578f-8b56-bc4cf3f18a77"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/8/page-data.json b/public/page-data/8/page-data.json deleted file mode 100644 index 0b5179f..0000000 --- a/public/page-data/8/page-data.json +++ /dev/null @@ -1 +0,0 @@ -{"componentChunkName":"component---src-templates-post-jsx","path":"/8/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"b775e483-4005-578f-8b56-bc4cf3f18a77","excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","html":"

문맥교환(Context Switching)

\n
\n

하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요?

\n

프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔을 때 이 과정을 이어받아 작업을 수행할 수 있습니다.

\n

여기서 하나의 프로세스를 실행하기 위해 필요한 정보들을 문맥(Context)라고 부르게 됩니다.\n이러한 문맥값들은 PCB속에 저장됩니다.환

\n
\n

\"img.png\"\n사진출처

\n

결국 프로세스 A에서 B로 프로세스가 넘어가는 순간에 프로세스 A정보를 백업하고 그작업이 끝난다면\n프로세스 B의 문맥을 불러오게 되며 이 것이 프로세스를 교대하는 방법입니다.

\n

문맥교환을 통해 여러개의 프로세스가 병렬적으로 시행되는 것 처럼 보이게 하지만 이러한 문맥교환은\n오버헤드가 발생할 수 있기 때문에 문맥교환이 자주일어나면 오버헤드를 신경써야 합니다.

\n
\n
\n

프로세스 상태

\n
\n

이전에 PCB에 기록되는 정보 중 프로세스 상태가 있다고 합니다. 여기서 말하는 프로세스 상태는 생성이 되었는지\n혹은 CPU를 사용하는지와 같은 정보를 통칭해서 프로세스 상태라고 부르게 됩니다.

\n
\n

프로세스 상태는 크게 다섯가지로 나뉠 수 있습니다.

\n

![img.png](프로세스 상태 전이도.png)\n사진출처

\n
\n

1. 생성 상태

\n

프로세스를 생성 중인 상태를 생성 상태라고 부릅니다. 메모리에 적재되어 PCB를 할당받은 상태를 생성상태라고 부르게 됩니다.\n생성 상태가 끝난다고 곧바로 실행되는 것이 아닌 준비 상태가 되어 실행되기를 기다리게 됩니다.

\n
\n

2. 준비 상태

\n

준비 상태는 당장 CPU를 할당받아 실행될 수 있지만, 차례가 오지않아 기다리고 있는 상태입니다.\n이 상태에서 준비가 되면 실행 상태로 넘어 갑니다. 그리고 다른 상태에서 다시 준비 상태로도 전환이 가능합니다.

\n

준비 상태인 프로세스를 실행 상태로 전환하는 것을 디스패치 라고 부릅니다.

\n
\n

3. 실행 상태

\n

실행 상태는 CPU를 할당받아 실행 중인 상태를 지칭 합니다. 실행 상태인 프로세스는 할당된 시간 동안 CPU를 사용할 수 있습니다.\n이때 제한된 시간내 프로세스를 완료하지 못한경우 준비 상태로 전환이 되며, I/O입력처럼 대기해야 하는 상황이 생기면\n대기 상태로 넘어가게 됩니다.

\n
\n

4. 대기 상태

\n

실행 상태에서 I/O입력과 같이 프로세스가 대기해야 하는 상황이 온다면 대기 상태로 진입하게 됩니다.\n대기 상태가 끝난다고 해도 실행 상태가 되는것이 아닌 준비 상태로 넘어가게 됩니다.

\n
\n

5. 종료 상태

\n

프로세스가 종료된 상태입니다. 이 상태에 도달하면 운영체제는 PCB와 프로세스가 사용한 메모리를 정리합니다.

\n
\n
\n

프로세스 계층 구조

\n
\n

프로세스는 실행 도중 시스템 호출을 통해 다른 프로세스를 생성할 수 있습니다.

\n

이때 새 프로세스를 생성한 프로세스를 부모 프로세스라고 부르게 되며, 생성 된 프로세스를 자식 프로세스라고\n부르게 됩니다.\n부모의 프로세스와 자식의 프로세스는 각각 고유한 PID를 가지며 자식프로세스에서 부모프로세스 PID를 PPID로 가지고 있기도 합니다.

\n
\n

![img.png](프로세스 계층 구조.png)\n[사진 출처: 혼자 공부하는 운영체제 저자:강민철]

\n
\n
\n

프로세스 생성기법

\n
\n

그렇다면 부모 프로세스가 어떻게 자식 프로세스를 생성 할까요?

\n

그 방법은 fork, exec라는 명령어를 통해서 생성하게 됩니다.

\n

부모 프로세스는 fork를 통해 자신의 복사본을 자식 프로세스로 생성해내고, 그 복사본은 exec명령어를 통해\n자신의 메모리 공간을 다른 프로그램으로 교체합니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

좀더 자세히 설명하면 fork, exec 모두 시스템 호출로 분류 됩니다.\n부모 프로세스는 fork 시스템 호출을 통해 자신의 복사본을 자식으로써 생성합니다.

\n

여기서 자식은 부모의 복사본이기 때문에 부모 프로세스의 자원들, 예를들면 메모리의 내용, 열린 파일의 목록등을\n상속하게 됩니다. 그렇다고 해서 모든 정보가 같지는 않습니다.

\n

왜냐하면, PID나 메모리 저장구조는 고유한 정보이기 때문에 fork로 만들어진 자식은 PID, 메모리 저장위치\n처럼 고유한 정보에 대해서는 개별적인 값을 가지고 있습니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

fork만 사용한 프로세스는 완전한 자식 프로세스라고 명하기는 조금 어렵습니다.\nPID와 같은 고유한 값을 제외한다면 부모가 가진 리소스를 동일하게 사용하는 대체품이기 때문입니다.

\n

그렇기 때문에 자식 프로세스는 자신의 프로세스를 가지기 위해 exec 시스템 호출을 하게 됩니다.

\n

exec 호출을 진행하게 되면 자신의 메모리 공간을 새로운 프로그램으로 덮어쓰게 됩니다.

\n

코드 영역과 데이터 영역의 내용이 실행한 프로그램으로 바뀌게 되고, 나머지 영역은 초기화 됩니다.

","frontmatter":{"title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","date":"September 11, 2025","update":"September 11, 2025","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"},"fields":{"slug":"/8/","readingTime":{"minutes":8.29}}},"seriesList":{"edges":[{"node":{"id":"260ee945-dda8-544a-907f-08886cb18912","fields":{"slug":"/7/"},"frontmatter":{"title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},{"node":{"id":"b775e483-4005-578f-8b56-bc4cf3f18a77","fields":{"slug":"/8/"},"frontmatter":{"title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},{"node":{"id":"c2d81bbc-3b4c-5c89-b193-1807200e7f30","fields":{"slug":"/9/"},"frontmatter":{"title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},{"node":{"id":"2e4f9ff2-e2bf-57e3-aaad-7eb2f7fd16b2","fields":{"slug":"/10/"},"frontmatter":{"title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},{"node":{"id":"6b2d0bc1-f501-5533-becc-2e0d0340e9e6","fields":{"slug":"/11/"},"frontmatter":{"title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}}]},"previous":{"fields":{"slug":"/7/"},"frontmatter":{"title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}},"next":{"fields":{"slug":"/9/"},"frontmatter":{"title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},"pageContext":{"id":"b775e483-4005-578f-8b56-bc4cf3f18a77","series":"프로세스와 쓰레드에 대해서 알아보기","previousPostId":"260ee945-dda8-544a-907f-08886cb18912","nextPostId":"c2d81bbc-3b4c-5c89-b193-1807200e7f30"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/9/page-data.json b/public/page-data/9/page-data.json deleted file mode 100644 index be8f7d0..0000000 --- a/public/page-data/9/page-data.json +++ /dev/null @@ -1 +0,0 @@ -{"componentChunkName":"component---src-templates-post-jsx","path":"/9/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"c2d81bbc-3b4c-5c89-b193-1807200e7f30","excerpt":"스레드란? img.png 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이…","html":"

스레드란?

\n
\n

\"img.png\"

\n
\n

스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다.

\n

또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다.

\n

마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이 여러 기능을 수행할 수 있습니다.

\n
\n

프로세스와 스레드

\n
\n

스레드를 이해하기 위해서는 프로세스와 엮어서 설명하고자 합니다.\n전통적인 CPU는 하나의 프로세스만 처리할 수 있었습니다. 메모장, 워드, 게임등 많은 프로세스가 하나의 실행\n흐름을 가지고 한 번의 하나의 부분만 실행되는 프로세스입니다.

\n

![img.png](단일스레드 프로세스.png)

\n

이런 프로세스를 단일 스레드 프로세스라고 부릅니다.

\n
\n

하지만, 스레드라는 개념이 도입되면서 하나의 프로세스가 한 번에 여러가지 일을 동시에 처리하는 것이 가능해졌습니다.\n프로세스를 구성하는 명령어를 동시에 처리하는것이 가능해졌습니다.

\n

![img.png](멀티스레드 프로세스.png)

\n
\n

그림을 통해 스레드를 보게 되면 스레드는 '프로세스를 구성하는 실행의 흐름 단위'라고 표현 가능 할 것입니다.

\n

왜냐하면, 하나의 프로세스 안에 여러가지 스레드가 있고 각각의 작업 흐름을 가지며 프로세스가 하는 일을 병렬적으로 만들어\n주기 때문입니다.

\n
\n
\n

스레드 메모리 구조

\n
\n

\"img.png\"

\n

스레드의 메모리 구조를 이해하기 위해서는 이전 프로세서의 구조를 상기해봐야 합니다.

\n

프로세스는 스택, 힙, 데이터, 코드 영역을 각자 가진다고 합니다.\n스레드는 '프로세스를 구성하는 실행 흐름의 단위'라고 했고, 이 떄문에 스레드는 프로세스의 메모리 구조의 대부분을 공유해서\n사용한다. 그렇기 때문에 여러 스레드의 작업이 하나의 프로세스 안에서 이루어져도 동시작업이 가능한 이유입니다.

\n
\n

그렇다면 어떻게 스레드는 프로세스와 스레드간 데이터를 공유하는 것일까?\n아래 그림을 통해서 보게되면

\n
\n

\"img.png\"\n사진출처

\n
\n

우선 하나의 프로세스안에 코드, 데이터, 힙, 스택 영역이 존재합니다. 그리고 프로세스 내부의 개별적인 스레드가 존재합니다.

\n

스레드가 레지스터, 프로그램 카운터, 스택을 개별적으로 가지는 핵심 이유는 독립적인 실행 흐름을 보장하기 위해서입니다.

\n

프로그램 카운터는 각 스레드가 서로 다른 코드 위치에서 실행될 수 있도록 현재 실행 지점을 개별 추적하고,

\n

레지스터는 각 스레드의 작업 데이터를 독립적으로 저장합니다.\n이를 통해 CPU가 스레드 간 전환할 때 현재 상태를 저장하고 복원하여 중단된 지점에서 정확히 재개할 수 있습니다.\n스택 영역을 따로 가지는 이유는 각 스레드가 독립적인 함수 호출 흐름을 가져야 하기 때문입니다.

\n

스택은 함수 호출 시 지역 변수, 매개변수, 리턴 주소를 저장하는데, 만약 스레드들이 스택을 공유한다면 한 스레드의\n함수 호출이 다른 스레드의 함수 실행에 영향을 주어 실행 흐름이 꼬이게 됩니다. 따라서 각 스레드는 독립적인 스택을 가져 서로 다른 함수를 안전하게 호출하고 실행할 수 있습니다.\n결과적으로 이런 구조를 통해 스레드들은 힙과 데이터 영역은 공유하면서도 각자 독립적인 실행 흐름을 유지할 수 있어\n, 하나의 프로세스 내에서 여러 작업을 동시에 효율적으로 처리할 수 있게 됩니다.

\n
\n
\n

TCB란

\n
\n

\n \n \n \n \n \n
img.png
\n

\n

스레드 제어 블록은 운영체제가 각 스레드를 관리하기 위해 유지하는 데이터 구조체입니다.\n프로세스 제어 블록(PCB)과 유사하지만 스레드 수준에서 필요한 정보들을 담고 있습니다.\n링크드 리스트 형태로 구현되어 PCB안에 해당 스레드의 TCB를 내포하고 있는 형태로 저장됩니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

\"img.png\"

\n
\n
\n

TCB는 사진과 같은 형태로 저장되며, 아래와 같은 정보를 가진다.

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
정보설명
스레드 식별자각 스레드를 식별하는 고유한 식별자
스레드 상태실행 준비 대기 등 스레드의 현재 상태
프로그램 카운터스레드가 다음에 실행할 명령어의 주소
레지스터스레드가 현재 사용하고 있는 CPU 레지스터의 값을 저장
스레드 우선순위스케줄링 결정에 사용되는 스레드의 우선순위
스레드 스택 포인터스택 내에서 현재 작업의 위치를 가리키는 레지스터
스레드 문맥 정보문맥 교환 시 저장되고 복원되어야 할 정보
","frontmatter":{"title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB","date":"September 12, 2025","update":"September 12, 2025","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"},"fields":{"slug":"/9/","readingTime":{"minutes":7.545}}},"seriesList":{"edges":[{"node":{"id":"260ee945-dda8-544a-907f-08886cb18912","fields":{"slug":"/7/"},"frontmatter":{"title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},{"node":{"id":"b775e483-4005-578f-8b56-bc4cf3f18a77","fields":{"slug":"/8/"},"frontmatter":{"title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},{"node":{"id":"c2d81bbc-3b4c-5c89-b193-1807200e7f30","fields":{"slug":"/9/"},"frontmatter":{"title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},{"node":{"id":"2e4f9ff2-e2bf-57e3-aaad-7eb2f7fd16b2","fields":{"slug":"/10/"},"frontmatter":{"title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},{"node":{"id":"6b2d0bc1-f501-5533-becc-2e0d0340e9e6","fields":{"slug":"/11/"},"frontmatter":{"title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}}]},"previous":{"fields":{"slug":"/8/"},"frontmatter":{"title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}},"next":{"fields":{"slug":"/10/"},"frontmatter":{"title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},"pageContext":{"id":"c2d81bbc-3b4c-5c89-b193-1807200e7f30","series":"프로세스와 쓰레드에 대해서 알아보기","previousPostId":"b775e483-4005-578f-8b56-bc4cf3f18a77","nextPostId":"2e4f9ff2-e2bf-57e3-aaad-7eb2f7fd16b2"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/about/page-data.json b/public/page-data/about/page-data.json old mode 100644 new mode 100755 index 826cb26..57978fb --- a/public/page-data/about/page-data.json +++ b/public/page-data/about/page-data.json @@ -1 +1 @@ -{"componentChunkName":"component---src-pages-about-jsx","path":"/about/","result":{"data":{"markdownRemark":{"html":"

English Guide

\n

Hello! This section is dedicated to introducing your blog. Here, you can showcase various information to your visitors, such as a blog introduction, personal profile, resume, portfolio, and more.

\n

Writing Guide

\n

To edit this page, modify the /contents/about/index.md file. You can write it in the same way as any other post. The path to this file cannot be changed.

\n

The Markdown document for the About page only contains a single frontmatter called title. The title frontmatter will be displayed as the title at the top of the About page.

\n

Disabling the About Page

\n
module.exports = {\n\n  // ...\n\n  useAbout: false, // 👈\n\n  // ...\n\n}
\n

You can disable the About page by setting the useAbout value to false in the blog-config.js file. If disabled, the tab in the blog header will be hidden, and visitors will not be able to access this page via the /about URL.

\n

한국어 가이드

\n

안녕하세요. 이 곳은 블로그를 소개하기 위한 공간입니다. 블로그 또는 자신에 대한 소개부터 이력서, 포트폴리오 등 다양한 정보를 이곳에서 방문자들에게 보여줄 수 있습니다.

\n

작성 가이드

\n

이 페이지를 편집하려면, /contents/about/index.md 파일을 수정하면 됩니다. 다른 포스팅을 작성하는 것과 동일한 방식으로 작성할 수 있습니다. 이 파일의 경로는 변경할 수 없습니다.

\n

About 페이지의 마크다운 문서는 오직 title 이라는 하나의 frontmatter 만 가지고 있습니다. title frontmatter 는 About 페이지 상단 제목으로 표시됩니다.

\n

비활성화

\n
module.exports = {\n\n  // ...\n\n  useAbout: false, // 👈\n\n  // ...\n\n}
\n

blog-config.js 파일의 useAbout 값을 false 로 설정하여 About 페이지를 비활성화 할 수 있습니다. 비활성화 된다면, 블로그 상단에 존재하는 탭이 숨겨지고, /about 경로로 이 페이지에 접속할 수도 없게 됩니다.

","frontmatter":{"title":"This is about page ✋"}},"allMarkdownRemark":{"totalCount":11}},"pageContext":{}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file +{"componentChunkName":"component---src-pages-about-jsx","path":"/about/","result":{"data":{"markdownRemark":{"html":"

English Guide

\n

Hello! This section is dedicated to introducing your blog. Here, you can showcase various information to your visitors, such as a blog introduction, personal profile, resume, portfolio, and more.

\n

Writing Guide

\n

To edit this page, modify the /contents/about/index.md file. You can write it in the same way as any other post. The path to this file cannot be changed.

\n

The Markdown document for the About page only contains a single frontmatter called title. The title frontmatter will be displayed as the title at the top of the About page.

\n

Disabling the About Page

\n
module.exports = {\n\n  // ...\n\n  useAbout: false, // 👈\n\n  // ...\n\n}
\n

You can disable the About page by setting the useAbout value to false in the blog-config.js file. If disabled, the tab in the blog header will be hidden, and visitors will not be able to access this page via the /about URL.

\n

한국어 가이드

\n

안녕하세요. 이 곳은 블로그를 소개하기 위한 공간입니다. 블로그 또는 자신에 대한 소개부터 이력서, 포트폴리오 등 다양한 정보를 이곳에서 방문자들에게 보여줄 수 있습니다.

\n

작성 가이드

\n

이 페이지를 편집하려면, /contents/about/index.md 파일을 수정하면 됩니다. 다른 포스팅을 작성하는 것과 동일한 방식으로 작성할 수 있습니다. 이 파일의 경로는 변경할 수 없습니다.

\n

About 페이지의 마크다운 문서는 오직 title 이라는 하나의 frontmatter 만 가지고 있습니다. title frontmatter 는 About 페이지 상단 제목으로 표시됩니다.

\n

비활성화

\n
module.exports = {\n\n  // ...\n\n  useAbout: false, // 👈\n\n  // ...\n\n}
\n

blog-config.js 파일의 useAbout 값을 false 로 설정하여 About 페이지를 비활성화 할 수 있습니다. 비활성화 된다면, 블로그 상단에 존재하는 탭이 숨겨지고, /about 경로로 이 페이지에 접속할 수도 없게 됩니다.

","frontmatter":{"title":"This is about page ✋"}},"allMarkdownRemark":{"totalCount":28}},"pageContext":{}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/app-data.json b/public/page-data/app-data.json old mode 100644 new mode 100755 index 842b6dd..afc7860 --- a/public/page-data/app-data.json +++ b/public/page-data/app-data.json @@ -1 +1 @@ -{"webpackCompilationHash":"bc441f0761e1ef528cca"} +{"webpackCompilationHash":"4ae85f1ca3e2e481f266"} diff --git a/public/page-data/dev-404-page/page-data.json b/public/page-data/dev-404-page/page-data.json new file mode 100644 index 0000000..b6de006 --- /dev/null +++ b/public/page-data/dev-404-page/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---cache-dev-404-page-js","path":"/dev-404-page/","result":{"data":{"allSiteFunction":{"nodes":[]},"allSitePage":{"nodes":[{"path":"/hs1/"},{"path":"/hs2/"},{"path":"/jc1/"},{"path":"/jc2/"},{"path":"/jc3/"},{"path":"/jc4/"},{"path":"/hs4/"},{"path":"/hs3/"},{"path":"/jc5/"},{"path":"/jc6/"},{"path":"/jc7/"},{"path":"/jc8/"},{"path":"/hs5/"},{"path":"/jc9/"},{"path":"/jc10/"},{"path":"/jc11/"},{"path":"/jc12/"},{"path":"/jc13/"},{"path":"/jc14/"},{"path":"/jc15/"},{"path":"/jc16/"},{"path":"/jc17/"},{"path":"/jc18/"},{"path":"/jc19/"},{"path":"/jc20/"},{"path":"/jc21/"},{"path":"/jc22/"},{"path":"/jc23/"},{"path":"/series/운영체제/"},{"path":"/series/운영체제-기본-개념/"},{"path":"/series/프로세스와-쓰레드에-대해서-알아보기/"},{"path":"/series/CPU-스케줄링/"},{"path":"/series/프로세스-동기화/"},{"path":"/series/가상메모리,-메모리분할/"},{"path":"/404/"},{"path":"/404.html"},{"path":"/about/"},{"path":"/"},{"path":"/search/"},{"path":"/series/"},{"path":"/tags/"}]}},"pageContext":{}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/hs1/page-data.json b/public/page-data/hs1/page-data.json new file mode 100755 index 0000000..b199b5a --- /dev/null +++ b/public/page-data/hs1/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/hs1/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"8b51f460-43e0-561e-ab49-84bc59be430a","excerpt":"운영체제(OS, Operating System) 운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다. 운영체제가 없으면 어떻게 될까? 꼭 필요할까? A computer is a machine that can be programmed to automatically carry ou…","html":"

운영체제(OS, Operating System)

\n

운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다.

\n

\n \n \n \n

\n

운영체제가 없으면 어떻게 될까? 꼭 필요할까?

\n
\n

A computer is a machine that can be programmed to automatically carry out sequences of arithmetic or logical operations\n(컴퓨터는 산술적 또는 논리적 연산(계산)의 순서를 자동으로 수행하도록 프로그래밍할 수 있는 기계이다).\n - wikepedia

\n
\n

운영체제가 없다면 컴퓨터는 그저 하드웨어의 집합체에 불과하다.\n사용자는 프로그램을 실행하기 위해서 매번 하드웨어를 직접 제어해야 하며, 이렇게 하는 것은 매우 비효율적일거다.\n또한 직접 제어를 한다고 해도 하드웨어의 성능은 제한적이므로 이 환경에서 최대한의 성능을 끌어내기 위해 최적화라는 고통스러운 작업을 해야 할 것이다.\n이러한 상황을 상상해보면 \"배보다 배꼽이 더 크다\"라는 말이 떠오른다.

\n

실제로 운영체제라는 개념이 있기 전에는 사용자들이 하나의 작업을 위해 펀치카드를 소지하며 관리해야 했다.\n그리고 단순 하드웨어에 올려 실행하는 과정의 방식이기에 한 번에 하나의 프로그램만 실행할 수 있었고, 해당 프로그램이 끝나야 다른 프로그램을 수행할 수 있었다.\n지금처럼 복잡한 방식의 프로그램은 꿈도 꿀 수 없었을 것이다.

\n

이러한 문제를 해결하기 위해 운영체제가 나왔고, 다음과 같은 목적을 지닌다.

\n
    \n
  • 사용자에게 컴퓨터의 프로그램을 쉽고 효율적으로 실행할 수 있는 환경을 제공한다.
  • \n
  • 컴퓨터 시스템 하드웨어 및 소프트웨어 자원을 여러 사용자 간에 효율적 할당, 관리, 보호하는 것
  • \n
  • 운영체제는 제어 프로그램으로서 사용자 프로그램의 오류나 잘못된 자원 사용을 감시하는 것과 입출력 장치 등의 자원에 대한 연산과 제어를 관리한다.
  • \n
\n

운영체제은 위와 같은 목적을 위해 다양한 방식을 가지고 있다.

\n

일괄 처리 시스템 (Batch Operating System)

\n

사용자의 개입없이 비슷한 작업들을 모아서 순차적으로 처리하는 방식이다.\n한 작업이 끝나야 다음 작업이 실행되기 때문에 모든 작업이 완료될 때까지 기다릴 수 있는 환경에서 사용된다.\n주로 대용량 데이터를 처리하거나 시간이 많이 소요되는 작업에 활용되며, 사용자의 개입이 필요하지 않고 반복적인 작업을 일괄적으로 처리할 수 있다.

\n

다중 프로그래밍 시스템 (Multi Programming System)

\n

이 방식은 CPU을 최대한 사용하고 하는 방식으로,\n여러 응용프로그램을 메모리에 동시에 올라가 CPU가 쉬지 않고 여러 작업을 번갈아서 실행하며 항상 연산을 수행하는 상태로 활용하는 방식이다.\n하나의 프로그램을 실행하는 동안 다른 프로그램은 대기하거나 I/O 작업 등을 수행하며 메모리에 올라간 상태로 대기하게 된다.\n운영 체제는 이런 과정에서 CPU를 배분하는 작업 스케줄링과 CPU 스케줄링을 진행하며,\n이를 통해 시스템 자원을 효율적으로 활용하고 응용 프로그램들이 서로 영향을 주지 않으면서 병렬적으로 실행된다.

\n

시분할 시스템 (Time Sharing System)

\n

이 방식은 CPU에 대해 일정 시간을 할당 받아 짧은 간격으로 번갈아 실행하는 방식이다.\n다중 프로그래밍 시스템에서는 Context Switching(CPU 점유 권한 전환)이 I/O작업에서만 발생한다.\n이를 통해서만 스케줄링을 할 경우 하나의 프로세스가 아주 오래 CPU를 독점하고 있는 상태가 발생할 수 있다는 문제점이 있다.\n이를 해결하기 위한 것이 시분할 시스템으로, 다중 프로그래밍과 비슷하지만 모든 프로세스가 특정 시간만 CPU를 점유하고 다른 프로세스에 권한을 넘겨주는 방식으로\nContext Switching 기준 시간으로 시분할을 구현해서 RR(Round-Robin) 알고리즘으로 스케줄링을 한다.

\n

대화형 시스템(Interactive System)

\n

앞서 설명한 일괄 처리 시스템은 처리해야할 작업들을 한번에 정의하고 일괄적으로 처리하는 방식이었다.\n이러한 일괄 처리 시스템의 문제점은 처리가 이루어지는 중에 시스템의 상태를 확인하기가 힘들고,\n작업이 끝나 결과가 도출되기 전까지는 작업을 수정할 수도 없다는 문제점이 있었다.\n이를 보완하기위해 등장한 시스템이 대화형 시스템으로,\n작업 중에도 사용자가 데이터, 명령 또는 작업을 입력하면 컴퓨터가 즉각적으로 해당 입력에 응답하는 사용자와 컴퓨터 간의 상호작용을 통해 작동하는 방식이다.

\n

커널(Kernel)

\n

그럼 우리들의 컴퓨터 속 운영체제는 어떻게 이러한 기능을 수행하고 있을까?

\n

운영체제의 이러한 핵심적인 부분을 담당하고 수행하는 것이 바로 커널이다.

\n

\n \n \n \n \n커널을 한글로 번역하면 핵심이다! 재밌지 아니한가? 아무튼 다시 돌아와서 커널은 어떻게 운영체제의 기능을 수행할까?

\n

커널은 하드웨어를 인터페이스로 제공하여 여러 사용자 또는 여러 프로세스가 하드웨어 즉 리소스를 효율적으로 관리하며 작업을 수행할 수 있도록 해준다.\n여기서 중요한 점은 커널은 사용자가 직접 제어할 수는 없다.\n그 이유는 보안상 유저 어플리케이션이 함부로 운영체제의 리소스를 건들지 못하게 하기 위해서다.\n그래서 커널에는 하드웨어에 접근이 허가된 커널모드와 그렇지 못한 유저모드로 분리가 되어있다.

\n

\n \n \n \n

\n

커널의 구조는 위 사진과 같은데, 간단한 흐름을 설명하자면 사용자가 유저모드인 어플리케이션을 실행하면서 발생하는 요청이 시스템 콜을 통해 커널 모드로 전환이 된다.\n애플리케이션은 커널모드로 전환되었다가 작업을 끝낸 후 응답을 반환하면서 다시 유저모드로 되돌아 가게 된다.\n여기서 시스템 콜은 뭐지 싶을텐데 어플리케이션의 요청이 커널에 접근해 시스템에 요청하는 것으로 간단히 유저모드에서 커널모드로 전환하는 것이라고 생각하면 된다.

\n

\n \n \n img 4\n \n

\n

이러한 방식을 통해 사용자의 프로세스가 직접적으로 운영체제의 리소스를 함부로 변경하지 못하게 보호해준다.

","frontmatter":{"title":"1. 운영체제의 개념과 구조","date":"September 03, 2025","update":"September 03, 2025","tags":["운영체제"],"series":"운영체제"},"fields":{"slug":"/hs1/","readingTime":{"minutes":9.8}}},"seriesList":{"edges":[{"node":{"id":"8b51f460-43e0-561e-ab49-84bc59be430a","fields":{"slug":"/hs1/"},"frontmatter":{"title":"1. 운영체제의 개념과 구조"}}},{"node":{"id":"a19bc92c-cb8c-5cf6-a09a-30349b5f21dc","fields":{"slug":"/hs2/"},"frontmatter":{"title":"2. 커널의 작동 방식"}}},{"node":{"id":"3ad80296-57ed-53b0-ada7-f06096fe6849","fields":{"slug":"/hs4/"},"frontmatter":{"title":"4. 쓰레드 "}}},{"node":{"id":"46425f46-05a1-5269-ad13-c4687acafbf1","fields":{"slug":"/hs3/"},"frontmatter":{"title":"3. 프로세스"}}},{"node":{"id":"cb8ba341-aac3-5491-9121-5bee87c5172c","fields":{"slug":"/hs5/"},"frontmatter":{"title":"5. CPU 스케줄링"}}}]},"previous":null,"next":{"fields":{"slug":"/hs2/"},"frontmatter":{"title":"2. 커널의 작동 방식"}}},"pageContext":{"id":"8b51f460-43e0-561e-ab49-84bc59be430a","series":"운영체제","previousPostId":null,"nextPostId":"a19bc92c-cb8c-5cf6-a09a-30349b5f21dc"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/hs2/page-data.json b/public/page-data/hs2/page-data.json new file mode 100755 index 0000000..d72c620 --- /dev/null +++ b/public/page-data/hs2/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/hs2/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"a19bc92c-cb8c-5cf6-a09a-30349b5f21dc","excerpt":"앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다.\n이제 커널이 어떻게 작동하는지 제대로 알아보자. 먼저 인터럽트(Interrupt)에 대해 알아야 한다. 컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데\n이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다.\n이중 하나가 인터럽트이다. \n인터럽트는 중단시키다라…","html":"

앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다.\n이제 커널이 어떻게 작동하는지 제대로 알아보자.

\n

먼저 인터럽트(Interrupt)에 대해 알아야 한다.

\n

\n \n \n \n img_3.png\n \n \n
img_3.png
\n

\n

컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데\n이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다.\n이중 하나가 인터럽트이다.

\n

\n \n \n img\n \n \n인터럽트는 중단시키다라는 의미로 초인종과 같다고 할 수 있다.\n즉, 인터럽트가 발생하면 잠깐 멈추고 다시 실행된다.

\n

\n \n \n img 1\n \n

\n

실제 발생하는 대부분의 인터럽트는 I/O 인터럽트이다.\n예를들면, 우리가 자바에서 print을 할 때 print라는 API를 파일이라는 인터페이스를 통해서 유저모드에서 커널 모드로 시스템 콜이 발생한다.\n유저모드 API에서 커널모드 구성요소에서 시스템 콜이 이어지고 디바이스 드라이버를 제어하기 시작하는데\n이때 디바이스 드라이버가 인터럽트를 CPU에 요청한다. 이 행위를 IRQ라고 한다.\n이러한 IRQ는 장치마다 다른 번호로 관리하게 된다.\n아무튼 출력기기에 출력이 되면, 다시 역순으로 디바이스(하드웨어)에서 디바이스 드라이버로,\n디바이스 드라이버에서 커널 모드로 해서 최종적으로 유저 모드로 다시 돌아오게 된다.

\n

\n \n \n \n \n이때, 이러한 행위 도중 wait을 걸면 블라킹(동기) 안걸면 논블라킹(비동기)으로 동작하게 된다.

\n

인터럽트에는 우선순위가 있고 외부 인터럽트인지 내부 인터럽트인지에 따라 우선순위가 달라진다.

\n

먼저, 외부 인터럽트로 내부 인터럽트보다 우선 시 된다.

\n

그 중에서도 우선 순위가 있는데, 다음과 같다.

\n
    \n
  • 전원 이상 인터럽트: 말 그대로 정전 또는 파워 이상
  • \n
  • 기계 착오 인터럽트: CPU의 기능적인 오류.
  • \n
  • 외부 신호 인터럽트: 타이머 또는, 키보드 인터럽트 키(Ctrl + Alt + Delete). 외부장치로부터 인터럽트 요청이 있는 경우. I/O 인터럽트와 다른 개념이다.
  • \n
  • 입출력 인터럽트: 입출력 장치가 데이터 전송을 요구하거나 전송이 끝나 다음 동작이 수행되어야 할 경우. 입출력 데이터에 이상이 있는 경우. 우리가 자주 다루게 될 인터럽트 부분이다.
  • \n
\n

이제 내부 인터럽트인데, 사실 우리가 주로 다루게 될 것은 외부 인터럽트에 있어 내부 인터럽트는 뭐가 있는지만 대강 본다.

\n
    \n
  • 명령어 잘못 인터럽트: 잘못된 명령어나 잘못된 데이터를 사용할 때 발생하며 Trap이라 부른다,
  • \n
  • 프로그램 검사
  • \n
  • 소프트웨어 인터럽트(=SVC, SuperVisor Call)
  • \n
\n

인터럽트 동작 순서에 대해 다시 살펴보면 다음과 같은데,

\n
    \n
  1. 인터럽트 요청
  2. \n
  3. 프로그램 실행 중단
  4. \n
  5. 현재 프로그램 상태 보존 -> PCB(Process Control Block), PC(Program Counter) 등
  6. \n
  7. 인터럽트 서비스 루틴 실행: 인터럽트 처리 코드
  8. \n
  9. 상태 복구
  10. \n
  11. 중단 프로그램 실행 재개
  12. \n
\n

\n \n \n img 2\n \n

\n

이 과정에서 유저모드에서 커널모드로 넘어갈 떄 컨텍스트 스위칭이 되면서 오버헤드가 발생하는데 이로 인해 시스템 상 지연이 발생한다.\n하지만 고성능 어플리케이션을 할 때 이 지연은 꽤나 치명적일 것이다.\n그래서 위와 같이 DMA(Direct Memory Access)라는 기술을 사용하게 됐다.\n예를들어, DirectX라는 것이 있는데 이는 게임을 할 때 이러한 컨텍스트 스위칭 되는 부분을 건너뛰어 직접 드라이버까지 가는 방식이 있다.\n이렇듯 DirectX처럼 인터럽트 시 컨텍스트 스위칭으로 인한 오버헤드가 발생하면서 지연이 발생하는데 이걸 해소하는 것이 DMA인 것이다.\n정리하자면, DMA는 RAM에 일정 부분을 예약해 불필요한 컨텍스트 스위칭을 스킵해 오버헤드 방지 및 지연을 획기적으로 줄이는 방식이다.

","frontmatter":{"title":"2. 커널의 작동 방식","date":"September 04, 2025","update":"September 04, 2025","tags":["운영체제"],"series":"운영체제"},"fields":{"slug":"/hs2/","readingTime":{"minutes":5.85}}},"seriesList":{"edges":[{"node":{"id":"8b51f460-43e0-561e-ab49-84bc59be430a","fields":{"slug":"/hs1/"},"frontmatter":{"title":"1. 운영체제의 개념과 구조"}}},{"node":{"id":"a19bc92c-cb8c-5cf6-a09a-30349b5f21dc","fields":{"slug":"/hs2/"},"frontmatter":{"title":"2. 커널의 작동 방식"}}},{"node":{"id":"3ad80296-57ed-53b0-ada7-f06096fe6849","fields":{"slug":"/hs4/"},"frontmatter":{"title":"4. 쓰레드 "}}},{"node":{"id":"46425f46-05a1-5269-ad13-c4687acafbf1","fields":{"slug":"/hs3/"},"frontmatter":{"title":"3. 프로세스"}}},{"node":{"id":"cb8ba341-aac3-5491-9121-5bee87c5172c","fields":{"slug":"/hs5/"},"frontmatter":{"title":"5. CPU 스케줄링"}}}]},"previous":{"fields":{"slug":"/hs1/"},"frontmatter":{"title":"1. 운영체제의 개념과 구조"}},"next":{"fields":{"slug":"/jc1/"},"frontmatter":{"title":"운영체제의 역할과 커널의 기능"}}},"pageContext":{"id":"a19bc92c-cb8c-5cf6-a09a-30349b5f21dc","series":"운영체제","previousPostId":"8b51f460-43e0-561e-ab49-84bc59be430a","nextPostId":"a856e34f-f9a9-5164-8fb5-befe1aa43bcd"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/hs3/page-data.json b/public/page-data/hs3/page-data.json new file mode 100755 index 0000000..1a420e8 --- /dev/null +++ b/public/page-data/hs3/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/hs3/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"46425f46-05a1-5269-ad13-c4687acafbf1","excerpt":"프로세스란? 컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 인스턴스를 의미합니다.\n여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다. 프로세스의 메모리 공간 프로세스는 다음 4개의 메모리 영역으로 구성되고 가상 메모리 공간에 독립적으로 형성됩니다. 코드 영역(Cod…","html":"

프로세스란?

\n

\n \n \n \n

\n

컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 인스턴스를 의미합니다.\n여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다.

\n

프로세스의 메모리 공간

\n

프로세스는 다음 4개의 메모리 영역으로 구성되고 가상 메모리 공간에 독립적으로 형성됩니다.

\n
    \n
  • 코드 영역(Code) : 프로그램 실행 코드가 적재되는 영역입니다. 읽기 모드만 지원합니다.
  • \n
  • 데이터 영역(Data) : 프로세스의 초기화 된 데이터들인 전역 변수와 정적 변수들이 적재되는 영역입니다.
  • \n
  • 힙 영역(Heap) : 런타임 동안 생성된 데이터를 보관하기 위해 동적으로 할당받는 영역입니다.
  • \n
  • 스택 영역(Stack) : 지역변수, 매개변수, 리턴 값, 복귀 주소 등이 저장되는 영역입니다.
  • \n
\n

이렇게 영역이 나눠진 이유는 최대한 중복적인 데이터를 방지하여 메모리 사용량을 줄이는데 목적이 있습니다.

\n
\n

예를 들면, 코드에서 공통으로 사용하는 부분을 전역 변수로 지정하는 행위와 같다.

\n
\n

PCB(프로세스 제어 블록)

\n

커널은 시스템 전체에 대해 레지스터에 하나의 프로세스 테이블을 두고 모든 프로세스의 정보를 관리합니다.\n여기서의 프로세스 정보는 해당 프로세스를 실행하기 위해 필요한 정보들로 컨텍스트라고 부릅니다.\n여기서 프로세스의 상태에 따라 프로세스를 교체하는 작업인 컨텍스트 스위칭 작업 이루어 지는데,\n이와 같은 상황에서 여러 프로세스를 관리하기 위해 각 프로세스들에 대해 식별이 가능해야 관리가 가능하기에 해당 프로세스의 정보가 필요합니다.

\n

예를 들어, 인터럽트가 발생해서 자원을 할당받은 프로세스가 대기 상태가 되고 다른 프로세스를 실행 상태로 올릴 때\n대기 중인 프로세스를 나중에 다시 수행하기 위해 대기 중인 프로세스의 상태와 같은 정보를 알아야 할 것입니다.

\n

운영체제의 커널은 이러한 이유로 활성된 프로세스를 관리하기 위해 해당 프로세스에 대한 정보를 PCB(프로세스 제어 블록)이라는 데이터 구조에 저장합니다.\n(\"PCB는 운영 체제가 프로세스를 표현한 것이다.\"라는 말도 있습니다.)

\n

\n \n \n img 1\n \n

\n
\n

PCB는 해당 프로세스가 실행되면 생성되어 종료 시 제거가 되는데 이 과정에서 PCB의 삽입 및 삭제가 용이한 연결 리스트(Linked List) 방식으로 관리됩니다.

\n
\n

Process Metadata

\n

그럼 PCB에는 어떤 정보가 담겨있을까요?\nPCB에는 아래와 같은 프로세스의 메타데이터들이 담겨져 있습니다.

\n
    \n
  • 프로세스 번호(PID, Process ID): 각 프로세스의 고유 식별 번호입니다.(PPID: 부모 프로세스 ID)
  • \n
  • 프로세스 상태(Process State): 프로세스가 현재 어떤 상태인지를 나타내는 정보(new, ready, running, waiting, end)입니다.
  • \n
  • 프로그램 카운터(PC, Program Counter): 이 프로세스에서 실행될 다음 명령어의 주소를 가리키는 포인터(주소)입니다.
  • \n
  • 레지스터 상태(Register State): 프로세스의 레지스터 값 세트로, 프로세스를 다시 실행할 때 현재 상태를 복원하는 데 사용됩니다.
  • \n
  • 스케줄링 정보(Scheduling Information): CPU 시간 스케줄링에 대한 정보입니다.
  • \n
  • 메모리 관리 정보 (Memory Management Information): 프로세스의 메모리 할당과 사용에 관한 정보입니다.
  • \n
  • 입출력 상태 (I/O Status): 프로세스가 입출력 작업을 수행 중인 경우, 해당 상태 정보 및 장치 정보입니다.
  • \n
\n

프로세스 상태

\n

운영체제의 커널은 프로세스를 관리하기 위해 프로세스 정보를 알아야 해서 PCB를 생성하는 것을 알았습니다.\n여기서 커널의 프로세스 관리는 프로세스 상태를 관리하는 것이기도 합니다.

\n

프로세스 상태는 위에서 언급한대로 프로세스가 현재 어떤 상태인지를 나타내는 정보로,\n프로세스의 상태에 따라 CPU를 할당하거나 대기 상태로 전환하는 등의 작업이 이루어집니다.\n프로세스 상태는 일반적으로 다음과 같은 상태로 구분됩니다.

\n

\n \n \n img 2\n \n

\n
    \n
  • New(생성) : 프로세스는 저장장치에서 메모리로 로드되어 생성됩니다. 이후 커널은 메모리를 할당하고 PCB를 생성하고 프로세스 테이블에 등록합니다. 실행 준비를 마치면 ready 상태로 전이됩니다.
  • \n
  • Ready(준비) : 프로세스가 CPU를 사용하고 있지는 않지만 언제든지 사용할 수 있는 상태로, 해당 상태의 프로세스들은 커널에 있는 준비 큐(우선순위 큐)에 들어갑니다. 스케줄러가 컨텍스트 스위칭을 수행할 때, 준비 큐에서 우선순위가 높은 프로세스가 CPU 스케줄링에 따라 리소스를 할당받아 running 상태로 전이(디스패치)됩니다.
  • \n
  • Running(실행) : 프로세스가 CPU를 차지하여 명령어들이 실행되고 있는 상태입니다. 할당된 시간을 모두 사용(타임아웃)했다면 타이머 인터럽트가 발생되어 준비 상태로 전이되고, 입출력 요청이나 자원 요청 등으로 인해 대기 상태로 전이될 수도 있습니다.
  • \n
  • Waiting(대기) : 프로세스 실행 도중 입출력 완료(주된 원인)와 같은 수신 등을 대기하는 상태를 말합니다.
  • \n
  • End(=terminated, 종료) : 프로세스의 실행이 종료된 상태입니다. 이떄, PCB와 프로세스의 메모리를 해제 또는 정리합니다.
  • \n
\n

프로세스 계층 구조

\n

프로세스는 실행 도중 시스템 콜을 통해 다른 프로세스를 생성할 수 있습니다.\n이때 시스템 콜을 호출한 프로세스를 부모 프로세스, 생성된 프로세스를 자식 프로세스라 합니다.

\n
\n

서로 다른 프로세스라 서로 다른 PID를 가집니다.\n일부 운영체제에서는 자식 프로세스의 PCB에 부모 프로세스의 PID (PPID)가 기록되기도 합니다.

\n
\n

프로세스 생성 기법은 복제와 교체 과정을 통한 방식을 사용합니다.

\n

\n \n \n img 3\n \n

\n

흐름의 시작인 부모 프로세스는 fork(복제) 시스템 콜을 통해 자신의 복사본을 자식 프로세스로 생성합니다.\n자식 프로세스는 exec(교체) 시스템 콜을 통해 자신의 메모리 공간을 다른 프로그램으로 교체합니다.\n이때, 자식 프로세스의 메모리 공간을 새로운 프로그램으로 덮어쓰게 합니다.(코드/데이터는 내용만 바꾸고, 나머지는 초기화)\n자식 프로세스가 exec 시스템 콜을 호출하지 않을 경우, 부모 프로세스와 자식 프로세스는 같은 코드를 병행하여 실행하는 프로세스가 됩니다.\n이러한 과정을 통해 프로세스는 계층 구조를 이루어 관리할 수 있습니다.

\n

많은 운영체제에서는 이처럼 프로세스를 낳는 계층적인 구조로써 프로세스들을 관리합니다.\n컴퓨터가 부팅될 때 실행되는 최초의 프로세스가 자식 프로세스들을 생성하고,\n생성된 자식 프로세스들이 새로운 프로세스들을 낳는 형식으로 여러 프로세스가 동시에 실행되는 것입니다.

\n

프로세스 간 통신

\n

앞서 언급했던 것처럼 프로세스는 서로 독립된 메모리 공간을 가지므로, 프로세스끼리는 서로의 영역에 접근 또는 간섭할 수 없습니다.\n이러한 이유로 통신이 필요할 경우, IPC를 통해 프로세스 간에 통신을 할 수 있습니다.\nIPC에는 공유 메모리를 이용한 통신과 파일을 통한 프로세스 간 통신 이렇게 두 가지 방법이 있습니다.

\n
\n

IPC 통신 시, 프로세스 간 데이터를 동기화하고 보호하기 위해 세마포어뮤텍스를 사용합니다.

\n
","frontmatter":{"title":"3. 프로세스","date":"September 08, 2025","update":"September 08, 2025","tags":["운영체제"],"series":"운영체제"},"fields":{"slug":"/hs3/","readingTime":{"minutes":11.625}}},"seriesList":{"edges":[{"node":{"id":"8b51f460-43e0-561e-ab49-84bc59be430a","fields":{"slug":"/hs1/"},"frontmatter":{"title":"1. 운영체제의 개념과 구조"}}},{"node":{"id":"a19bc92c-cb8c-5cf6-a09a-30349b5f21dc","fields":{"slug":"/hs2/"},"frontmatter":{"title":"2. 커널의 작동 방식"}}},{"node":{"id":"3ad80296-57ed-53b0-ada7-f06096fe6849","fields":{"slug":"/hs4/"},"frontmatter":{"title":"4. 쓰레드 "}}},{"node":{"id":"46425f46-05a1-5269-ad13-c4687acafbf1","fields":{"slug":"/hs3/"},"frontmatter":{"title":"3. 프로세스"}}},{"node":{"id":"cb8ba341-aac3-5491-9121-5bee87c5172c","fields":{"slug":"/hs5/"},"frontmatter":{"title":"5. CPU 스케줄링"}}}]},"previous":{"fields":{"slug":"/hs4/"},"frontmatter":{"title":"4. 쓰레드 "}},"next":{"fields":{"slug":"/jc5/"},"frontmatter":{"title":"인터럽트와 DMA를 통한 효율적 입출력 처리"}}},"pageContext":{"id":"46425f46-05a1-5269-ad13-c4687acafbf1","series":"운영체제","previousPostId":"3ad80296-57ed-53b0-ada7-f06096fe6849","nextPostId":"6fead90c-3201-5834-b766-1a6625757a89"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/hs4/page-data.json b/public/page-data/hs4/page-data.json new file mode 100755 index 0000000..0a5c2fd --- /dev/null +++ b/public/page-data/hs4/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/hs4/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"3ad80296-57ed-53b0-ada7-f06096fe6849","excerpt":"쓰레드란? 쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다. 그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다.\n이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다. 사용자 수준 쓰레드와 커널 수준 쓰레드의 차이 사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다.\n쓰레드와 관련된 모든 행위를 사용자 영…","html":"

쓰레드란?

\n

쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다.

\n

\n \n \n \n

\n

그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다.\n이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다.

\n
\n

사용자 수준 쓰레드와 커널 수준 쓰레드의 차이

\n

사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다.\n쓰레드와 관련된 모든 행위를 사용자 영역에서 하기 때문에,\n커널은 사용자 수준 쓰레드의 존재를 알지 못하고 쓰레드 교환에 개입하지 않습니다.\n커널 수준 쓰레드란, 커널이 직접 생성하고 관리하는 쓰레드를 의미합니다.

\n
\n

쓰레드의 메모리 공간

\n

같은 프로세스의 쓰레드는 프로세스로부터 각각의 스택을 나눠갖지만 Code, Data, Heap 메모리 영역을 공유합니다.\n하지만, 쓰레드 ID, 스택, PC나 레지스터 같은 쓰레드 컨텍스트에 대해서는 각기 다른 값을 가지고 있습니다.

\n

\n \n \n \n

\n

이렇게 각자의 PC, 레지스터, 스택을 가지고 있기에 쓰레드마다 독립적으로 실행할 수 있습니다.

\n

여기서 중요한 점은 프로세스의 쓰레드들은 실행에 필요한 최소한의 정보(PC, 레지스터, 스택)만을 유지한 채\n프로세스 자원을 공유하며 실행된다는 점입니다.

\n

TCB(쓰레드 제어블록)

\n

쓰레드 또한 프로세스의 PCB(프로세스 제어 블록)처럼 TCB(쓰레드 제어 블록)을 통해 관리됩니다.\nTCB는 각 쓰레드에 위치하고, 커널은 TCB를 통해 쓰레드를 관리합니다.

\n

그럼 TCB에는 어떤 정보가 담겨있을까요?\nTCB에는 아래와 같은 쓰레드의 메타데이터들이 담겨져 있습니다.

\n

\n \n \n \n

\n
    \n
  • 쓰레드 번호(TID, Thread ID): 각 쓰레드의 고유 식별 번호입니다.
  • \n
  • 스택 포인터 (Stack Pointer): 쓰레드가 존재하는 프로세스의 PCB에 대한 포인터
  • \n
  • 프로그램 카운터(PC, Program Counter): 이 쓰레드에서 실행될 다음 명령어의 주소를 가리키는 포인터(주소)입니다.
  • \n
  • 쓰레드 상태(Thread State): 쓰레드가 현재 어떤 상태인지를 나타내는 정보(new, ready, running, waiting, end)입니다.
  • \n
  • 레지스터 상태(Register State): 쓰레드의 레지스터 값 세트입니다.
  • \n
\n

각 프로세스에 대한 중요 정보를 강조하는 특정 정보가 쓰레드 제어 블록에 저장됩니다.

\n

프로세스와 쓰레드의 차이

\n

프로세스는 각각 독립된 메모리 영역(Code, Data, Heap, Stack)을 할당받고 고유 프로세스 ID를 가지는 특성으로 인해,\n프로세스끼리는 서로의 영역에 접근할 수 없습니다.\n그래서 한 프로세스가 다른 프로세스의 자원에 접근하려면 IPC(inter-process communication)을 사용해야 합니다.

\n

하지만, 쓰레드는 IPC와 같은 별도의 통신 방법 없이도 앞서 언급한 것처럼 프로세스의 Code, Data, Heap 메모리 영역을 공유합니다.

\n

이처럼 프로세스들 사이의 통신에 대한 어려움 해소 및 빠른 컨텍스트 스위칭으로 인해 쓰레드가 프로세스보다 더 가벼운 실행 단위로 사용됩니다.\n이로 인해 현대에 와서 운영체제의 실행단위는 프로세스에서 쓰레드로 바뀌어 가고 있습니다.

\n

동시성 환경에서의 차이

\n

동시성 환경에서는 어떤지 알아볼까요?\n여러 프로세스를 동시에 실행하는 멀티 프로세스와 한 프로세스에서 여러 쓰레드를 동시에 실행하는 멀티 쓰레드가 있습니다.

\n

\n \n \n img 3\n \n

\n

여기서 가장 큰 차이점은 프로세스끼리는 기본적으로 공유하지 않지만, 쓰레드끼리는 같은 프로세스 내의 자원을 공유한다는 점입니다.

\n

즉, 멀티 프로세스는 여러 프로세스를 동시에 실행해 각각의 독립적인 프로세스 간 자원을 공유하지 않기 때문에 프로세스 간 통신 (IPC) 방식을 써야 합니다.\n또한, 메모리에 동일한 내용들이 중복해서 존재하기 때문에 메모리에도 부담이 될 수 있습니다.\n그러나 한편으로는 자원을 공유하지 않는 덕분에 하나의 프로세스에 문제가 생겨도 다른 프로세스들에는 문제가 발생하지 않는다는 장점이 있기도 합니다.

\n

반면, 멀티 쓰레드는 실행에 필요한 최소한의 정보(PC, 레지스터, 스택)만을 유지한 채 프로세스 자원을 공유하며 실행되기에\n커널의 개입 없이 쓰레드간 통신을 할 수 있고, 메모리에도 부담이 덜합니다.\n또한 fork로 인한 생성이 공유하는 부분을 제외한 부분만 복사하면 되기 때문에 프로세스보다 빠릅니다.(쓰레드가 접근하는 공유 데이터에 대해 동기화 작업을 수행해야 합니다)\n
\n하지만, 하나의 쓰레드에 문제가 생기면 같은 프로세스 내의 다른 쓰레드들에도 문제가 발생할 수 있다는 단점이 있습니다.

","frontmatter":{"title":"4. 쓰레드 ","date":"September 08, 2025","update":"September 08, 2025","tags":["운영체제"],"series":"운영체제"},"fields":{"slug":"/hs4/","readingTime":{"minutes":7.295}}},"seriesList":{"edges":[{"node":{"id":"8b51f460-43e0-561e-ab49-84bc59be430a","fields":{"slug":"/hs1/"},"frontmatter":{"title":"1. 운영체제의 개념과 구조"}}},{"node":{"id":"a19bc92c-cb8c-5cf6-a09a-30349b5f21dc","fields":{"slug":"/hs2/"},"frontmatter":{"title":"2. 커널의 작동 방식"}}},{"node":{"id":"3ad80296-57ed-53b0-ada7-f06096fe6849","fields":{"slug":"/hs4/"},"frontmatter":{"title":"4. 쓰레드 "}}},{"node":{"id":"46425f46-05a1-5269-ad13-c4687acafbf1","fields":{"slug":"/hs3/"},"frontmatter":{"title":"3. 프로세스"}}},{"node":{"id":"cb8ba341-aac3-5491-9121-5bee87c5172c","fields":{"slug":"/hs5/"},"frontmatter":{"title":"5. CPU 스케줄링"}}}]},"previous":{"fields":{"slug":"/jc4/"},"frontmatter":{"title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}},"next":{"fields":{"slug":"/hs3/"},"frontmatter":{"title":"3. 프로세스"}}},"pageContext":{"id":"3ad80296-57ed-53b0-ada7-f06096fe6849","series":"운영체제","previousPostId":"c96ac712-ee44-5bd2-8318-3d771e986911","nextPostId":"46425f46-05a1-5269-ad13-c4687acafbf1"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/hs5/page-data.json b/public/page-data/hs5/page-data.json new file mode 100755 index 0000000..2cb2287 --- /dev/null +++ b/public/page-data/hs5/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/hs5/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"cb8ba341-aac3-5491-9121-5bee87c5172c","excerpt":"기아 상태와 CPU 스케줄링 프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다.\n그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나,\n너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고\n이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다.\n이를 컴퓨팅에서…","html":"

기아 상태와 CPU 스케줄링

\n

프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다.\n그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나,\n너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고\n이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다.\n이를 컴퓨팅에서는 기아 현상이라고 하는데,\n이로 인해 프로세스들에게 CPU 자원 할당을 배분해주는 CPU 스케줄링이 개발되었고,\n운영체제에 반드시 필요로 하게 되었습니다.

\n
\n

기아 현상에 대한 대표적인 해결 방법은 에이징 기법을 이용하는 것입니다.\n오랫동안 대기한 프로세스의 우선순위에 대해 가중치를 주어,\n처음에 우선순위가 낮아도 언젠가는 우선순위가 높아져 기아 현상을 막을 수 있습니다.\n이와 같이 CPU 스케줄링에서는 이러한 문제 해결을 위한 다양한 방식들이 있습니다.

\n
\n

프로세스 우선 순위

\n

스케줄링을 지정하는 것은 순서를 지정하는 것과 같습니다.\n그런데 어떻게 프로세스들 간의 순위를 공정하게 지원하고 있을까요?

\n

순차방식

\n

가장 단순하게 생각해보면 요청이 들어온 순서대로 할당하는 방식입니다.\n그러나 이 방식은 빨리 처리해야 하는 프로세스가 있을 수 있는 상황에서 대응하지 못한다는 것입니다.

\n

예시로 CPU를 많이 사용하는 프로세스가 I/O 작업을 하는 프로세스 보다 늦게 들어올 경우,\n순서상으로는 뒤에 있어야 하지만, CPU 자원을 할당한다는 측면에서 볼 떄에는 앞 순위로 두는 것이 효울적일 것입니다.

\n

우선순위 지정 방식

\n

위 순차적인 방식이 아닌, 별도의 우선순위를 지정하는 방식도 있습니다.\n이때, 우선순위에 대한 정보는 PCB에 저장이 됩니다.

\n

이로 인해 프로세스의 중요도에 맞게 프로세스가 CPU를 이용할 수 있도록 운영체제가 부여하는 것이 우선순위이며,\n운영체제는 PCB를 기반으로 어떤 프로세스가 CPU를 얼마나 사용하게 될 것인지 등을 결정합니다.

\n

프로세스 우선순위는 간단한 명령어나 프로그램 등으로 확인이 가능한데,\n일부 우선순위의 경우에는 사용자가 직접 설정 가능한 것도 있습니다.

\n

스케줄링 큐

\n

프로세스가 여러 개일 경우, 다음 CPU 자원을 이용할 프로세스를 선택하기 위해 매번 모든 프로세스들의 PCB를 다 뒤져보는 것은 매우 비효율적일 것입니다.\n또한, CPU 말고도, 메모리, 입출력 장치를 사용하고자 하는 경우에도 비슷한 상황을 겪을 것입니다.

\n

때문에 운영체제는 어떤 자원을 이용하고자 할 때 대기 하는 스케줄링 큐를 활용하고 있습니다.

\n

이때, 큐라고 해서 반드시 선입선출(FIFO)에 국한되지 않습니다.

\n

선점형 스케줄링과 비선점형 스케줄링

\n

스케줄링 방식에는 선점형 스케줄링과 비선점형 스케줄링 방식이 있습니다.

\n

선점형 스케줄링

\n

선점형 스케줄링은 현재 CPU를 사용 중인 프로세스로부터 CPU 자원을 뺴앗아 요청한 프로세스에 할당하는 방법입니다.\n어느 한 프로세스의 자원 독점을 막고 프로세스에 골고루 자원을 배분할 수 있으나, 그 만큼 컨텍스트 스위칭 과정에서 오버헤드가 발생할 수 있습니다.

\n

비선점형 스케줄링

\n

비선점형 스케줄링은 현재 CPU를 사용 중인 프로세스의 작업이 끝날 때까지 기다리는 방식입니다.

\n

선점형 스케줄링과 반대되는 개념으로, 컨텍스트 스위칭에서 발생하는 오버헤드가 적지만, 한편으로는 모든 프로세스가 골고루 자원을 이용하기 어렵습니다.

\n

CPU 스케줄링 알고리즘

\n

선점형 스케줄링과 비선점형 스케줄링을 기반으로 다양한 CPU 스케줄링 알고리즘이 있습니다.

\n

선입 선처리 스케줄링

\n

FCFS(First Come First Served) 스케줄링으로, 준비 큐에 삽입된 순서대로 처리하는 비선점 스케줄링 방식입니다.\nCPU를 먼저 요청한 프로세스부터 CPU를 할당합니다.\n이로 인해 프로세스들이 기다리는 시간이 매우 길어질 수 있는 부작용이 있으며,\n이를 convoy effect, 호위 효과라고 합니다.

\n

최단 작업 우선 스케줄링

\n

SJF(Shortest Job First) 스케줄링으로,\n사용 시간이 긴 프로세스를 나중에 실행하고,\n시간이 짧은 프로세스를 먼저 실행함으로써 평균 대기 시간을 줄일 수 있습니다.\n이 알고리즘은 기본적으로는 비선점형 스케줄링 방식에 속하지만,\n선점형과 비선점형 스케줄링 방식으로 모두 가능합니다.

\n

라운드 로빈 스케줄링

\n

RR(Round Robin) 스케줄링으로,\n선입 선처리 스케줄링과 시분할 시스템의 타임 슬라이스(time slice) 개념이 결합된 방식입니디.\n정해진 타임 슬라이스만큼의 시간 동안 돌아가며 CPU를 이용하게 하는 선점형 스케줄링입니다.

\n

최소 잔여 시간 우선 스케줄링

\n

SRT(Shortest Remaining Time) 스케줄링으로,\n최단 작업 우선 스케줄링과 라운드 로빈 스케줄링이 결합된 형태입니다.\n정해진 시간만큼 CPU를 이용하되,\n다음으로 CPU를 사용할 프로세스로는 남은 작업 시간이 가장 적은 프로세스를 선택합니다.

\n

우선순위 스케줄링

\n

프로세스들에 우선순위를 부여하고, 우선순위가 높은 프로세스부터 실행하는 방식입니다.\n우선순위가 같은 프로세스들은 선입 선처리 스케줄링으로 돌아가고,\n최단 작업 우선 스케줄링이나 최소 잔여 시간 스케줄링은 포괄적인 의미에서 우선순위 스케줄링에 속한다고 할 수 있습니다.

\n

다단계 큐 스케줄링

\n

멀티 레벨 큐 스케줄링으로도 불리는데, 우선순위 스케줄링의 발전된 형태입니다.\n우선순위 별로 준비 큐를 여러 개 사용하고, 우선순위가 높은 큐에 있는 프로세스를 먼저 실행합니다.\n우선순위가 높은 큐가 비어 있다면, 그 다음 우선순위 큐에 있는 프로세스를 처리합니다.\n이러한 방식은 프로세스 유형별로 우선순위를 구별하게 하여 관리가 쉬워집니다.\n큐 별로 타임 슬라이스를 여러 개 지정할 수도 있고, 큐마다 다른 스케줄링 알고리즘을 사용할 수도 있습니다.\n기본적으로 큐 간 이동이 불가능하기 때문에, 우선순위가 낮은 프로세스는 계속해서 우선순위가 낮을 수 밖에 없고,\n그로 인해 기아 현상을 겪을 수도 있습니다.

\n

다단계 피드백 큐 스케줄링

\n

멀티 레벨 피드백 큐 스케줄링으로도 불리는 이 방식은 다단계 큐 스케줄링의 발전된 형태로,\n큐 간 이동이 가능합니다.\n새로 준비 상태로 된 프로세스가 있으면 가장 우선순위가 높은 큐에 삽입합니다.\n일정 시간 즉, 타임 슬라이스 만큼 CPU를 사용할 수 있는데,\n만약 작업이 끝나지 않았다면,\n그때 우선순위가 다음으로 높은 곳에 삽입을 합니다.\n작업을 많이 있는 프로세스일수록 우선순위가 점점 낮아지게 되고,\n따라서 CPU 집중 프로세스는 상대적으로 우선순위가 낮아지고, 입출력 집중 프로세스는 높아지게 될 겁니다.\n일정 시간 이상 낮은 우선순위에서 기다리고 있던 프로세스가 있었다면 이 프로세스의 우선순위를 점차 높임으로써 기아 현상을 방지할 수 있습니다.\n다단계 피드백 큐 스케줄링은 CPU 사용 시간이 길면 우선순위가 점점 낮아지고, 동시에 어떤 프로세스가 낮은 우선순위 큐에서 너무 오래 기다리면 우선순위를 높일 수도 있습니다.\n다단계 피드백 큐 스케줄링은 복잡하지만, CPU 스케줄링의 가장 일반적인 형태로 알려져 있습니다.

","frontmatter":{"title":"5. CPU 스케줄링","date":"September 12, 2025","update":"September 12, 2025","tags":["운영체제"],"series":"운영체제"},"fields":{"slug":"/hs5/","readingTime":{"minutes":12.06}}},"seriesList":{"edges":[{"node":{"id":"8b51f460-43e0-561e-ab49-84bc59be430a","fields":{"slug":"/hs1/"},"frontmatter":{"title":"1. 운영체제의 개념과 구조"}}},{"node":{"id":"a19bc92c-cb8c-5cf6-a09a-30349b5f21dc","fields":{"slug":"/hs2/"},"frontmatter":{"title":"2. 커널의 작동 방식"}}},{"node":{"id":"3ad80296-57ed-53b0-ada7-f06096fe6849","fields":{"slug":"/hs4/"},"frontmatter":{"title":"4. 쓰레드 "}}},{"node":{"id":"46425f46-05a1-5269-ad13-c4687acafbf1","fields":{"slug":"/hs3/"},"frontmatter":{"title":"3. 프로세스"}}},{"node":{"id":"cb8ba341-aac3-5491-9121-5bee87c5172c","fields":{"slug":"/hs5/"},"frontmatter":{"title":"5. CPU 스케줄링"}}}]},"previous":{"fields":{"slug":"/jc8/"},"frontmatter":{"title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}},"next":{"fields":{"slug":"/jc9/"},"frontmatter":{"title":"쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},"pageContext":{"id":"cb8ba341-aac3-5491-9121-5bee87c5172c","series":"운영체제","previousPostId":"f49c1834-3399-5504-9929-1abc15d55888","nextPostId":"6fb64598-2fd1-50e9-bfca-d7513b95df85"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/index/page-data.json b/public/page-data/index/page-data.json index 78b6da2..9c56c00 100644 --- a/public/page-data/index/page-data.json +++ b/public/page-data/index/page-data.json @@ -1 +1 @@ -{"componentChunkName":"component---src-pages-index-jsx","path":"/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"allMarkdownRemark":{"group":[{"fieldValue":"운영체제","totalCount":11}],"nodes":[{"excerpt":"동시성 이슈란? img.png 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면…","fields":{"slug":"/11/"},"frontmatter":{"date":"September 14, 2025","update":"Sep 14, 2025","title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","tags":["운영체제"]}},{"excerpt":"img.png 멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술이다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것이다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세…","fields":{"slug":"/10/"},"frontmatter":{"date":"September 13, 2025","update":"Sep 13, 2025","title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","tags":["운영체제"]}},{"excerpt":"스레드란? img.png 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이…","fields":{"slug":"/9/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB","tags":["운영체제"]}},{"excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","fields":{"slug":"/8/"},"frontmatter":{"date":"September 11, 2025","update":"Sep 11, 2025","title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","tags":["운영체제"]}},{"excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. ![img.png](실행중인 프로세스.png) 백그라운드…","fields":{"slug":"/7/"},"frontmatter":{"date":"September 10, 2025","update":"Sep 10, 2025","title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","tags":["운영체제"]}},{"excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","fields":{"slug":"/6/"},"frontmatter":{"date":"September 09, 2025","update":"Sep 09, 2025","title":"6. 동기식/비동기식 I/O의 차이와 활용 사례","tags":["운영체제"]}},{"excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","fields":{"slug":"/5/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리","tags":["운영체제"]}},{"excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. img.png 멀티 프로그래밍 img.png 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하…","fields":{"slug":"/4/"},"frontmatter":{"date":"September 07, 2025","update":"Sep 07, 2025","title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","tags":["운영체제"]}},{"excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. img.png 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비…","fields":{"slug":"/3/"},"frontmatter":{"date":"September 06, 2025","update":"Sep 06, 2025","title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리","tags":["운영체제"]}},{"excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","fields":{"slug":"/2/"},"frontmatter":{"date":"September 05, 2025","update":"Sep 05, 2025","title":"2. CPU 스케줄링, 시스템 자원 관리","tags":["운영체제"]}},{"excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","fields":{"slug":"/1/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"1. 운영체제의 역할과 커널의 기능","tags":["운영체제"]}}]}},"pageContext":{}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file +{"componentChunkName":"component---src-pages-index-jsx","path":"/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"allMarkdownRemark":{"group":[{"fieldValue":"운영체제","totalCount":28}],"nodes":[{"excerpt":"서론 지금까지 가상 메모리를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다.\n이러한 행위는 한정된 메모리를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다. 그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다. 불필요한 페이지를 선별 후 스왑 아웃 한다. 프로세스에게 적절한 프레임을 할당한다…","fields":{"slug":"/jc23/"},"frontmatter":{"date":"September 26, 2025","update":"Sep 26, 2025","title":"요구페이징을 잘 수행하기 위해서 필요한 것들","tags":["운영체제"]}},{"excerpt":"연속 할당의 문제점 연속적 할당의 대표적인 문제점은 외부 단편화가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해\n필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다. 이러한 문제를 해결하기 위해서는 불연속 할당 방식 중 대표적인 페이징기법을 사용할 수 있습니다. 페이징이란? 페이징 기법은 프로세스를 일정한 단위로 자릅니다. …","fields":{"slug":"/jc22/"},"frontmatter":{"date":"September 25, 2025","update":"Sep 25, 2025","title":"페이징","tags":["운영체제"]}},{"excerpt":"연속 메모리 할당 연속 메모리 할당이란 메모리에 프로세스가 그림처럼 연속적으로 배치되는 상황을 가정합니다. 프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다. 이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 스와핑과 관련이 있습니다. 스와핑이란? 메모리는 실행시킬 프로세스를 적재하게 됩니다. 하…","fields":{"slug":"/jc21/"},"frontmatter":{"date":"September 24, 2025","update":"Sep 24, 2025","title":"메모리 배치기법 그리고 단편화에 대해","tags":["운영체제"]}},{"excerpt":"물리주소와 논리주소 메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다.\n이 저장된 메모리의 데이터를 CPU 혹은 실행중인 프로그램이 읽어 실행하게 됩니다. 해당 그림은 두가지 관점으로 주소를 나누고 사용하는 방식을 그림으로 나타낸 것입니다. 왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요? 이유는 메모리에 저장되어 있는 정보는 변…","fields":{"slug":"/jc20/"},"frontmatter":{"date":"September 23, 2025","update":"Sep 23, 2025","title":"물리주소, 논리주소 그리고 메모리 분할 방식","tags":["운영체제"]}},{"excerpt":"교착상태란?(Dead Lock) 교착상태란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다. 교착상태를 설명하는 대표적인 예시로 식사하는 철학자 문제라는게 있습니다. 식사하는 철학자 식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습…","fields":{"slug":"/jc19/"},"frontmatter":{"date":"September 22, 2025","update":"Sep 22, 2025","title":"교착상태와 해결 방법","tags":["운영체제"]}},{"excerpt":"상호배제(Mutual Exclusion) 상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다. 일상생활에서 비유하면, 화장실 사용과 같습니다.\n한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다.\n컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 …","fields":{"slug":"/jc18/"},"frontmatter":{"date":"September 21, 2025","update":"Sep 21, 2025","title":"상호배제와 동기화 기법","tags":["운영체제"]}},{"excerpt":"공유자원 동시에 실행되는 프로세스에서 공통으로 사용하는 자원을 우리는 공유자원이라고 부릅니다. 임계구역(Critical Section) 공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 임계 구역이라고 부릅니다. 두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한…","fields":{"slug":"/jc17/"},"frontmatter":{"date":"September 20, 2025","update":"Sep 20, 2025","title":"임계구역과 경쟁상태","tags":["운영체제"]}},{"excerpt":"병행성(Concurrency) 병행성은 다른 말로 동시성이라고 부르는 용어입니다.\n이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 컨텍스트 스위칭을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다.\n이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실…","fields":{"slug":"/jc16/"},"frontmatter":{"date":"September 19, 2025","update":"Sep 19, 2025","title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성","tags":["운영체제"]}},{"excerpt":"다단계 큐 스케쥴링(Multilevel queue scheduling) 멀티 레벨 스케줄링은 우선순위 스케줄링의 발전된 형태입니다.\n아래 그림을 통해 설명 하면, 이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데,\n멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다. 가장 높은 우선순위에 있는 큐들을 처리하고,…","fields":{"slug":"/jc15/"},"frontmatter":{"date":"September 18, 2025","update":"Sep 18, 2025","title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링","tags":["운영체제"]}},{"excerpt":"스케줄링 알고리즘 개요 스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다. 비선점 스케줄링 선입 선처리 스케줄링 (FCFS) 최단 작업 우선 스케줄링 (SJF) 선점 스케줄링 라운드 로빈 스케줄링 최소 잔여 시간 우성 스케줄링 (SRT) 우선순위 스케줄링 비 선점 스케줄링 선입 선처리 스케줄(FCFS) FCFS는 준비 큐에 들…","fields":{"slug":"/jc14/"},"frontmatter":{"date":"September 17, 2025","update":"Sep 17, 2025","title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)","tags":["운영체제"]}},{"excerpt":"선점형? 비선점형? 개요 CPU 스케줄링은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다. 여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다. 선점형 스케줄링 선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다. …","fields":{"slug":"/jc13/"},"frontmatter":{"date":"September 16, 2025","update":"Sep 16, 2025","title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법","tags":["운영체제"]}},{"excerpt":"CPU 할당? 지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용\n하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등\nCPU사용에 …","fields":{"slug":"/jc12/"},"frontmatter":{"date":"September 15, 2025","update":"Sep 15, 2025","title":"CPU 스케줄링의 목적과 스케줄러의 종류","tags":["운영체제"]}},{"excerpt":"동시성 이슈란? 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면 11가 됩니…","fields":{"slug":"/jc11/"},"frontmatter":{"date":"September 14, 2025","update":"Sep 14, 2025","title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","tags":["운영체제"]}},{"excerpt":"멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술입니다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것입니다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부…","fields":{"slug":"/jc10/"},"frontmatter":{"date":"September 13, 2025","update":"Sep 13, 2025","title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","tags":["운영체제"]}},{"excerpt":"기아 상태와 CPU 스케줄링 프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다.\n그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나,\n너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고\n이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다.\n이를 컴퓨팅에서…","fields":{"slug":"/hs5/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"5. CPU 스케줄링","tags":["운영체제"]}},{"excerpt":"스레드란? 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이 여러 기능을…","fields":{"slug":"/jc9/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"쓰레드의 개념, 메모리 공유 구조 및 TCB","tags":["운영체제"]}},{"excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","fields":{"slug":"/jc8/"},"frontmatter":{"date":"September 11, 2025","update":"Sep 11, 2025","title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","tags":["운영체제"]}},{"excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. 백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는…","fields":{"slug":"/jc7/"},"frontmatter":{"date":"September 10, 2025","update":"Sep 10, 2025","title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","tags":["운영체제"]}},{"excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","fields":{"slug":"/jc6/"},"frontmatter":{"date":"September 09, 2025","update":"Sep 09, 2025","title":"동기식/비동기식 I/O의 차이와 활용 사례","tags":["운영체제"]}},{"excerpt":"쓰레드란? 쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다. 그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다.\n이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다. 사용자 수준 쓰레드와 커널 수준 쓰레드의 차이 사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다.\n쓰레드와 관련된 모든 행위를 사용자 영…","fields":{"slug":"/hs4/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"4. 쓰레드 ","tags":["운영체제"]}},{"excerpt":"프로세스란? 컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 인스턴스를 의미합니다.\n여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다. 프로세스의 메모리 공간 프로세스는 다음 4개의 메모리 영역으로 구성되고 가상 메모리 공간에 독립적으로 형성됩니다. 코드 영역(Cod…","fields":{"slug":"/hs3/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"3. 프로세스","tags":["운영체제"]}},{"excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","fields":{"slug":"/jc5/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"인터럽트와 DMA를 통한 효율적 입출력 처리","tags":["운영체제"]}},{"excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. 멀티 프로그래밍 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다.…","fields":{"slug":"/jc4/"},"frontmatter":{"date":"September 07, 2025","update":"Sep 07, 2025","title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","tags":["운영체제"]}},{"excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비스를 제공받을…","fields":{"slug":"/jc3/"},"frontmatter":{"date":"September 06, 2025","update":"Sep 06, 2025","title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리","tags":["운영체제"]}},{"excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","fields":{"slug":"/jc2/"},"frontmatter":{"date":"September 05, 2025","update":"Sep 05, 2025","title":"CPU 스케줄링, 시스템 자원 관리","tags":["운영체제"]}},{"excerpt":"앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다.\n이제 커널이 어떻게 작동하는지 제대로 알아보자. 먼저 인터럽트(Interrupt)에 대해 알아야 한다. 컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데\n이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다.\n이중 하나가 인터럽트이다. \n인터럽트는 중단시키다라…","fields":{"slug":"/hs2/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"2. 커널의 작동 방식","tags":["운영체제"]}},{"excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","fields":{"slug":"/jc1/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"운영체제의 역할과 커널의 기능","tags":["운영체제"]}},{"excerpt":"운영체제(OS, Operating System) 운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다. 운영체제가 없으면 어떻게 될까? 꼭 필요할까? A computer is a machine that can be programmed to automatically carry ou…","fields":{"slug":"/hs1/"},"frontmatter":{"date":"September 03, 2025","update":"Sep 03, 2025","title":"1. 운영체제의 개념과 구조","tags":["운영체제"]}}]}},"pageContext":{}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc1/page-data.json b/public/page-data/jc1/page-data.json new file mode 100755 index 0000000..6b1dc16 --- /dev/null +++ b/public/page-data/jc1/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc1/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"a856e34f-f9a9-5164-8fb5-befe1aa43bcd","excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","html":"

운영체제란 무엇일까?

\n
\n

운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원관리하고,\n
프로세스를 관리하는 등 여러가지 일을 수행합니다.

\n

이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다.

\n

운영체제의 역할

\n
\n

하드웨어 관리

\n
\n

운영체제는 CPU, 메모리, 입출력 장치 등 컴퓨터 하드웨어 자원을 관리합니다.\n
여기서 말하는 관리란 자원의 충돌을 방지하고 사용자가 하드웨어를 효율적으로\n사용하도록 처리하는것을 의미하게 됩니다.

\n
\n
\n
\n

프로세스 관리

\n
\n

프로세스의 생성과 종료 그리고 CPU 스케줄링을 통해 프로세스의 실행 시간을 관리합니다.\n
멀티 태스킹환경에서 프로세스 전환을 관리합니다.

\n
\n
\n
\n

메모리 관리

\n
\n

각 애플리케이션에 충분한 메모리 공간을 할당하는 기능을 합니다.\n
또한 가상 메모리를 통해 실제 메모리보다 큰 주소 공간을 제공합니다.

\n
\n

커널이란 무엇일까?

\n
\n

커널이란 운영체제의 핵심 기능을 담당하며, 커널은 하드웨어와 소프트웨어 애플리케이션 간 통신을 관리합니다. 커널의 대표적인 기능으로는\n
프로세스 관리, 메모리 관리, 파일 시스템, 입 출력 관리의 역할을 수행하게 됩니다.

\n

위 설명 처럼 운영체제의 핵심기능을 커널이 많은 부분을 담당하기 때문에 이전에 설명한 운영체제의 기능이 커널의 기능이라고 생각하면 됩니다.

\n

커널이 자원을 관리하는 이유

\n
\n
\n

커널은 어떻게 충돌 없이 자원을 관리할까요?

\n
\n

이 질문에 대한 대답은 자원을 관리하는 지점을 커널을 통한 단일 진입점으로 만들게 되면서 해결 하게 됩니다.\n

\n
\n

왜 자원을 커널을 통해서만 관리하게 설게 했을까요?

\n
\n

커널이 자원을 혼자 관리해야 하는 이유를 예시를 들어서 설명하겠습니다.

\n

유치원 수업시간에 하나의 바구니에 테이프, 연필, 지우개와 같은 문구용품을 담아두고 선생님이 학생들에게 자율적으로 사용해도 된다고 하게 된다면 어떤일이 벌어질까요?

\n

처음에는 아이들이 각자 필요한 문구 용품을 사용하겠지만 얼마 가지 않아서 연필을 찾는 학생,\n
테이프를 가지고 누가먼저 쓸지 싸우는 학생,\n
혹은 지우개를 망가뜨린 학생등 많은 사고가 있을 것입니다.

\n

이러한 문제가 벌어지는 이유는 공용 문구를 사용할때 통제권이 모두에게 있기 떄문입니다. 그렇다면 이를 해결하기 위해서\n모두에게 있는 통제권을 하나로 합쳐서 해결하면 되는 문제이고 이것이 자원을 사용하기 위해 커널의 관리를 받아야 하는 이유입니다.

","frontmatter":{"title":"운영체제의 역할과 커널의 기능","date":"September 04, 2025","update":"September 04, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/jc1/","readingTime":{"minutes":4.585}}},"seriesList":{"edges":[{"node":{"id":"a856e34f-f9a9-5164-8fb5-befe1aa43bcd","fields":{"slug":"/jc1/"},"frontmatter":{"title":"운영체제의 역할과 커널의 기능"}}},{"node":{"id":"206f7f4e-13af-5568-b55d-4f56ccf6f27d","fields":{"slug":"/jc2/"},"frontmatter":{"title":"CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"3b1392c5-94e5-5f2b-889c-04d05775956f","fields":{"slug":"/jc3/"},"frontmatter":{"title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"c96ac712-ee44-5bd2-8318-3d771e986911","fields":{"slug":"/jc4/"},"frontmatter":{"title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"6fead90c-3201-5834-b766-1a6625757a89","fields":{"slug":"/jc5/"},"frontmatter":{"title":"인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"1460ba25-d467-50f1-873c-d36498b197b7","fields":{"slug":"/jc6/"},"frontmatter":{"title":"동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":{"fields":{"slug":"/hs2/"},"frontmatter":{"title":"2. 커널의 작동 방식"}},"next":{"fields":{"slug":"/jc2/"},"frontmatter":{"title":"CPU 스케줄링, 시스템 자원 관리"}}},"pageContext":{"id":"a856e34f-f9a9-5164-8fb5-befe1aa43bcd","series":"운영체제 기본 개념","previousPostId":"a19bc92c-cb8c-5cf6-a09a-30349b5f21dc","nextPostId":"206f7f4e-13af-5568-b55d-4f56ccf6f27d"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc10/page-data.json b/public/page-data/jc10/page-data.json new file mode 100755 index 0000000..941ce3c --- /dev/null +++ b/public/page-data/jc10/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc10/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"fc9488aa-d0c3-5870-9e9c-afaef4672d71","excerpt":"멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술입니다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것입니다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부…","html":"

\n \n \n \n \n \n
img.png
\n

\n

멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술입니다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것입니다.

\n
\n
\n

어떻게 멀티 프로세스를 생성할까?

\n

멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부모 프로세스가\n여러개의 자식 프로세스를 생성합니다.

\n

부모 프로세스는 자식 프로세스의 PID를 알고있으며 자식또한 PID와 PPID를 알고있어\n서로 통신이 가능합니다.

\n

이런 성질은 각각 독립적이지만 통신이 가능하게 만들었고 멀티 프로세스의 대표적인 예가\n브라우저의 탭이라고 할 수 있습니다.

\n

브라우저 탭은 문제가 발생해서 닫아야 하는 상황이여도 다른 탭까지 닫히지 않고 개별적으로\n운용을 할 수 있는걸 기억해보면 독립적이란 말을 더 잘 이해할 수 있을것이다.

\n
\n
\n

멀티 프로세스의 장점

\n
\n
    \n
  1. 안정성
  2. \n
\n

멀티 프로세스의 안정성은 각각의 프로세스가 독립적이기 떄문에 가능합니다.\n대표적인 예로 좀전에 설명을 했던 특정 브라우저 탭이 문제가 발생하여 닫아야 하는 상황에서\n같은 브라우저의 다른 탭까지 닫히지는 않습니다.\n이런것이 독립적인 성격에 의한 안정성이라고 할 수 있습니다.

\n
\n
\n

멀티 프로세스의 단점

\n
\n
    \n
  1. 문맥교환 (Context Switching) Overhead
  2. \n
\n

멀티 태스킹을 이루는 기술인 문맥 교환 과정에서 성능 저하가 발생할 수 있습니다.\n프로세스를 컨텍스트 스위칭 하면, CPU는 다음 프로세스의 정보를 불러오기 위해\n메모리를 검색하고, CPU 캐시 메모리를 초기화하며, 프로세스 상태를 저장하고,\n불러올 데이터를 준비해야 하기 떄문에, 빈번한 문맥교환이 발생하고 이 비용은 곧 오버헤드로 발생할 수 있습니다.

\n
\n
\n
    \n
  1. 자원 공유 비효율성
  2. \n
\n

프로세스는 독립적인 메모리를 가지고, 멀티 프로세스는 독립적인 메모리 공간의 합일 것입니다.\n그렇기 때문에 메모리 비효율성을 초래합니다.

\n
\n
\n

멀티 스레드

\n
\n

\n \n \n \n \n \n
img.png
\n

\n
\n

이전에 보았던 것처럼 스레드는 하나의 프로세스 내에 있는 실행 흐름입니다.\n멀티 스레드는 하나의 프로세스 안에 여러개의 실행흐름을 가지는 것입니다.\n멀티 스레드 또한 멀티 프로세스 처럼 여러개의 작업을 동시 실행 할 수 있습니다.

\n

이전에 보았던 것처럼 멀티 프로세스는 브라우저의 여러개의 탭을 통해 예시를 들었습니다.\n하지만, 멀티 스레드는 같은 브라우저라 할지라도 동일탭에 여러 실행 흐름을 말하게 되고\n예를들어 네트워크 처리 스레드, 검색 스레드 와 같이 동일한 프로세스 내 기능들을 말하게 됩니다.

\n
\n
\n

멀티 스레드의 장점

\n
\n

프로세스보다 스레드가 가벼움

\n

스레드는 프로세스보다 용량이 가볍다. 이유는 데이터, 코드, 힙 영역을\n프로세스와 공유해서 사용하기 때문에 내장된 정보다 프로세스보다 작기 떄문입니다.\n그렇기 때문에 스레드를 제거하는 작업이 프로세스를 제거하는 작업보다 가볍습니다.

\n
\n
\n

자원의 효율성

\n

멀티 스레드는 하나의 프로세스 내에서 스택영역을 제외한 영역을 공유하기 때문에\n프로세스 간 통신을 사용하지 않고도 자원의 공유가 가능하여 자원을 효율적으로 사용할 수 있습니다.

\n
\n
\n

Context Switching 비용 감소

\n

스레드 문맥 교환 또한 오버헤드가 존재하지만, 프로세스 문맥교환과 비교했을 때,\n상대적으로 오버헤드가 적습니다.

\n

이유는 프로세스 컨텍스트 스위칭 비용은 스위칭할 때마다 CPU 캐시에 있는 내용을 모두 초기화하고,\n새로운 프로세스 정보를 CPU 캐시에 적재해야 하기 떄문입니다.\n하지만, 스레드 문맥교환은 스레드 개별적인 정보만 교체하면 되기 떄문에 비용이 상대적으로 낮습니다.

\n
\n
\n

멀티 스레드의 단점

\n

멀티 프로세스는 개별적인 작업으로 인해 독집적이고, 각자의 문제를 전파하지 않는다고 합니다.

\n

하지만, 멀티 스레드는 하나의 스레드가 문제가 발생하면 다른 스레드들고 영향을 받아 전체가 종료가 될 수 있습니다.

\n
\n
\n

데드락

\n

데드락이란 하나의 자원을 사용하기위해 여러 곳에서 접근했고, 그상황에서 교착상태가 일어났을때\n여러대의 스레드가 서로 대기하면서 무한정 기다리는 현상을 데드락이라고 합니다.

\n

예를들어, 스레드 1 은 자원 A을 점유하고 있는 상태에서 자원 B가 필요한 상황입니다.\n그리고 스레드 2 는 자원 B를 점유하고 있는 상태에서 자원 A이 필요한 상황입니다.\n하지만 스레드 1은 자원 B가 필요한 상황에서 자원 A을 빌려줄 수 있는 상황이 아니고,\n스레드 2또한 자원 A이 필요한 상태에서 자원 B를 빌려줄 수 없는 상황인 것입니다.\n이처럼 다수의 쓰레드가 같은 lock을 동시에,\n다른 명령에 의해 획득하려 할 때 서로 절대 불가능한 일을 계속적으로 기다리는 상황을 이야기 합니다.

","frontmatter":{"title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","date":"September 13, 2025","update":"September 13, 2025","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"},"fields":{"slug":"/jc10/","readingTime":{"minutes":8.32}}},"seriesList":{"edges":[{"node":{"id":"0f3ed929-e023-5c69-9609-82bade016409","fields":{"slug":"/jc7/"},"frontmatter":{"title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},{"node":{"id":"f49c1834-3399-5504-9929-1abc15d55888","fields":{"slug":"/jc8/"},"frontmatter":{"title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},{"node":{"id":"6fb64598-2fd1-50e9-bfca-d7513b95df85","fields":{"slug":"/jc9/"},"frontmatter":{"title":"쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},{"node":{"id":"fc9488aa-d0c3-5870-9e9c-afaef4672d71","fields":{"slug":"/jc10/"},"frontmatter":{"title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},{"node":{"id":"5a1e74a6-7abb-5097-97ee-1af020ef9a81","fields":{"slug":"/jc11/"},"frontmatter":{"title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}}]},"previous":{"fields":{"slug":"/jc9/"},"frontmatter":{"title":"쓰레드의 개념, 메모리 공유 구조 및 TCB"}},"next":{"fields":{"slug":"/jc11/"},"frontmatter":{"title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}},"pageContext":{"id":"fc9488aa-d0c3-5870-9e9c-afaef4672d71","series":"프로세스와 쓰레드에 대해서 알아보기","previousPostId":"6fb64598-2fd1-50e9-bfca-d7513b95df85","nextPostId":"5a1e74a6-7abb-5097-97ee-1af020ef9a81"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc11/page-data.json b/public/page-data/jc11/page-data.json new file mode 100755 index 0000000..69dd747 --- /dev/null +++ b/public/page-data/jc11/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc11/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"5a1e74a6-7abb-5097-97ee-1af020ef9a81","excerpt":"동시성 이슈란? 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면 11가 됩니…","html":"

동시성 이슈란?

\n
\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다.

\n

예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면 11가 됩니다. 하지만 스레드 a와 b는 좋아요 카운트에 동시에 접근해서 초기값 10을 받은 상태라면\n스레드 b는 늘어난 11라는 숫자대신 10을 기준으로 값을 줄이게 됩니다. 그럼 최종 결과는 10이 아닌 9라는 값으로 나오게 됩니다.

\n

이처럼 멀티 스레드 환경에서는 하나의 자원에 동시에 접근하게 되면 이러한 문제가 발생할 수 있습니다.

\n
\n
\n

스레드 안전

\n
\n

그럼 우리가 추구해야 할 문제는 스레드 안전한 멀티 스레드 프로그래밍을 구현할 수 있어야 한다. 이것을 구현하는\n방법에 대해 이야기 하려고 합니다.

\n
\n
\n

스레드 안전 여부 판단

\n
\n
    \n
  1. 전역 변수나 힙, 파일과 같이 여러 스레드가 동시 접근 가능한 자원을 사용하는가
  2. \n
  3. 핸들과 포인터를 통한 데이터의 간접 접근이 가능한가?
  4. \n
  5. 부수 효과를 가져오는 코드가 있는가?
  6. \n
\n
\n
\n

스레드 안전을 지키기 위한 4가지 방법

\n
\n
    \n
  1. 상호 배제(Mutual Exclusion)
  2. \n
\n
\n
    \n
  • 공유 자원에 하나의 Thread만 접근할 수 있도록 세마포어/ 뮤텍스락을 통제하는 방법입니다.
  • \n
\n
\n
    \n
  1. 원자 연산(Atomic Operation)
  2. \n
\n
\n
    \n
  • 공유 자원에 접근할 때 원자 연산을 이용하거나 원자적으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현하는 방법입니다.
  • \n
  • Atomic\n
      \n
    • 공유 자원 변경에 필요한 연산을 원자적으로 분리한 뒤에 실제로 데이터의 변경이 이루어지는 시점에 Lock을 걸고,
    • \n
    \n데이터를 변경하는 시간 동안 다른 쓰레드의 접근이 불가능하도록 하는 방법입니다.
  • \n
\n
\n
    \n
  1. Thread-Local Storage (스레드 지역 저장소)
  2. \n
\n
\n
    \n
  • 공유 자원의 사용을 최대한 줄이고 각가의 쓰레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는 방법입니다.
  • \n
  • 일반적으로 공유 상태를 피할 수 없을 때 사용하는 방식이며, 전역 변수 사용을 자제하라는 뜻으로 생각하면 됩니다.
  • \n
\n
\n
    \n
  1. Re-entrancy (재진입성)
  2. \n
\n
\n
    \n
  • 쓰레드 호출과 상관 없이 프로그램에 문제가 없도록 작성하는 방법입니다.
  • \n
  • 어떤 함수가 한 스레드에 의해 호출되어 실행 중이라면 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 옳바르게 주어져야 합니다.
  • \n
  • 쓰레드끼리 독립적으로 동작할 수 있도록 코드를 작성하는 것으로 생각하면 됩니다.
  • \n
\n
\n
","frontmatter":{"title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","date":"September 14, 2025","update":"September 14, 2025","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"},"fields":{"slug":"/jc11/","readingTime":{"minutes":4.39}}},"seriesList":{"edges":[{"node":{"id":"0f3ed929-e023-5c69-9609-82bade016409","fields":{"slug":"/jc7/"},"frontmatter":{"title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},{"node":{"id":"f49c1834-3399-5504-9929-1abc15d55888","fields":{"slug":"/jc8/"},"frontmatter":{"title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},{"node":{"id":"6fb64598-2fd1-50e9-bfca-d7513b95df85","fields":{"slug":"/jc9/"},"frontmatter":{"title":"쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},{"node":{"id":"fc9488aa-d0c3-5870-9e9c-afaef4672d71","fields":{"slug":"/jc10/"},"frontmatter":{"title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},{"node":{"id":"5a1e74a6-7abb-5097-97ee-1af020ef9a81","fields":{"slug":"/jc11/"},"frontmatter":{"title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}}]},"previous":{"fields":{"slug":"/jc10/"},"frontmatter":{"title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}},"next":{"fields":{"slug":"/jc12/"},"frontmatter":{"title":"CPU 스케줄링의 목적과 스케줄러의 종류"}}},"pageContext":{"id":"5a1e74a6-7abb-5097-97ee-1af020ef9a81","series":"프로세스와 쓰레드에 대해서 알아보기","previousPostId":"fc9488aa-d0c3-5870-9e9c-afaef4672d71","nextPostId":"59bb0404-6a3f-5c62-a448-24499754bbb4"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc12/page-data.json b/public/page-data/jc12/page-data.json new file mode 100755 index 0000000..89f9ce5 --- /dev/null +++ b/public/page-data/jc12/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc12/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"59bb0404-6a3f-5c62-a448-24499754bbb4","excerpt":"CPU 할당? 지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용\n하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등\nCPU사용에 …","html":"

CPU 할당?

\n
\n

지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용\n하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등\nCPU사용에 여러 변수가 있습니다.

\n

한가지 의문점은, 누가? 어떻게? CPU를 할당하는지 배운적은 없습니다.\n여기서 CPU라는 리소스에 대한 사용을 결정짓는건 운영체제입니다.\n그리고 오늘 글의 주제인 CPU 스케줄링은 운영체제가 CPU라는 자원을 배분하는 행위를 지칭합니다.

\n
\n
\n

CPU 스케줄링 우선순위

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

운영체제는 많은 프로세스에게 공정하게 CPU라는 공용자원을 배분하기 위해 고려해야 하는것이 우선순위 입니다.\n우선순위라는 기준을 매겨야 하는 이유는\n운영체제는 어떤 프로세스는 당장 처리해야 할 중요성을 띄거나, IO작업이 많거나, CPU 사용시간 자체가 길거나처럼 각자의 사정이 있고, 이 사정 가운대 효율적으로 자원을 배분해야 하기 떄문입니다.

\n
\n

'우선순위가 높다'라는 표현은 CPU 사용에 우선권을 가집니다. 즉 먼저 처리되어야 한다 라는 뜻입니다.\n대표적으로 우선순위가 높은 프로세스는 입출력이 많은 프로세스 입니다.\n(입출력 처리가 많은 프로세스가 우선순위가 높은 이유는 아래에서 설명합니다.)

\n

대부분의 프로세스는 I/O 작업과 CPU처리를 번갈아가면서 수행하게 됩니다. 이 말은 프로세스 상태 변화에서 실행, 대기를 번갈아 가면서 사용한다는 뜻입니다.\n그렇지만 모든 프로세스가 동일한 비율로 I/O와 CPU처리를 하는것은 아닙니다. 여기서 CPU작업의 비율이 많다면 CPU 집중 프로세스라고 하게 되며, 반대로 I/O작업의\n비율이 많다면 입출력 집중 프로세스 라고 부르게 됩니다.

\n

CPU집중 프로세스는 실행상태가 많고, 입출력 집중 프로세스는 대기 상태가 많으니 입출력 집중 프로세스를 빠르게 대기 상태로 넘겨주는 것이 CPU사용에 대해서 더 효율적인\n방법일것입니다. 그렇기 떄문에 입출력 처리가 많은 프로세스가 우선순위가 높습니다.

\n

여담으로, CPU를 이용하는 작업을 CPU 버스트, 입출력을 이용하는 작업을 입출력 버스트라고 부르게 됩니다.

\n
\n
\n

이러한 우선순위는 PCB에 기록됩니다. PCB 우선순위 기준으로 먼저 처리할 프로세스를 결정하고 처리하게 됩니다.

\n
\n
\n

스케줄링 큐

\n
\n

\n \n \n \n \n \n
img.png
\n

\n

우선순위는 PCB에 기록되지만, 운영체제가 매 CPU 할당 과정마다 PCB를 확인하고 결정하는건 비효율 적인 방식입니다.\n그렇기 때문에 프로세스는 마치 '줄을 서는것'처럼 대기하게 됩니다. 이것을 스케줄링 큐라고 부르게 됩니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

운영체제는 메모리로 적재되고 싶은 프로세스들을 큐에 삽입하여 줄을 세우고, CPU를 사용하고 싶거나, 특정 입출력장치를 사용하거 싶은 프로세스들을 줄세웁니다.\n이 과정에서 사용할 자원에 따라 다른 큐에서 대기하게 됩니다.

\n

운영체제가 관리하는 큐로는 준비큐대기큐로 이루어 져 있습니다. 준비 큐는 말그대로 CPU를 이용하고 싶은 프로세스들이 대기하게 되고,

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

대기 큐는\n입출력장치를 이용하기 위한 대기 상태에 돌입한 프로세스들이 서는 줄입니다.\n큐에 들어와 있다고 해도 항상 순서대로 작동하는 것은 아니고 우선 순위를 고려합니다.

\n
\n

출처

\n
\n

이미지 출처

","frontmatter":{"title":"CPU 스케줄링의 목적과 스케줄러의 종류","date":"September 15, 2025","update":"September 15, 2025","tags":["운영체제"],"series":"CPU 스케줄링"},"fields":{"slug":"/jc12/","readingTime":{"minutes":5.89}}},"seriesList":{"edges":[{"node":{"id":"59bb0404-6a3f-5c62-a448-24499754bbb4","fields":{"slug":"/jc12/"},"frontmatter":{"title":"CPU 스케줄링의 목적과 스케줄러의 종류"}}},{"node":{"id":"45c9933f-7bb7-5a1f-ae03-f34cd407a222","fields":{"slug":"/jc13/"},"frontmatter":{"title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법"}}},{"node":{"id":"ae9a2b29-4c95-5711-96bb-742626bb7775","fields":{"slug":"/jc14/"},"frontmatter":{"title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)"}}},{"node":{"id":"7b87c866-3440-52b3-9e3c-7a9d1a9357ab","fields":{"slug":"/jc15/"},"frontmatter":{"title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링"}}}]},"previous":{"fields":{"slug":"/jc11/"},"frontmatter":{"title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}},"next":{"fields":{"slug":"/jc13/"},"frontmatter":{"title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법"}}},"pageContext":{"id":"59bb0404-6a3f-5c62-a448-24499754bbb4","series":"CPU 스케줄링","previousPostId":"5a1e74a6-7abb-5097-97ee-1af020ef9a81","nextPostId":"45c9933f-7bb7-5a1f-ae03-f34cd407a222"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc13/page-data.json b/public/page-data/jc13/page-data.json new file mode 100755 index 0000000..ee5fc5a --- /dev/null +++ b/public/page-data/jc13/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc13/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"45c9933f-7bb7-5a1f-ae03-f34cd407a222","excerpt":"선점형? 비선점형? 개요 CPU 스케줄링은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다. 여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다. 선점형 스케줄링 선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다. …","html":"

선점형? 비선점형? 개요

\n
\n

CPU 스케줄링은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다.

\n

여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다.

\n
\n
\n

선점형 스케줄링

\n
\n
\n

선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다.

\n
\n

즉, 어떤 프로세스가 CPU라는 자원을 사용하고 있음에도 운영체제가 CPU를 사용중인 프로세스로부터 자원을 강제로 빼앗아 다른 프로세스에 할당할 수 있는\n스케줄링 방식을 의미합니다.

\n

다르게 표현한다면 어떠한 프로세스도 CPU를 독점할 수 없다는 말입니다.

\n

선점형의 예시중 하나는 지금까지 보았던, 특정 주기마다 CPU에 대한 할당 권한을 다른 프로세스에게 넘겨주는 방식이 있습니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n
\n

비 선점형 스케줄링

\n
\n

비선점형 스케줄링이란 하나의 프로세스가 자원을 사용하고 있다면 그 프로세스가 종료되거나\n스스로 대기 상태에 접어들기 전까진 다른 프로세스가 끼어들 수 없는 스케줄링입니다.

\n

다르게 표현한다면 특정 프로세스가 CPU를 사용하기 시작했다면 자원 사용을 독점할 수 있는 방식입니다.

\n
\n

\n \n \n \n \n \n
img.png
\n

\n
\n
\n

선점, 비선점의 장 단점

\n
\n

대부분의 운영체제는 선점형 스케줄링를 사용중입니다. 그럼에도 비선점형 스케줄링를 사용하는 곳이 있는데 그것은 각자의 장 단점이 존재하기 때문입니다.

\n
\n
    \n
  • 선점형 스케줄링 장점
  • \n
\n
\n

선점형 스케줄링은 어는 한 프로세스의 자원 독점을 막고 프로세스들에 골고루 자원을 분배 할 수 있다는 장점이 있습니다.

\n
\n
\n
    \n
  • 선점형 스케줄링 단점
  • \n
\n
\n

콘텍스트 스위칭이 빈번하기 떄문에 오버헤드가 많이 발생합니다.

\n
\n
\n
\n
    \n
  • 비 선점형 스케줄링 장점
  • \n
\n
\n

상대적으로 선점형 보다 콘텍스트 스위칭에 대한 오버헤드가 작게 발생합니다.

\n
\n
\n
    \n
  • 선점형 스케줄링 단점
  • \n
\n
\n

하나의 프로세스가 작업이 끝나기를 기다려야 하기 때문에, 모든 프로세스가 골고루 자원을 사용할 수 없습니다.

\n
\n
\n
\n

기아 상태(Starvation)

\n
\n

기아 상태란 우선순위가 밀린 프로세스가 영원히 자신의 우선순위까지 순서가 오지 못해 실행되지 못하는 상태를 기아 상태라고 합니다.

\n
\n
\n

기아 상태 해결법

\n
\n

이러한 기아 상태를 해결하기 위한 방법으로는

\n

에이징 기법을 활용하는 것입니다.

\n

기아 상태가 발생하는 이유는 항상 자신보다 높은 우선순위를 가지는 프로세스가 존재하기 떄문입니다.

\n

에이징 기법은 준비큐에서 대기가 길어진 프로세스들에게 우선순위를 조금씩 높여주는 방식을 사용합니다.\n결국 조금씩 우선순위가 높아진다면 언젠가는 해당 프로세스가 실행될 수 있게 됩니다.

","frontmatter":{"title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법","date":"September 16, 2025","update":"September 16, 2025","tags":["운영체제"],"series":"CPU 스케줄링"},"fields":{"slug":"/jc13/","readingTime":{"minutes":4.64}}},"seriesList":{"edges":[{"node":{"id":"59bb0404-6a3f-5c62-a448-24499754bbb4","fields":{"slug":"/jc12/"},"frontmatter":{"title":"CPU 스케줄링의 목적과 스케줄러의 종류"}}},{"node":{"id":"45c9933f-7bb7-5a1f-ae03-f34cd407a222","fields":{"slug":"/jc13/"},"frontmatter":{"title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법"}}},{"node":{"id":"ae9a2b29-4c95-5711-96bb-742626bb7775","fields":{"slug":"/jc14/"},"frontmatter":{"title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)"}}},{"node":{"id":"7b87c866-3440-52b3-9e3c-7a9d1a9357ab","fields":{"slug":"/jc15/"},"frontmatter":{"title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링"}}}]},"previous":{"fields":{"slug":"/jc12/"},"frontmatter":{"title":"CPU 스케줄링의 목적과 스케줄러의 종류"}},"next":{"fields":{"slug":"/jc14/"},"frontmatter":{"title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)"}}},"pageContext":{"id":"45c9933f-7bb7-5a1f-ae03-f34cd407a222","series":"CPU 스케줄링","previousPostId":"59bb0404-6a3f-5c62-a448-24499754bbb4","nextPostId":"ae9a2b29-4c95-5711-96bb-742626bb7775"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc14/page-data.json b/public/page-data/jc14/page-data.json new file mode 100755 index 0000000..0a1684a --- /dev/null +++ b/public/page-data/jc14/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc14/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"ae9a2b29-4c95-5711-96bb-742626bb7775","excerpt":"스케줄링 알고리즘 개요 스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다. 비선점 스케줄링 선입 선처리 스케줄링 (FCFS) 최단 작업 우선 스케줄링 (SJF) 선점 스케줄링 라운드 로빈 스케줄링 최소 잔여 시간 우성 스케줄링 (SRT) 우선순위 스케줄링 비 선점 스케줄링 선입 선처리 스케줄(FCFS) FCFS는 준비 큐에 들…","html":"

스케줄링 알고리즘 개요

\n
\n

스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다.

\n
\n
    \n
  • 비선점 스케줄링\n
      \n
    • 선입 선처리 스케줄링 (FCFS)
    • \n
    • 최단 작업 우선 스케줄링 (SJF)
    • \n
    \n
  • \n
\n
\n
    \n
  • 선점 스케줄링\n
      \n
    • 라운드 로빈 스케줄링
    • \n
    • 최소 잔여 시간 우성 스케줄링 (SRT)
    • \n
    • 우선순위 스케줄링
    • \n
    \n
  • \n
\n
\n

비 선점 스케줄링

\n
\n
\n

선입 선처리 스케줄(FCFS)

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

FCFS는 준비 큐에 들어가있는 순서대로 CPU를 할당하는 간단한 스케줄링 입니다.

\n

하지만, FCFS 방식에는 호위 효과라는 문제가 있습니다.

\n

그림을 보면 프로세스 A, B, C순서대로 실행되며 각각 실행 시간이 17, 5, 2 ms가 걸리게 됩니다.\n이상황에서 프로세스 B는 실행 상태가 되기 위해 최소 17ms를 기다려야 하며, 프로세스 c는 22ms를 기다리게 됩니다.

\n
\n

이러한 현상을 호위 효과(Convoy effect) 라고 하며 이것이 FCFS 스케줄링의 단점입니다.

\n
\n
\n
\n

하지만, 이러한 FCFS 방식도 배치 처리 시스템이나 작업 길이가 거의 비슷하고 사용자와 상호 작용이 필요하지 않는 환경에는\n적합하며, 멀티프로그래밍이나 실시간 시스템에서는 부적합합니다.

\n
\n
\n

최단 작업 우선 스케줄링(SJF)

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

최단작업 우선 스케줄링(SJF)는 이전 FCFS방식에서 호위 효과를 억제하기 위해 사용하는 방식입니다.

\n

호위 효과는 실행시간이 긴 프로세스 때문에 다른 프로세스가 기다리는 시간이 길다는 문제가 있고,\n이러한 문제를 실행시간이 짧은 프로세스를 먼저 시행되게 하여 해결하는 방식입니다.

\n

그림을 통해 보면 FCFS방식의 평균 대기시간은 13ms인 반면에 SJF방식의 편균대기 시간은 3ms로 줄어든것을\n확인할 수 있습니다.

\n
\n

즉 SJF방식은 호위효과를 줄여 프로세스들의 평균대기시간을 줄이는 방법으로 이해하면 됩니다.

\n
\n

하지만, 이러한 방식도 문제가 있는데, 실행 시간이 긴 프로세스가 기아상태에 빠지기 쉽다는 것입니다.

\n

이러한 방식은 평균 대기 시간을 중요하게 여기는 시스템에 적합하며, 실시간 시스템이나 사용자 대화형 시스템에 부적합하게 됩니다.

\n
\n
\n

선점 스케줄링

\n
\n
\n

라운드 로빈 스케줄링

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

라운드 로빈 스케줄링은 선입 선처리 방식(FCFS)방식에서 타임 슬라이스가 더해진 방식입니다.\n여기서 말하는 타임 슬라이스는 CPU를 사용할 수 있는 정해진 시간을 의미합니다.

\n

그림에서처럼 타임 슬라이스가 4ms이면 한번에 4ms까지 CPU를 할당받을 수 있고, 그 이후는 큐 가장 뒤로 들어가며\n콘텍스트 스위칭이 일어나게 됩니다.

\n
\n
\n

라운드 로빈 방식의 중요한 포인트는 슬라이스 크기입니다.

\n
\n

만약 슬라이스 크기가 지나치게 크다면 FCFS방식과 다를게 없을 것이고, 지나치게 작다면 콘텍스트 스위칭으로 인한\n오버헤드가 많이 발생할 것입니다.

\n
\n
\n

최소 잔여 시간 우선 스케줄링 (SRT)

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

최단 작업 우선 알고리즘(SJF) 그리고 라운드 로빈 알고리즘을 합친 형태입니다.\n즉 작업 시간이 짧은 프로세스를 먼저 실행하되, 타임슬라이스 보다 큰 프로세스는 다시 큐 뒤로 보내고 작업을 이어가는 방식입니다.

\n

위 알고리즘은 특이한 점이 있어서 상세히 설명하겠습니다.

\n
\n

SRT 동작 방식

\n
    \n
  1. 새로운 프로세스가 도착하면 그 프로세스의 남은 실행 시간을 계산합니다
  2. \n
  3. 준비 큐에 있는 프로세스 중에서 현재 실행 중인 프로세스를 포함하여 가장 짧은 실행 시간을 가진 프로세스에 CPU를 할당합니다
  4. \n
  5. 만약 새로운 프로세스가 도착하고 현재 실행 중인 프로세스 보다 남은 실행 시간이 더 짧다면 현재 프로세스는 중단되고 CPU는 새 프로세스에 할당되는 '선점'이 발생합니다.
  6. \n
  7. 선점이 발생하면 운영체제는 콘텍스트 스위칭으로 CPU자원을 현재 프로세스에서 새 프로세스로 교체합니다.
  8. \n
  9. 선점된 프로세스는 준비 큐로 이동합니다.
  10. \n
\n
\n

SRT또한 SJF와 비슷한 장 단점을 공유하는데, 평균 대기 시간을 최소화 하는 장점을 가지지만, 작업 시간이 긴\n프로세스는 CPU 할당을 받기 어렵다는 단점이 있습니다.

\n
\n
\n

우선 순위 스케줄링

\n
\n

우선순위 스케줄링은 우선순위를 부여하고, 가장 높은 우선순위를 가진 프로세스부터 실행하는 알고리즘 입니다.\n만약 같은 우선순위가 있다면 선입 선처리로 처리 됩니다.

\n

이러한 우선순위 알고리즘 방식은 기아(Starvation) 현상을 동반하며 이는 에이징 방식으로 해결가능 하다고 이전 파트에서 설명했으니\n넘어가겠습니다.

\n

출처

\n
\n

이미지 출처

\n

SRT 출처

","frontmatter":{"title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)","date":"September 17, 2025","update":"September 17, 2025","tags":["운영체제"],"series":"CPU 스케줄링"},"fields":{"slug":"/jc14/","readingTime":{"minutes":7.49}}},"seriesList":{"edges":[{"node":{"id":"59bb0404-6a3f-5c62-a448-24499754bbb4","fields":{"slug":"/jc12/"},"frontmatter":{"title":"CPU 스케줄링의 목적과 스케줄러의 종류"}}},{"node":{"id":"45c9933f-7bb7-5a1f-ae03-f34cd407a222","fields":{"slug":"/jc13/"},"frontmatter":{"title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법"}}},{"node":{"id":"ae9a2b29-4c95-5711-96bb-742626bb7775","fields":{"slug":"/jc14/"},"frontmatter":{"title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)"}}},{"node":{"id":"7b87c866-3440-52b3-9e3c-7a9d1a9357ab","fields":{"slug":"/jc15/"},"frontmatter":{"title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링"}}}]},"previous":{"fields":{"slug":"/jc13/"},"frontmatter":{"title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법"}},"next":{"fields":{"slug":"/jc15/"},"frontmatter":{"title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링"}}},"pageContext":{"id":"ae9a2b29-4c95-5711-96bb-742626bb7775","series":"CPU 스케줄링","previousPostId":"45c9933f-7bb7-5a1f-ae03-f34cd407a222","nextPostId":"7b87c866-3440-52b3-9e3c-7a9d1a9357ab"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc15/page-data.json b/public/page-data/jc15/page-data.json new file mode 100755 index 0000000..ccd68e7 --- /dev/null +++ b/public/page-data/jc15/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc15/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"7b87c866-3440-52b3-9e3c-7a9d1a9357ab","excerpt":"다단계 큐 스케쥴링(Multilevel queue scheduling) 멀티 레벨 스케줄링은 우선순위 스케줄링의 발전된 형태입니다.\n아래 그림을 통해 설명 하면, 이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데,\n멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다. 가장 높은 우선순위에 있는 큐들을 처리하고,…","html":"

다단계 큐 스케쥴링(Multilevel queue scheduling)

\n
\n

멀티 레벨 스케줄링은 우선순위 스케줄링의 발전된 형태입니다.\n아래 그림을 통해 설명 하면,

\n
\n

\n \n \n \n \n \n
img.png
\n

\n
\n

이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데,\n멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다.

\n

가장 높은 우선순위에 있는 큐들을 처리하고, 가장 높은 우선순위 큐가 비게 된다면 그 아래 우선순위의 큐를 처리하게 됩니다.\n그림을 통해 이해하자면, 우선순위 0 -> 우선순위 1 -> 우선순위 2 이렇게 처리하게 되는것입니다.

\n

멀티레벨 큐의 특징으로는 각각의 큐들을 개별적으로 핸들링 할 수 있습니다.\n예를들어, 특정 큐의 타임 슬라이드와 다른 큐의 타임 슬라이드를 다르게 처리 한다던가, 혹은 스케줄링 방식 자체를\nFCFS를 적용하고 다른 곳에서는 라운드로빈을 적용하는것 처럼 개별적인 핸들링이 가능합니다.

\n
\n
\n

다단계 큐 스케쥴링 문제점

\n
\n

다단계 큐 스케줄링의 문제점으로는 기아 현상이 있습니다.

\n

멀티레벨 큐 방식에서는 큐간의 이동이 불가능합니다. 그렇기 떄문에 우선순위가 낮은 곳에 배정받은 프로세스들은\n이전에 보았던 에이징방식을 사용할수 없습니다. 그렇기 때문에 이러한 방식은 우선순위가 올때 까지 기다려야 하는\n기아 현상을 문제로 가지고 있습니다.

\n

이러한 방식의 해결법은 아래 설명할 다단계 피드백 큐 스케줄링으로 해결이 가능합니다.

\n
\n
\n

다단계 피드백 큐 스케줄링(multilevel feedback queue scheduling)

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

다단계 피드백 큐 스케줄링 같은경우는 프로세스들이 큐 사이로 이동할 수 있습니다. 그렇기 때문에 이전 방식에서 보았던\n기아현상을 직접적으로 해결할 수 있습니다.

\n
\n

다단계 피드백 큐 스케줄링 특징

\n

이러한 이동가능한 점 때문에 멀티 레벨 큐와 다른 점이 있습니다.\n멀티 레벨 피드백 큐는 처음 생성된 프로세스가 우선순위가 가장 높은 큐로 삽입이 됩니다. 그 이후 CPU를 할당받고\n타임슬라이드 동안 실행되며, 이 실행이 끝나게 된다면 다음 우선순위 큐로 넘어 갑니다(우선순위가 낮아짐). 또 다음 우선순위\n큐에서 실행이 끝나지 않는다면 또 다음 우선순위로 넘어가고 이 과정을 반복합니다.

\n

이렇게 우선순위가 낮아지는 방식을 사용함으로써 자동으로 CPU 버스트가 많은 프로세스는 우선순위가 낮아지고,\nIO 버스트가 많은 프로세스는 상대적으로 우선순위가 높아질것입니다.

\n

기아 해결

\n

또한, 프로세스들이 이동가능 하기 때문에 우선순위가 낮아져 기아상태에 빠진 프로세스에는 에이징기법을 적용해\n다시 우선순위를 높이게 됩니다.

","frontmatter":{"title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링","date":"September 18, 2025","update":"September 18, 2025","tags":["운영체제"],"series":"CPU 스케줄링"},"fields":{"slug":"/jc15/","readingTime":{"minutes":4.51}}},"seriesList":{"edges":[{"node":{"id":"59bb0404-6a3f-5c62-a448-24499754bbb4","fields":{"slug":"/jc12/"},"frontmatter":{"title":"CPU 스케줄링의 목적과 스케줄러의 종류"}}},{"node":{"id":"45c9933f-7bb7-5a1f-ae03-f34cd407a222","fields":{"slug":"/jc13/"},"frontmatter":{"title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법"}}},{"node":{"id":"ae9a2b29-4c95-5711-96bb-742626bb7775","fields":{"slug":"/jc14/"},"frontmatter":{"title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)"}}},{"node":{"id":"7b87c866-3440-52b3-9e3c-7a9d1a9357ab","fields":{"slug":"/jc15/"},"frontmatter":{"title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링"}}}]},"previous":{"fields":{"slug":"/jc14/"},"frontmatter":{"title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)"}},"next":{"fields":{"slug":"/jc16/"},"frontmatter":{"title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성"}}},"pageContext":{"id":"7b87c866-3440-52b3-9e3c-7a9d1a9357ab","series":"CPU 스케줄링","previousPostId":"ae9a2b29-4c95-5711-96bb-742626bb7775","nextPostId":"15749e2b-95a6-50ae-94d5-fc0acd81f54c"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc16/page-data.json b/public/page-data/jc16/page-data.json new file mode 100755 index 0000000..c429982 --- /dev/null +++ b/public/page-data/jc16/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc16/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"15749e2b-95a6-50ae-94d5-fc0acd81f54c","excerpt":"병행성(Concurrency) 병행성은 다른 말로 동시성이라고 부르는 용어입니다.\n이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 컨텍스트 스위칭을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다.\n이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실…","html":"

병행성(Concurrency)

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

병행성은 다른 말로 동시성이라고 부르는 용어입니다.\n이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 컨텍스트 스위칭을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다.\n이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실행되는 것은 아닙니다.

\n

동시성의 핵심 키워드는 동시에 처리되게 보이는것입니다.

\n
\n
\n

병렬성(Parallelism)

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

병렬 처리는 프로그램의 독립적인 작업을 동시에 실행할 수 있는 능력입니다. 이러한 작업은\n다른 프로세스 코어 단위에서, 혹은 분산 시스템 처럼 완전히 다른 컴퓨터에서 동시에 실행될 수 도 있습니다.

\n

병렬성의 핵심 키워드는 실제로 동시에 처리되고 있는것입니다.

\n
\n
\n

동기화

\n
\n

동시다발적으로 실행되는 프로세스들은 공동의 목적을 수행하기 위해 서로 협력하며 영향을 주고 받기도 합니다.\n조금 전 설명했던 동시성, 병렬성 모두 동시다발적으로 수행되는 환경입니다.

\n

이런 환경의 예시를 하나들면, 워드 프로세스가 있습니다. 해당 프로세스는 글을 쓸수도 있고, 쓰여진 글을 읽을 수도 있고,\n맞춤법을 검사하는 기능도 있습니다. 하지만 해당 프로세스가 따로 동작하는 것이 아닌 모두 하나의 프로그램처럼 보여지고 있습니다.

\n

이런 상황을 동시 다발적이란 표현을 통해 하고, 이런 동시 다발적인 상황의 수행 시기를 맞춰주는 것이\n동기화라고 합니다.

\n
\n

수행 시기를 맞추다?

\n

이전에 설명한 수행 시기를 맞추다는 말은 추상적입니다.

\n

이를 두가지 관점으로 볼 수 있습니다.

\n
    \n
  1. 실행 순서 제어: 프로세스를 올바른 순서대로 실행하는것
  2. \n
  3. 상호 배제: 동시에 접근해서는 안 되는 자원에 하나의 프로세스만 접근하는 것
  4. \n
\n

다시 말해 동기화는 실행 순서를 제어하는 동기화와, 상호 배제를 위한 동기화가 있습니다.

\n
\n
\n

1. 실행 순서를 제어하는 동기화

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

실행 순서를 제어한다는 것은 요리 레시피 순서를 지키는것과 같습니다.\n재료를 준비하고, 손질하고, 요리하는 이런 일련의 과정을 지켜 보았을 때\n재료 손질이 준비보다 먼저일 수 없고, 요리또한 손질보다 먼저일 수 없습니다.

\n

프로세스도 마찬가지로 무언가를 읽게 하였는데 읽은 대상이 생성 되어있고, 작성되어있어야 합니다.\n이런 것을 실행 순서라고 표현하며 이것을 지키게 하는 것을 동기화라고 표현합니다.

\n
\n
\n

2. 상호 배제를 위한 동기화

\n
\n

상호 배제란 공유가 불가능한 자원의 동시 사용을 피하기 위해 사용하는 알고리즘입니다.\n여기서 말하는 공유가 불가능한 자원은 실제로 공유하면 안되는 자원이 아닌, 동시 사용하는 경우 문제가 발생하는\n자원입니다.

\n

아래 예시를 통해서 보면

\n

\n \n \n \n \n \n
img.png
\n

\n

프로세스A는 현재 잔고에서 2만원을 더하고, 프로세스B는 현재 잔고에서 5만원을 더합니다.\n이러한 경우 총합 7만원을 더하는 형태가 될것입니다.

\n

하지만 프로세스A가 값을 더하고(12만원) 저장하기 전에 콘텍스트 스위칭이 일어난다면 다음 프로세스B는\n저장하기 전 값을 조회하고(10만원) 자신의 값을 저장할것 입니다(15만원).\n다시 프로세스 A로 돌아오면 12만원을 저장하고 프로세스 B로 돌아오면 15만원을 저장합니다.\n이과정에서 서로의 결과를 무시하는 방향으로 진행되고 최종적으로 마지막에 저장한 값은 다른 프로세스의 결과를\n반영하지 않는 상태가 됩니다.

\n

이런 상황은 동시에 사용하는 자원에 대해 동기화를 이루지 못해서 발생한 경우이고, 이 경우 상호 배제를 위한 동기화\n를 진행해야 합니다.

\n
\n
\n

출처

\n
\n

동시성, 병렬성 출처\n이미지 출처

","frontmatter":{"title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성","date":"September 19, 2025","update":"September 19, 2025","tags":["운영체제"],"series":"프로세스 동기화"},"fields":{"slug":"/jc16/","readingTime":{"minutes":6.355}}},"seriesList":{"edges":[{"node":{"id":"15749e2b-95a6-50ae-94d5-fc0acd81f54c","fields":{"slug":"/jc16/"},"frontmatter":{"title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성"}}},{"node":{"id":"c80f6afe-e857-55ad-9db0-732b80dba4e4","fields":{"slug":"/jc17/"},"frontmatter":{"title":"임계구역과 경쟁상태"}}},{"node":{"id":"0684370e-6b4b-5b53-888f-57b7af8420b0","fields":{"slug":"/jc18/"},"frontmatter":{"title":"상호배제와 동기화 기법"}}},{"node":{"id":"b19e8b85-ca19-51c2-a8f6-bef465859e51","fields":{"slug":"/jc19/"},"frontmatter":{"title":"교착상태와 해결 방법"}}}]},"previous":{"fields":{"slug":"/jc15/"},"frontmatter":{"title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링"}},"next":{"fields":{"slug":"/jc17/"},"frontmatter":{"title":"임계구역과 경쟁상태"}}},"pageContext":{"id":"15749e2b-95a6-50ae-94d5-fc0acd81f54c","series":"프로세스 동기화","previousPostId":"7b87c866-3440-52b3-9e3c-7a9d1a9357ab","nextPostId":"c80f6afe-e857-55ad-9db0-732b80dba4e4"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc17/page-data.json b/public/page-data/jc17/page-data.json new file mode 100755 index 0000000..528d56d --- /dev/null +++ b/public/page-data/jc17/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc17/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"c80f6afe-e857-55ad-9db0-732b80dba4e4","excerpt":"공유자원 동시에 실행되는 프로세스에서 공통으로 사용하는 자원을 우리는 공유자원이라고 부릅니다. 임계구역(Critical Section) 공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 임계 구역이라고 부릅니다. 두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한…","html":"

공유자원

\n
\n

동시에 실행되는 프로세스에서 공통으로 사용하는 자원을 우리는 공유자원이라고 부릅니다.

\n
\n
\n

임계구역(Critical Section)

\n
\n

공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 임계 구역이라고 부릅니다.

\n

두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한 프로세스의\n작업이 마무리되면 그제서야 기다렸던 프로세스가 임계 구역에 진입 합니다.

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n
\n

경쟁상태(Race Condition)

\n
\n

임계 구역은 두 개 이상의 프로세스가 동시에 실행되면 안 되는 영역이지만, 잘못된 실행으로 여러 프로세스가\n공유 자원을 사용하는 경우에 문제가 발생합니다.\n이러한 문제를 경쟁 상태라고 합니다.

\n

이러한 경쟁 상태는 데이터의 일관성이 깨지는 문제를 발생시킵니다.

\n
\n
\n

운영체제가 임계구역 문제를 해결하는 세가지 원칙

\n
\n

1. 상호배제: 한 프로세스가 임계 구역에 진입했다면 다른 프로세스가 들어올 수 없다.

\n

2. 진행: 임계구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세는 들어갈 수 있어야 한다.

\n

3. 유한 대기: 한 프로세스가 임계구역에 진입하고 싶다면 언젠가는 임계구역에 들어갈 수 있어야 한다.(무한정 대기x)

\n

출처

\n
\n

이미지 출처

","frontmatter":{"title":"임계구역과 경쟁상태","date":"September 20, 2025","update":"September 20, 2025","tags":["운영체제"],"series":"프로세스 동기화"},"fields":{"slug":"/jc17/","readingTime":{"minutes":2.27}}},"seriesList":{"edges":[{"node":{"id":"15749e2b-95a6-50ae-94d5-fc0acd81f54c","fields":{"slug":"/jc16/"},"frontmatter":{"title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성"}}},{"node":{"id":"c80f6afe-e857-55ad-9db0-732b80dba4e4","fields":{"slug":"/jc17/"},"frontmatter":{"title":"임계구역과 경쟁상태"}}},{"node":{"id":"0684370e-6b4b-5b53-888f-57b7af8420b0","fields":{"slug":"/jc18/"},"frontmatter":{"title":"상호배제와 동기화 기법"}}},{"node":{"id":"b19e8b85-ca19-51c2-a8f6-bef465859e51","fields":{"slug":"/jc19/"},"frontmatter":{"title":"교착상태와 해결 방법"}}}]},"previous":{"fields":{"slug":"/jc16/"},"frontmatter":{"title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성"}},"next":{"fields":{"slug":"/jc18/"},"frontmatter":{"title":"상호배제와 동기화 기법"}}},"pageContext":{"id":"c80f6afe-e857-55ad-9db0-732b80dba4e4","series":"프로세스 동기화","previousPostId":"15749e2b-95a6-50ae-94d5-fc0acd81f54c","nextPostId":"0684370e-6b4b-5b53-888f-57b7af8420b0"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc18/page-data.json b/public/page-data/jc18/page-data.json new file mode 100755 index 0000000..566157d --- /dev/null +++ b/public/page-data/jc18/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc18/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"0684370e-6b4b-5b53-888f-57b7af8420b0","excerpt":"상호배제(Mutual Exclusion) 상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다. 일상생활에서 비유하면, 화장실 사용과 같습니다.\n한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다.\n컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 …","html":"

상호배제(Mutual Exclusion)

\n
\n

상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다.

\n

일상생활에서 비유하면, 화장실 사용과 같습니다.\n한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다.\n컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 프로세스만 사용할 수 있어야 합니다.

\n
\n

왜 상호배제가 필요할까?

\n

현대 운영체제는 멀티태스킹 환경에서 여러 프로세스가 동시에 실행됩니다.\n이때 프로세스들이 공유하는 자원(메모리, 파일, 데이터베이스 등)에 동시에 접근하면 다음과 같은 문제가 발생할 수 있습니다.

\n

1.경쟁 상황(Race Condition)

\n

두 프로세스가 동시에 같은 데이터를 수정하려 할 때, 실행 순서에 따라 결과가 달라지는 상황입니다.\n예를 들어, 은행 계좌 잔액을 동시에 업데이트하는 두 거래가 있다면, 최종 잔액이 예상과 다를 수 있습니다.

\n

2. 데이터 일관성 파괴

\n

여러 프로세스가 동시에 데이터를 수정하면 데이터의 무결성이 깨질 수 있습니다. 이는 시스템 전체의 신뢰성에 큰 영향을 미칩니다.

\n
\n
\n

동기화 기법

\n
\n

이런 상호 배제에 대해 방지하는 방법으로는 뮤텍스, 세마포어, 모니터 기법이 있습니다.

\n
\n
\n

뮤텍스 락(Mutex lock)

\n
\n

뮤텍스 락의 풀네임은 Mutual Exclusion Lock입니다. 즉 상호 배제 단어에 lock을 붙인 단어와 일치합니다.

\n

이 말은 상호배제를 구현하기 위해 Locking방식을 사용하는 방법입니다.

\n

뮤텍스 락은 화장실 사용에 비유해보겠습니다.

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

화장실은 한칸에 한사람만 받을 수 있습니다. 칸에 사람이 들어가있다면 해당 칸에 다른 사람이 들어올 수 없습니다.\n다른 사람이 들어오는 시점은 먼저 사용하던 사람이 해당 칸을 나가게 되면 사용할 수 있습니다.

\n

이 내용을 설명하는 이유는, 위 방식의 흐름이 뮤텍스 락과 동일하기 때문입니다.

\n

간단한 뮤텍스락을 코드를 통해서 보겠습니다.

\n

자물쇠에 해당하는 전역변수 하나, 그리고 해당 자물쇠를 잠구고, 푸는 두가지 함수만 있으면 구현가능합니다.

\n
\n
\n
acquire(){\n    while (lock == true){\n        .....\n        }\n    \n    lock = true;\n}
\n
release(){\n    lock = false;\n        }
\n
\n

해당 함수들은 차례대로 화장실 문이 잠겼는지 확인하고 잠기지 않았다면 들어가서 잠구는 함수 Acquire,\n그리고 화장실을 나올때 잠금을 해제 하는 Release로 볼 수 있습니다.

\n

이 함수를 아래 수도코드 처럼, 임계 구역 들어가기전, 나온 후 에 사용하게 되면

\n
acquire();\n// 임계 구역\nrelease();
\n

lock여부를 확인 한 후, 들어가도 되면 본인이 lock을 걸고 이미 lock이 걸려있다면\n임계 구역 코드 전에서 계속 기다리게 됩니다.

\n
\n

뮤텍스 락의 단점

\n

하지만, 이런 방식에는 큰 문제가 있는데 바쁜대기(Busy Wait) 을 수행하게 됩니다.\n명칭 그대로 대기를 하는 상황임에도 바쁘게 행동하는 것을 말하게 됩니다.

\n

대기를 하는 상황에 행동을 하는것은 lock 확인작업에 CPU를 사용하겠다는 것을 의미하고,\n이런 기다림은 해당 lock 이 풀릴떄까지 지속됩니다. 즉, 비효율적입니다.

\n
\n
\n

세마포(semaphore)

\n
\n

세마포는 동기화 방식중 하나입니다. 뮤텍스 락과 비교하면 공유자원의 갯수를 다루는 방식이 다릅니다.\n뮤텍스 락은 공유자원이 하나라고 가정하고 라킹을 수행하지만, 세마포는 공유 자원이 여러 개 있을경우\n각 프로세스는 해당 공유자원에 접근이 가능합니다.

\n

마치 공중화장실에서 화장신 칸 수 만큼 공유자원이 있고, 각 칸에 사람이 들어가는 것을 관리하는 방식입니다.

\n

\n \n \n \n \n \n
img.png
\n

\n

세마포는 사진과 같은 철도 신호기에서 유래한 단어 입니다. 그렇기 때문에 철도 신호와 같은 방식을 사용합니다.

\n

뮤텍스 락은 공유 자원을 잠금, 해제를 수행하면서 해당 자원을 관리하지만,

\n

세마포의 경우 빨간불, 초록불 처럼 가도 되는지, 멈춰야 하는지 상태를 알려줍니다.

\n

세마포도 간단하게 코드로 구현이 가능합니다.

\n

먼저 공유자원의 갯수를 나타내는 전역 변수 한개와, 임계구역에 들어가도 되는지, 기다려야 할지 알려주는 함수 Wait,\n그리고 기다리고 있는 프로세스에게 이제 출발하라를 나타내는 Signal함수가 있습니다.

\n
\n
wait() {\n    while(S <= 0){\n        \n        }\n    S--;\n}
\n
signal() {\n    S++;\n}
\n

위 코드를 차례대로 Wait, Signal함수를 구현한것이고 전역 변수 S의 값이 양수, 즉 사용해도 되는\n공유자원이 있을 경우 Wait함수의 while문을 탈출합니다.

\n

그 경우 사용가능한 공유 자원 갯수를 하나 줄입니다.

\n
wait();\n// 임계 구역\nsignal();
\n

임계 구역을 나오게 되면 signal이 수행될것이고, 사용가능한 자원을 하나 반납하게 될것입니다.

\n
\n

근데 while문이 있다면 뮤텍스락처럼 바쁜 대기 상태가 발생할 수 있다는걸 암시하게 됩니다.\n하지만 이는 세마포가 CPU를 사용하지 않게 구현하며 해결할 수 있습니다.

\n
\n

세마포가 busy wait를 해결하는 방법

\n
\n

아래 두가지 함수를 통해서 세마포는 busy wait를 해결합니다.

\n
wait(){\n    S--;\n    if ( S < 0){\n        add this process to Queue;\n        sleep();\n    }\n}
\n
signal(){\n    S++\n    if ( S <= 0){\n        remove a process p from Queue;\n        wakeup(p);\n        }        \n}
\n

위 방식은 이전처럼 while문을 통한 접근 가능여부를 체크하는 것이 아닌 만약 접근 불가능 한경우(사용가능한 공유 자원이 없을떄)\n해당 프로세스의 PCB세마포를 위한 대기 큐에 넣습니다.

\n

프로세스는 대기 큐에 들어가게 되면서 이후 해당 PCB준비 큐로 돌리기 전까지 CPU자원을 잡아 먹지 않게 됩니다.

\n
\n
\n

모니터

\n
\n

세마포 기법 자체는 동기화도구로써 좋은 효능을 보여주지만, 사용자 측면에서 불편한 점이 있다.\n임계 구역에 앞뒤로 wait, signal 함수를 사용하고 휴먼에러로 인한 실수가 발생한다면 예기치 못한 결과를 발생시킬 수 있기 때문이다.

\n

이에 모니터라는 동기화 도구가 생기게 된다.

\n

모니터는 공유 자원과, 공유 자원에 접근하기 위한 인터페이스를 묶어 관리합니다.

\n
\n

\n \n \n \n \n \n
img.png
\n

\n
\n

이를 위해 모니터를 통해 공유 자원에 접근하고자 하는 프로세스를 큐에 삽입하고, 큐에 삽입된 순서대로 하나씩 공유 자원을 이용하도록 합니다.\n모니터는 공유 자원을 다루는 인터페이스에 접근하기 위한 큐를 만들고, 모니터 안에 항상 하나의 프로세스만 들어오도록 하여 상호 배제를 수행합니다.

\n

또한, 모니터는 실행 순서를 제어하는 동기화 또한 수횅합니다. 조건 변수를 사용해서 실행 순서를 제어하게 됩니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

해당 그림처럼 기존 상호 배제를 위한 큐가 아닌 조건 변수에 대한 큐가 있습니다. 이 조건 변수는 기존처럼 wait, signal 연산을\n수횅할 수 있습니다.

\n

상호 배제를 위한 큐에서 가장 선두에 있는 프로세스A보다 특정 프로세스B가 더 먼저 시행되어야 한다면, B가 수행되기 전까지 앞선 프로세스들은 wait 연산을 통해\n조건 변수에 대한 큐에서 대기하게 되고, 그렇게 대기를 하게되면 최우선 시행되는 프로세스는 B가 될것입니다. 이런 형태로 모니터는 실행 순서를 제어합니다.

\n

출처

\n
\n

이미지 출처

","frontmatter":{"title":"상호배제와 동기화 기법","date":"September 21, 2025","update":"September 21, 2025","tags":["운영체제"],"series":"프로세스 동기화"},"fields":{"slug":"/jc18/","readingTime":{"minutes":11.43}}},"seriesList":{"edges":[{"node":{"id":"15749e2b-95a6-50ae-94d5-fc0acd81f54c","fields":{"slug":"/jc16/"},"frontmatter":{"title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성"}}},{"node":{"id":"c80f6afe-e857-55ad-9db0-732b80dba4e4","fields":{"slug":"/jc17/"},"frontmatter":{"title":"임계구역과 경쟁상태"}}},{"node":{"id":"0684370e-6b4b-5b53-888f-57b7af8420b0","fields":{"slug":"/jc18/"},"frontmatter":{"title":"상호배제와 동기화 기법"}}},{"node":{"id":"b19e8b85-ca19-51c2-a8f6-bef465859e51","fields":{"slug":"/jc19/"},"frontmatter":{"title":"교착상태와 해결 방법"}}}]},"previous":{"fields":{"slug":"/jc17/"},"frontmatter":{"title":"임계구역과 경쟁상태"}},"next":{"fields":{"slug":"/jc19/"},"frontmatter":{"title":"교착상태와 해결 방법"}}},"pageContext":{"id":"0684370e-6b4b-5b53-888f-57b7af8420b0","series":"프로세스 동기화","previousPostId":"c80f6afe-e857-55ad-9db0-732b80dba4e4","nextPostId":"b19e8b85-ca19-51c2-a8f6-bef465859e51"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc19/page-data.json b/public/page-data/jc19/page-data.json new file mode 100755 index 0000000..0cc5a85 --- /dev/null +++ b/public/page-data/jc19/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc19/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"b19e8b85-ca19-51c2-a8f6-bef465859e51","excerpt":"교착상태란?(Dead Lock) 교착상태란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다. 교착상태를 설명하는 대표적인 예시로 식사하는 철학자 문제라는게 있습니다. 식사하는 철학자 식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습…","html":"

교착상태란?(Dead Lock)

\n
\n

교착상태란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다.

\n

교착상태를 설명하는 대표적인 예시로 식사하는 철학자 문제라는게 있습니다.

\n
\n

식사하는 철학자

\n
\n

\n \n \n \n \n \n
img.png
\n

\n
\n

식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습니다.\n식사를 하려면 두개의 포크를 들어야 하는 상황입니다.

\n

이를 순서도로 표현하면

\n
    \n
  1. 생각을 하다가 왼쪽 포크를 들 수 있다면 든다.
  2. \n
  3. 생각을 하다가 오른쪽 포크를 들 수 있다면 든다.
  4. \n
  5. 왼쪽, 오른쪽 포크를 모두 집어들면 정해진 시간동안 식사를 한다.
  6. \n
  7. 식사 시간이 끝나면 오른쪽 포크를 내려놓는다.
  8. \n
  9. 나머지 왼쪽 포크도 내려놓는다.
  10. \n
  11. 1번부터 반복한다.
  12. \n
\n
\n

위와같은 상황일때 모든 철학자가 왼쪽 포크를 들고 있거나, 반대쪽 포크를 들고 있다면 식사는 영원히 끝나지 않습니다. 이유는 포크라는 자원은\n철학자의 수만큼 존재하고 각 철학자는 두개의 포크를 원하는 상태에서 모든 포크를 얻을때까지 가디라기 떄문에, 모든 철학자가 포크를 기다리기만 하는\n상황이 발생합니다.

\n

이러한 문제는 일어나지 않을 사건을 기다리며 진행이 멈춰 버리는 교착상태와 같습니다.

\n

여기서 철학자를 프로세스 혹은 스레드 포크를 자원 그리고 생각하는 행위가 자원을 기다리는 것이라고 생각한다면, 프로세스와 스레드는\n자원을 사용하기 위해 기다리는 행위만 계속하는 상황이 되는것입니다.

\n
\n
\n

교착상태 발생조건

\n
\n

교착상태가 발생할 조건에는 네가지가 있습니다. 차례대로 상호배제, 점유와 대기, 비선점, 원형 대기입니다. 해당 조건은\n모두 만족해야지 교착상태가 발생하고 하나라도 해당하지 않는다면 교착상태는 발생하지 않습니다.

\n
\n

1. 상호 배제

\n

교착 상태가 발생한 근본적인 원인은 해당 자원을 하나의 프로세스만 사용하기 때문입니다. 프로세스도 마찬가지로 한 프로세스가 사용하는 자원을 다른 프로세스가\n사용할 수 없을때, 교착상태가 발생합니다.

\n

2. 점유와 대기

\n

프로세스는 자원을 할당받은 상태에서 다른 자원을 할당받기를 기다린다면 교착 상태가 발생할 수 있습니다. 이렇게 자원을 할당받은 상태에서 다른 자원을\n할당받기를 기다리는 상태점유와 대기라고 합니다.

\n

3. 비선점

\n

이전에 선점, 비선점이라는 개념을 보았습니다. 비선점이란 프로세스나 스레드가 자원을 할당받으면 그 작업이 끝나기전까지 자원을 뻇어갈수 없다는\n특징이 있었습니다. 교착상태가 발생하는 원인은 점유와 대기상태중 필요한 자원을 선점할수 없이 계속 기다리기만 하여서 발생하는 문제 입니다.

\n

4. 원형 대기

\n

자원 할당 그래프가 원의 형태로 그려지면 교착 상태가 발생할 수 있습니다. 이렇게 프로세스들이 원의 형태로 자원을 대기하는 것을 원형 대기라고 합니다.

\n
\n
\n

교착상태 해결방법

\n
\n

교착상태를 해결하는 방법은 크게 세가지로 나눌수 있습니다.

\n
\n
    \n
  1. 예방
  2. \n
  3. 회피
  4. \n
  5. 검출 후 회복
  6. \n
\n
\n
\n
\n

예방을 통한 해결

\n
\n

예방이란 교착상태 발생 조건에 부합하지 않게 자원을 분배하는 방식입니다.

\n

이전에 말한 교착상태발생 조건에 해당하는 네 가지 중 하나를 충족 하게 되면 교착 상태를 해결할 수 있습니다.

\n

상호 배제를 없애는 방식

\n
\n

이론적으로는 가능하나, 모든 자원이 상호 배제를 없애기는 어렵기 때문에 비현실적이다.

\n
\n
\n

점유와 대기를 없애는 방식

\n
\n

특정 자원이 먼저 점유를 수행하여 작업을 끝내고, 다른 프로세스에게 자원을 몰아주는 방식으로 해결이 가능합니다.

\n

하지만 이런 방식은 자원 활용률이 낮아 진다는 문제가 있습니다.

\n
\n
\n

비선점 조건을 없애는 방식

\n
\n

비선점 방식으로 작업을 다루게 되면 교착상태가 발생해도 자원을 뺏어 해결 할 수 있습니다.

\n

하지만, 이런방식의 문제점은 모든 자원이 비선점 기능을 사용할 수 없다는 점에 있습니다.

\n

예를들어, 프린터는 비선점 방식을 수행하는 자원입니다.

\n
\n
\n

원형 대기 조건을 없애는 방식

\n
\n

모든 자원에 번홀을 붙이고 오름차순으로 자원을 할당하면 원형 대기는 방생하지 않습니다.\n마치 원형이 아닌, 선형으로 자원을 나열하는 방식입니다.

\n

이런 방식은 자원에 일일이 번호를 붙여야 한다는점과, 특정 번호는 자원 활용률이 떨어질수 있다는 문제가 있습니다.

\n
\n
\n
\n

회피를 통한 해결

\n
\n

회피 방식에서는 교착 상태 발생이 한정된 자원을 무분별하게 할당하였서 그렇다고 가정합니다. 그렇기 때문에 회피방식은 자원을 신중하게 할당하는 방식으로\n해결합니다.

\n

즉, 교착 상태가 발생하지 않을 정도의 양만큼만 자원을 배분하는 방법을 교착 상태 회피라고 부릅니다.

\n

안정 상태, 불안전 상태가 있습니다. 각각 교착상태가 발생하지 않는 상태를 안정상태, 발생할 가능성이 있는 상태를 불안정 상태라고 부릅니다.

\n

회피를 통해 교착상태를 해결하기 위해 안전 순서열을 고려해서 문제를 해결합니다.

\n
\n

안전순서열: 교착 상태 없이 안전하게 프로세스들에 자원을 할당할 수 있는 순서를 의미합니다.

\n
\n
\n

내용을 종합하면 안전 순서열이 있고 그것을 사용할때 상태를 안정상태, 안전 순서열이 없을 때 상태는 불안정상태라고 부르게 됩니다.

\n
\n
\n

교착 상태 검출 후 회복

\n
\n

마지막으로, 교착상태를 피하기 위해서는 검출, 회복 방식을 사용합니다.

\n

두가지 방식을 고려할 수 있는데,

\n
    \n
  1. 선점을 통한 회복
  2. \n
  3. 프로세스 강제종료
  4. \n
\n
\n

선점을 통한 회복

\n

교착 상태가 해결될 때까지 한 프로세스씩 자원을 몰아주는 방식입니다. 교착 상태가 해결될 떄까지 다른 프로세스로부터 자원을 빼앗고 할당하는 방식입니다.

\n
\n

강제종료를 통한 회복

\n

교착 상태에 놓인 순간 모든 프로세스를 종료 하는 방법 혹은 프로세스를 하나씩 종료해서 확인해보는 방법이 있습니다.

\n

전자는 가장 확실하지만 모든 작업에 대한 진행사항을 잃을 가능성이 있고, 후자는 전자보다 손실에 대한 부담은 적지만 오버헤드가 커진다는 단점이 있습니다.

\n

출처

\n
\n

이미지 출처

","frontmatter":{"title":"교착상태와 해결 방법","date":"September 22, 2025","update":"September 22, 2025","tags":["운영체제"],"series":"프로세스 동기화"},"fields":{"slug":"/jc19/","readingTime":{"minutes":10.46}}},"seriesList":{"edges":[{"node":{"id":"15749e2b-95a6-50ae-94d5-fc0acd81f54c","fields":{"slug":"/jc16/"},"frontmatter":{"title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성"}}},{"node":{"id":"c80f6afe-e857-55ad-9db0-732b80dba4e4","fields":{"slug":"/jc17/"},"frontmatter":{"title":"임계구역과 경쟁상태"}}},{"node":{"id":"0684370e-6b4b-5b53-888f-57b7af8420b0","fields":{"slug":"/jc18/"},"frontmatter":{"title":"상호배제와 동기화 기법"}}},{"node":{"id":"b19e8b85-ca19-51c2-a8f6-bef465859e51","fields":{"slug":"/jc19/"},"frontmatter":{"title":"교착상태와 해결 방법"}}}]},"previous":{"fields":{"slug":"/jc18/"},"frontmatter":{"title":"상호배제와 동기화 기법"}},"next":{"fields":{"slug":"/jc20/"},"frontmatter":{"title":"물리주소, 논리주소 그리고 메모리 분할 방식"}}},"pageContext":{"id":"b19e8b85-ca19-51c2-a8f6-bef465859e51","series":"프로세스 동기화","previousPostId":"0684370e-6b4b-5b53-888f-57b7af8420b0","nextPostId":"e200cc99-336c-511d-886c-4104f5b4002e"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc2/page-data.json b/public/page-data/jc2/page-data.json new file mode 100755 index 0000000..aa8010c --- /dev/null +++ b/public/page-data/jc2/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc2/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"206f7f4e-13af-5568-b55d-4f56ccf6f27d","excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","html":"

CPU 스케줄링

\n
\n

CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n
모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다.

\n

CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n

\n

CPU 스케줄링 원칙

\n
\n

CPU는 스케줄링을 하면서 두가지 원칙을 중요시 하게 됩니다.\n

\n
    \n
  1. 공정함: 특정 프로세스 실행이 무한정 대기하지 않도록 기간을 보장합니다.
  2. \n
  3. 우선순위: 우선순위가 높은 작업에 우선권을 제공 합니다.
  4. \n
\n
\n

CPU 스케줄링 평가 기준

\n
\n

CPU는 객관적인 스케줄링을 위해 아래와 같은 평가 기준을 사용합니다.

\n
\n
    \n
  1. CPU 사용률 - CPU가 작업을 수행하는데 사용하는 시간의 비율
  2. \n
  3. 처리량 - 시스템이 단위 시간당 완료할 수 있는 작업의 양
  4. \n
  5. 응답 시간 - 시스템이 사용자의 요청에 반응하여 첫 번째 응답을 생성하기 시작하는데 걸리는 시간
  6. \n
  7. 대기 시간 - 프로세스가 실행되기 위해 CPU를 할당받아 준비 상태에서 대기하는 시간의 총합
  8. \n
  9. 처리 시간 - 특정 작업이 시작되었을 때부터 그 작업이 완전히 끝나는데 걸리는 시간의 총합
  10. \n
","frontmatter":{"title":"CPU 스케줄링, 시스템 자원 관리","date":"September 05, 2025","update":"September 05, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/jc2/","readingTime":{"minutes":2.05}}},"seriesList":{"edges":[{"node":{"id":"a856e34f-f9a9-5164-8fb5-befe1aa43bcd","fields":{"slug":"/jc1/"},"frontmatter":{"title":"운영체제의 역할과 커널의 기능"}}},{"node":{"id":"206f7f4e-13af-5568-b55d-4f56ccf6f27d","fields":{"slug":"/jc2/"},"frontmatter":{"title":"CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"3b1392c5-94e5-5f2b-889c-04d05775956f","fields":{"slug":"/jc3/"},"frontmatter":{"title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"c96ac712-ee44-5bd2-8318-3d771e986911","fields":{"slug":"/jc4/"},"frontmatter":{"title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"6fead90c-3201-5834-b766-1a6625757a89","fields":{"slug":"/jc5/"},"frontmatter":{"title":"인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"1460ba25-d467-50f1-873c-d36498b197b7","fields":{"slug":"/jc6/"},"frontmatter":{"title":"동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":{"fields":{"slug":"/jc1/"},"frontmatter":{"title":"운영체제의 역할과 커널의 기능"}},"next":{"fields":{"slug":"/jc3/"},"frontmatter":{"title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},"pageContext":{"id":"206f7f4e-13af-5568-b55d-4f56ccf6f27d","series":"운영체제 기본 개념","previousPostId":"a856e34f-f9a9-5164-8fb5-befe1aa43bcd","nextPostId":"3b1392c5-94e5-5f2b-889c-04d05775956f"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc20/page-data.json b/public/page-data/jc20/page-data.json new file mode 100755 index 0000000..ff060aa --- /dev/null +++ b/public/page-data/jc20/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc20/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"e200cc99-336c-511d-886c-4104f5b4002e","excerpt":"물리주소와 논리주소 메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다.\n이 저장된 메모리의 데이터를 CPU 혹은 실행중인 프로그램이 읽어 실행하게 됩니다. 해당 그림은 두가지 관점으로 주소를 나누고 사용하는 방식을 그림으로 나타낸 것입니다. 왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요? 이유는 메모리에 저장되어 있는 정보는 변…","html":"

물리주소와 논리주소

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다.\n이 저장된 메모리의 데이터를 CPU 혹은 실행중인 프로그램이 읽어 실행하게 됩니다.

\n

해당 그림은 두가지 관점으로 주소를 나누고 사용하는 방식을 그림으로 나타낸 것입니다.

\n

왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요?

\n
\n

이유는 메모리에 저장되어 있는 정보는 변화가 빠르고 이를 시시각각 알기어렵기 때문에

\n
\n

가령 프로그램이 새롭게 실행될때, 삭제 될때 혹은 같은 프로그램일지라도 실행될때마다 실행되는 주소가 다르기 때문입니다.

\n

그렇기때문에 주소를 두가지 관점으로 나눠서 사용하게 됩니다.

\n
\n

물리주소란 실제로 정보가 저장된 하드웨어상 주소를 의미합니다.

\n
\n
\n

논리주소란 실행중인 프로그램에 부여된 0번지부터 시작되는 주소를 의미합니다.

\n
\n

여기서 주의할점은 논리주소는 0번지 부터 시작하는 논리적 주소이기 때문에, 고유성이 없습니다. 하지만 물리주소는\n하드웨어상 주소기 때문에 고유성이 있습니다.

\n
\n
\n

메모리 할당 방식

\n
\n

메모리 할당이란 주기억 장치에 프로세스를 저장하는 과정입니다.\n이러한 과정은 크게 두가지로 나누어집니다.

\n
    \n
  1. 연속 할당
  2. \n
  3. 불연속 할당
  4. \n
\n
\n

연속할당

\n
\n

연속 할당은 프로세스가 연속된 메모리 영역에 할당되는 방법을 말합니다.\n각 프로세스는 연속적인 메모리 주소 범위 내에 위치하게 됩니다. 이렇게 연속할당을 하게 되면\n빈공간보다 프로세스 공간이 더 작은 경우가 있는데 이러한 현상을 단편화라고 합니다.

\n

연속할당의 종류로는 고정 크기 파티셔닝, 가변 크기 파티셔닝이 있습니다.

\n
\n

고정 크기 파티셔닝

\n

고정 크기 파티셔닝은 메모리를 고정된 크기의 파티션으로 나누어 각 파티션에 프로세스를 할당하는 방식입니다.\n예를들어, 모든 파티션을 10MB로 설정하고 파티션마다 프로세스를 할당하는 방식을 사용할 수 있습니다.

\n

이러한 방식은 모든 프로세스가 지정한 파티션 크기만큼 떨어지는것이 아니기 떄문에 효율적이지 못한 단점이 있습니다.

\n
\n

가변 크기 파티셔닝

\n

가변 크기 파티셔닝은 파티션의 크기를 유동적으로 조절하는 메모리 할당 방식입니다.\n이러한 방식은 고정 크기 파티셔닝보다는 효율적이지만, 메모리 공간에 어떤 프로세스를 저장해야 할지 결정하는게\n복잡합니다.

\n
\n
\n

불연속 할당

\n
\n

불연속 할당은 한 프로세스를 메모리 여러 곳에 분산 저장하는 방법입니다. 페이징, 세그멘테이션 이 있습니다.

\n
\n

페이징

\n

페이징은 프로세스의 주소 공간을 페이지라는 동일한 크기의 구획으로 나누고, 주기억 장치도 페이지와 동일한 크기의\n프레임이라는 구획으로 나눕니다. 이후 한 페이지를 한 프레임에 적재하는 방식입니다.

\n

자세한 내용은 이후에 다루게 됩니다.

\n
\n

세그멘테이션

\n

프로세스의 주소공간을 세그먼트라는 단위로 나누어 주기억 장치에 적재합니다.\n프로세스는 코드, 데이터, 스택 등으로 구성되기 때문에 각각을 한 세그먼트로 나누어서 메모리에 적재합니다.

\n

이 과정에서, base주소와, limit주소를 이용하여 프로세스가 자신에게 할당된 메모리 영역만 사용하게 합니다.

\n
\n

출처

\n
\n

이미지 출처

","frontmatter":{"title":"물리주소, 논리주소 그리고 메모리 분할 방식","date":"September 23, 2025","update":"September 23, 2025","tags":["운영체제"],"series":"가상메모리, 메모리분할"},"fields":{"slug":"/jc20/","readingTime":{"minutes":5.57}}},"seriesList":{"edges":[{"node":{"id":"e200cc99-336c-511d-886c-4104f5b4002e","fields":{"slug":"/jc20/"},"frontmatter":{"title":"물리주소, 논리주소 그리고 메모리 분할 방식"}}},{"node":{"id":"80145e53-099c-5767-895e-44103f0a9232","fields":{"slug":"/jc21/"},"frontmatter":{"title":"메모리 배치기법 그리고 단편화에 대해"}}},{"node":{"id":"852135ec-8164-5227-aa26-11eb554f0357","fields":{"slug":"/jc22/"},"frontmatter":{"title":"페이징"}}},{"node":{"id":"a8a31830-eb16-5010-9ca4-b9d9c7b0d4bc","fields":{"slug":"/jc23/"},"frontmatter":{"title":"요구페이징을 잘 수행하기 위해서 필요한 것들"}}}]},"previous":{"fields":{"slug":"/jc19/"},"frontmatter":{"title":"교착상태와 해결 방법"}},"next":{"fields":{"slug":"/jc21/"},"frontmatter":{"title":"메모리 배치기법 그리고 단편화에 대해"}}},"pageContext":{"id":"e200cc99-336c-511d-886c-4104f5b4002e","series":"가상메모리, 메모리분할","previousPostId":"b19e8b85-ca19-51c2-a8f6-bef465859e51","nextPostId":"80145e53-099c-5767-895e-44103f0a9232"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc21/page-data.json b/public/page-data/jc21/page-data.json new file mode 100755 index 0000000..f1983ed --- /dev/null +++ b/public/page-data/jc21/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc21/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"80145e53-099c-5767-895e-44103f0a9232","excerpt":"연속 메모리 할당 연속 메모리 할당이란 메모리에 프로세스가 그림처럼 연속적으로 배치되는 상황을 가정합니다. 프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다. 이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 스와핑과 관련이 있습니다. 스와핑이란? 메모리는 실행시킬 프로세스를 적재하게 됩니다. 하…","html":"

연속 메모리 할당

\n
\n

\n \n \n \n \n \n
img.png
\n

\n

연속 메모리 할당이란 메모리에 프로세스가 그림처럼 연속적으로 배치되는 상황을 가정합니다.

\n

프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다.

\n

이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 스와핑과 관련이 있습니다.

\n
\n

스와핑이란?

\n
\n

메모리는 실행시킬 프로세스를 적재하게 됩니다. 하지만, 이런 프로세스들 중에 현재 실행되지 않는 프로세스는 처리해줘야 합니다.\n메모리 리소스가 한정적이기 때문입니다.

\n

여기서 말하는 실행되지 않는 프로세스의 예시는 I/O작업, 오랫동안 사용되지 않는 프로세스가 이에 해당합니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

그렇다면 이러한 프로세스를 메모리에서 처리하는 방법이 필요한데 그 방법이 스와핑 입니다.

\n

스와핑은, 두가지 행위를 통해서 수행할 수 있습니다.

\n
\n

스왑 아웃: 현재 실행되지 않는 프로세스가 메모리에서 스왑 영역으로 옮겨지는 것 (메모리 -> 스왑 영역)

\n
\n
\n

스왑 인: 스왑영역에 있던 프로세스가 다시 메모리로 옮겨지는 것 (스왑 영역 -> 메모리)

\n
\n

또한 메모리에서 보조기억장치로 옮겨질때 스왑영역으로 프로세스를 옮겨두는데 그 영역을 스왑 영역이라고 합니다.

\n
\n
\n

메모리 할당 방식

\n
\n

프로세스는 메모리 속 비어있는 공간에 적재되어야 합니다. 비어 있는 메모리 공간에 프로세스를 연속적으로 할당하기 위해\n세가지 방법을 고려할 수 있습니다.

\n
    \n
  1. 최초 적합(first fit)
  2. \n
  3. 최적 적합(best fit)
  4. \n
  5. 최악 적합(worst fit)
  6. \n
\n

각방식을 아래 예시를 통해 들어보려 합니다.

\n

프로세스 A,B,C는 이미 적재되어있고, 빈 공간 A,B,C가 있습니다. 앞으로 적재할 프로세스는 20MB크기를 가지고 있으며\n적재 방식에 따라 이를 어디에 적재할지 달라지게 됩니다.

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

최초 적합

\n
\n

최초 적합은 메모리 내의 빈 공간을 순서대로 검색하다가 적재할 수 있는 공간을 발견하면 그 공간에 프로세스를 배치하는 방식입니다.\n이전 그림에서 운영체제가 빈공간 A,B,C 순서대로 검색을 하였다면 가장 먼저 검색된 A 빈공간에 적재되는 방식입니다.

\n

\n \n \n \n \n \n
img.png
\n

\n

적재후 모습은 그림과 같으며 해당 방식은 검색을 최소화 하며 빠른 할당을 가능하게 하는 장점이 있습니다.\n하지만, 이후에 보게 될 외부 단편화가 생길 가능성이 높아지게 됩니다.

\n
\n
\n

최적 적합

\n
\n

최적 적합은 운영체제가 빈공간을 모두 검색한 후 프로세스가 적재될 수 있는 공간 중 가장 작은 공간에 프로세스를\n배치하는 방식입니다.\n이전 그림에서는 빈 공간 C가 가장 적합한 크기를 가진 공간이기 때문에 그곳에 적재 됩니다.

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

적재후 모습은 그림과 같으며 해당 방식은 적재할 프로세스 크기를 고려한 방식이기 때문에 외부 단편화를\n최소화 할 수 있다는 장점이 있지만, 모든공간을 검색하는 행위가 오버헤드를 발생시키기 때문에 느려집니다.

\n
\n
\n

최악 적합

\n
\n

최악 적합은 운영체제가 빈 공간을 모두 검색한 후, 가장 큰 공간에 프로세스를 적재하는 방식입니다.

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

적재 후 모습은 가장 빈공간의 크기가 큰 B에 적재되는 것을 확인할 수 있습니다. 이러한 방식은\n외부 단편화의 발생 빈도도 크며, 모든 공간을 검색한다는 비효율적인 측면도 가지고 있습니다.

\n
\n

지금까지 외부 단편화라는 용어가 단점으로 설명했습니다.\n그렇다면, 외부 단편화는 어떠한 문제일까요?

\n
\n

단편화

\n
\n

단편화는 크게 두가지로 나눌 수 있습니다.

\n
    \n
  1. 내부 단편화
  2. \n
  3. 외부 단편화
  4. \n
\n
\n

내부 단편화

\n

\n \n \n \n \n \n
img.png
\n

\n

내부 단편화 문제는 이전 최초 적합 사례에서 볼 수 있습니다.\n빈공간A의 크기는 30MB인데 적재한 프로세스는 20MB입니다. 이런경우 10MB의 빈공간이 생기게 되고 이러한 비어있는\n공간을 내부 단편화가 발생했다고 표현합니다.

\n
\n

외부 단편화

\n

\n \n \n \n \n \n
img.png
\n

\n

외부 단편화 문제는 이전 최초 적합 사례를 이어서 설명하겠습니다.\n현재 그림속 비어있는 공간은 80MB입니다. 하지만 해당 공간에 80MB크기의 프로세스를 적재할 수 없습니다.\n이유는, 빈 공간이 연속적인것이 아닌 프로세스C에 의해 끊어져있기 때문입니다.

\n

이처럼, 프로세스를 할당하기 어려울 만큼 작은 메모리 공간들로 인해 메모리가 낭비되는 현상을 지칭합니다.

\n

이러한 외부 단편화를 해결할 수 있는 대표적인 방안은 메모리를 압축하는 방법이 있습니다.

\n
\n

압축

\n
\n

압축이란 흩어져 있는 빈 공간들을 하나로 모으는 방식으로 메모리 내에 저장된 프로세스를 재배치 시켜 빈 공간을\n하나의 큰 빈 공간으로 만드는 방법입니다.

\n

이러한 방식은 단점이 있는데, 메모리의 빈공간을 모으는 작업은 시스템을 중지 시킨다는 문제가 있습니다.\n또한, 메모리를 옮기는 작업이 큰 오버헤드를 만들고, 최적화 방법에 대한 정답을 고르기가 어렵습니다.

\n

출처

\n
\n

이미지 출처

","frontmatter":{"title":"메모리 배치기법 그리고 단편화에 대해","date":"September 24, 2025","update":"September 24, 2025","tags":["운영체제"],"series":"가상메모리, 메모리분할"},"fields":{"slug":"/jc21/","readingTime":{"minutes":8.11}}},"seriesList":{"edges":[{"node":{"id":"e200cc99-336c-511d-886c-4104f5b4002e","fields":{"slug":"/jc20/"},"frontmatter":{"title":"물리주소, 논리주소 그리고 메모리 분할 방식"}}},{"node":{"id":"80145e53-099c-5767-895e-44103f0a9232","fields":{"slug":"/jc21/"},"frontmatter":{"title":"메모리 배치기법 그리고 단편화에 대해"}}},{"node":{"id":"852135ec-8164-5227-aa26-11eb554f0357","fields":{"slug":"/jc22/"},"frontmatter":{"title":"페이징"}}},{"node":{"id":"a8a31830-eb16-5010-9ca4-b9d9c7b0d4bc","fields":{"slug":"/jc23/"},"frontmatter":{"title":"요구페이징을 잘 수행하기 위해서 필요한 것들"}}}]},"previous":{"fields":{"slug":"/jc20/"},"frontmatter":{"title":"물리주소, 논리주소 그리고 메모리 분할 방식"}},"next":{"fields":{"slug":"/jc22/"},"frontmatter":{"title":"페이징"}}},"pageContext":{"id":"80145e53-099c-5767-895e-44103f0a9232","series":"가상메모리, 메모리분할","previousPostId":"e200cc99-336c-511d-886c-4104f5b4002e","nextPostId":"852135ec-8164-5227-aa26-11eb554f0357"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc22/page-data.json b/public/page-data/jc22/page-data.json new file mode 100755 index 0000000..5e48b7f --- /dev/null +++ b/public/page-data/jc22/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc22/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"852135ec-8164-5227-aa26-11eb554f0357","excerpt":"연속 할당의 문제점 연속적 할당의 대표적인 문제점은 외부 단편화가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해\n필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다. 이러한 문제를 해결하기 위해서는 불연속 할당 방식 중 대표적인 페이징기법을 사용할 수 있습니다. 페이징이란? 페이징 기법은 프로세스를 일정한 단위로 자릅니다. …","html":"

연속 할당의 문제점

\n
\n

연속적 할당의 대표적인 문제점은 외부 단편화가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해\n필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다.

\n

이러한 문제를 해결하기 위해서는 불연속 할당 방식 중 대표적인 페이징기법을 사용할 수 있습니다.

\n
\n
\n

페이징이란?

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

페이징 기법은 프로세스를 일정한 단위로 자릅니다. 또한 프로세스가 들어갈 메모리 공간 또한 일정한 단위로 자릅니다.

\n

여기서 프로세스를 일정한 단위로 자르면 일정한 논리 주소 공간이 생기는데 이것을 페이지라고 부르며,\n일정한 단위로 잘린 메모리 물리 주소 공간프레임이라고 부르게 됩니다.

\n

여기서 프레임, 페이지의 일정한 단위는 동일한 크기로 자르게 됩니다.

\n

이렇게 만들어진 페이지프레임에 할당하는 가상 메모리 관리 기법을 페이징기법이라고 부르게 됩니다.

\n

이렇게 일정한 크기를 정하고 불연속 할당을 수행하면 외부 단편화 문제를 줄일 수 있습니다.

\n
\n

페이징에서 스와핑

\n

\n \n \n \n \n \n
img.png
\n

\n

페이징에서도 이전과 마찬가지로 스와핑이 사용됩니다. 차이가 있다면 기존 연속 할당 방식 스와핑은\n프로세스 전체가 스왑영역으로 넘어가지만, 페이징 스와핑은 사용하지 않는 특정 페이지만 스왑아웃\n시킬 수 있습니다.

\n

이러한 방식은 이후 가상메모리 방식을 사용하는데 핵심이 됩니다.

\n
\n

페이지 테이블

\n
\n

불연속 할당 방식에는 실행순서에 대한 문제가 하나 있습니다.\n연속적 할당 방식에서는 실행순서를 CPU에게 알려줄 필요가 없습니다. 왜냐하면 실제로 물리 메모리에 연속적으로\n프로세스에 대한 정보가 있기 때문에 순서대로 실행시키면 되기 때문입니다.

\n

하지만, 불연속 할당은 상황이 다릅니다. 메모리상 프로세스에 대한 정보가 연속적이지 않기 떄문에\n이를 실행시키는 CPU입장에서는 어떤 프로세스를 실행시켜야 할지 알기 어렵습니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

이를 해결하기 위해서 페이지 테이블이란것을 사용합니다.

\n

페이지 테이블페이지 번호, 프레임 번호를 짝지어 줍니다. 그렇게 되면 CPU입장에서는\n페이지 번호만 알고있다면 페이지 테이블을 통해 프레임으로 접근이 가능하기 때문입니다.

\n

페이지 테이블은 프로세스마다 각자의 페이지 테이블을 가지게 됩니다.

\n
\n
\n

페이지 테이블 베이스 레지스터(PTBR)

\n
\n

페이지 테이블은 프로세스마다 가지고 있고, 이는 메모리에 저장됩니다.

\n

하지만, CPU 입장에서는 결국 페이지 테이블의 위치를 알아야 합니다. 이러한 기능을 수행하는게\nCPU내의 존재하는 PTBR입니다.

\n

PTBRCPU내에 존재하고 페이지 테이블의 위치를 기록합니다.

\n

\n \n \n \n \n \n
img.png
\n

\n

해당 그림처럼 특정 프로세스 작업을 수행하기 위해서 CPU는 해당 PTBR내부 프로세스의 페이지 테이블을\n조회합니다. 이후 메모리내부 해당 페이지 테이블 주소로 넘어가서 특정 프로세스의 페이지 까지 접근하게 됩니다.

\n
\n
\n

비효율적인 접근

\n
\n

이전 페이지 테이블을 참조하는데 한가지 문제가 있습니다.

\n

CPU페이지 테이블로 접근하고, 해당 값들을 통해 실제 페이지로 접근합니다.

\n

즉, 하나의 조회에 대해 두가지 접근을 수행하게 됩니다. 이러한 방식은 비효율적입니다.\n그렇기 때문에 캐싱기능을 통해 이를 해결하고 이러한 기능을 수행하는게 TLB입니다.

\n
\n

TLB(Translation Lookaside Buffer)

\n
\n

\n \n \n \n \n \n
img.png
\n

\n

TLB는 CPU 곁에 존재하며 이는 페이지 테이블에 대한 캐시 메모리입니다.\n참조 지역성에 근거해 주로 최근에 사용된 페이지 위주로 가져와서 저장합니다.

\n

여타한 캐싱 기능과동일하게 리소스가 TLB를 통해서 나오게 되면, 히트했다. 그것이 아니라면\n미스했다 라고 표현합니다.

\n
\n
\n

페이징에서의 주소 변환

\n
\n

특정 주소에 접근하기 위해서는 두가지 관점의 정보가 필요하게 됩니다.

\n
    \n
  1. 어떤 페이지 혹은 프레임에 접근하고 싶은지
  2. \n
  3. 접근하려는 주소가 그 페이지 혹은 프레임으로부터 얼마나 떨어져 있을지
  4. \n
\n
\n

이중에서 1번은 기존 페이지 번호를 통해서 해결할 수 있습니다.\n하지만, 2번의 말은 조금 애매하게 들리는데 이를 풀어서 설명하면,\n하나의 주소내에서도 논리 혹은 물리주소에 따른 순차적인 주소가 있습니다.

\n

n번지, n+1번지, n+2번지.... 처럼 세부적인 지점을 의미합니다.

\n

1번 주소를 통해서 페이지혹은 프레임에 접근한다면 그 중 명확한 지점을 식별해야 하기 때문에

\n

페이징 시스템에서는 페이지번호, 변위를 이용합니다.

\n

자세한 예시는 아래 그림을 통해서 하겠습니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

페이지, 페이지 테이블, 프레임을 나타내는 그림입니다. 이러한 그림은 특정 페이지에 접근하기 위해\n페이지 테이블을 참조하고 프레임 번호를 얻어 실제 메모리 프레임에 접근하는 시퀀스 입니다.

\n

만약 CPU가 5번페이지에 변위가 2인 곳에 접근하려고 하면 10번지로 접근하게 될것입니다.

\n
    \n
  1. 5번 페이지는 1번 프레임에 있다.
  2. \n
  3. 1번 프레임의 시작 번지수는 8번지이다
  4. \n
  5. 8번지에 변위 2를 더해서 최종주소는 10이 된다.
  6. \n
\n

여기서 주의 할점은, 논리주소의 변위를 최종 물리 주소상 프레임 번지에 더하였다는 것입니다.

\n
\n

이말은, 논리주소의 변위 == 물리주소의 변위 입니다.

\n
\n

이것이 가능한 이유는 처음 페이징 방식을 사용할때 페이지와 프레임 변환과정에서 특정 크기로 나누게 되고,\n그 간격이 같기 때문에 논리주소의 변위랑 물리주소의 변위는 같다는 결론이 나옵니다.

\n
\n
\n

페이지 테이블 엔트리

\n
\n

페이지 테이블 엔트리는 페이지 테이블 row를 지칭하는 단위입니다.

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

지금까지는 이러한 페이지 테이블에는 페이지 번호, 프레임 번호만 존재 한다고 설명했습니다.\n하지만, 다른 중요한 정보들도 있습니다.

\n
    \n
  1. 유효 비트
  2. \n
  3. 보호 비트
  4. \n
  5. 참조 비트
  6. \n
  7. 수정 비트
  8. \n
\n
\n

유효 비트

\n

유효비트는 해당 페이지에 접근 가능한지 여부를 알려줍니다. 대표적으로 접근 불가능 한 경우는\n스와핑으로 인한 해당 페이지스왑영역으로 들어간 경우입니다.

\n

이러한 경 페이지 폴트라는 예외가 발생하며, 하드웨어 인터럽트 처럼 처리 됩니다.

\n
    \n
  1. CPU는 기존 작업 내역을 백업합니다.
  2. \n
  3. 페이지 폴트 처리 루틴을 실행합니다.
  4. \n
  5. 페이지 처리 루틴은 원하는 페이지를 메모리로 가져온 뒤 유효 비트를 1로 변경해줍니다.
  6. \n
  7. 페이지 폴트를 처리했다면 이제 CPU는 해당 페이지에 접근할 수 있게 됩니다.
  8. \n
\n
\n

보호 비트

\n

보호비트는 페이지 보호 기능을 위해 존재합니다. 리눅스의 읽기 쓰기 권한을 생각하면 됩니다.\n해당 페이지가 읽기 전용 페이지라면 보호비트는 0을 나타내고, 읽고 쓰기가 가능하다면 1을 나타냅니다.

\n
\n

참조 비트

\n

CPU가 접근한적 있는지 여부를 나타냅니다. 참조된 비트라면 1을 나타내며, 그렇기 않다면 0으로 유지됩니다.

\n
\n

수정 비트

\n

해당 페이지에 데이터를 쓴 적이 있는 여부를 나타냅니다. 수정 여부를 확인해야 하는 이유는 스와핑 떄문입니다.\n만약 CPU가 페이지에 대한 내용을 수정했다면, 스와핑 과정에서 보조 기억장치에 있는 데이터 또한 수정해야 하기 때문입니다.

\n

출처

\n
\n

이미지 출처

","frontmatter":{"title":"페이징","date":"September 25, 2025","update":"September 25, 2025","tags":["운영체제"],"series":"가상메모리, 메모리분할"},"fields":{"slug":"/jc22/","readingTime":{"minutes":12.045}}},"seriesList":{"edges":[{"node":{"id":"e200cc99-336c-511d-886c-4104f5b4002e","fields":{"slug":"/jc20/"},"frontmatter":{"title":"물리주소, 논리주소 그리고 메모리 분할 방식"}}},{"node":{"id":"80145e53-099c-5767-895e-44103f0a9232","fields":{"slug":"/jc21/"},"frontmatter":{"title":"메모리 배치기법 그리고 단편화에 대해"}}},{"node":{"id":"852135ec-8164-5227-aa26-11eb554f0357","fields":{"slug":"/jc22/"},"frontmatter":{"title":"페이징"}}},{"node":{"id":"a8a31830-eb16-5010-9ca4-b9d9c7b0d4bc","fields":{"slug":"/jc23/"},"frontmatter":{"title":"요구페이징을 잘 수행하기 위해서 필요한 것들"}}}]},"previous":{"fields":{"slug":"/jc21/"},"frontmatter":{"title":"메모리 배치기법 그리고 단편화에 대해"}},"next":{"fields":{"slug":"/jc23/"},"frontmatter":{"title":"요구페이징을 잘 수행하기 위해서 필요한 것들"}}},"pageContext":{"id":"852135ec-8164-5227-aa26-11eb554f0357","series":"가상메모리, 메모리분할","previousPostId":"80145e53-099c-5767-895e-44103f0a9232","nextPostId":"a8a31830-eb16-5010-9ca4-b9d9c7b0d4bc"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc23/page-data.json b/public/page-data/jc23/page-data.json new file mode 100755 index 0000000..07594d7 --- /dev/null +++ b/public/page-data/jc23/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc23/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"a8a31830-eb16-5010-9ca4-b9d9c7b0d4bc","excerpt":"서론 지금까지 가상 메모리를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다.\n이러한 행위는 한정된 메모리를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다. 그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다. 불필요한 페이지를 선별 후 스왑 아웃 한다. 프로세스에게 적절한 프레임을 할당한다…","html":"

서론

\n
\n

지금까지 가상 메모리를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다.\n이러한 행위는 한정된 메모리를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다.

\n

그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다.

\n
    \n
  1. 불필요한 페이지를 선별스왑 아웃 한다.
  2. \n
  3. 프로세스에게 적절한 프레임을 할당한다.
  4. \n
\n

각각 페이지 교체 알고리즘, 프레임 할당이라고 부릅니다.

\n

또한, 이러한 작업은 요구 페이징(demand paging) 이라는 작업을 더 효율적으로 할 수 있게 돕습니다.

\n

이 글은 요구 페이징에 대해서 알아보고, 요구 페이징이 안정적으로 작동하기 위해 필연적인 페이지 교체 알고리즘과, 프레임 할당을 설명합니다.

\n
\n
\n

요구 페이징(demand paging)

\n
\n

프로세스를 메모리에 적재할 떄 처음부터 모든 페이지를 적재하지 않고 필요한 페이지만을 메모리에 적재하는 방식을\n요구 페이징이라고 부릅니다.

\n

요구 페이징은 다음과 같은 플로우로 진행됩니다.

\n
    \n
  1. CPU가 특정 페이지에 접근하는 명령어를 내린다.
  2. \n
  3. 페이지가 메모리에 존재하면 유효비트 1을 나타내며 해당 프레임에 접근한다.
  4. \n
  5. 존재 하지 않는다면 유효비트 0을 나타내며 페이지 폴트가 발생한다.
  6. \n
  7. 페이지 폴트가 발생하면 해당 페이지를 메모리로 적재하고 유효비트를 1로 설정한다.
  8. \n
  9. 1번을 다시 시행한다.
  10. \n
\n

이러한 요구 페이징은 필요한 페이지만 그때그때 불러서 적재 후 사용한다는 의미를 나타냅니다.

\n

요구 페이징을 안정적으로 수행하기 위해서는 크게 두가지를 고려해야 합니다.\n첫번째는, 요구 페이징은 메모리 기준 Input작업 입니다.\n그렇다면 반대로 Output작업도 필요하게 됩니다.

\n

왜냐하면 메모리는 한정되고 상대적으로 덜 필요한 페이지를 스왑아웃하는 작업도 필요하기 때문입니다.

\n

이러한 방식을 페이지 교체 라고 부르며, 그중 여러가지 방식이 있기 때문에 페이지 교체 알고리즘으로 분류하고 명명합니다.

\n

두번째는, 한정된 프레임을 잘 배분하는 것으로 스왑 아웃자체를 줄일 수 있기 때문에 프레임 할당 또한\n요구 페이징을 수행하기 위해 중요합니다.

\n
\n
\n

페이지 교체 알고리즘

\n
\n

페이지 교체 알고리즘은 스왑 아웃할 페이지를 선별하는 알고리즘입니다.\n그렇기 때문에 어떤 선별 기준에 따라 알고리즘을 나누게 됩니다.

\n

일반적으로 기준페이지 폴트 발생 비율입니다. 페이지 폴트는 보조기억장치로 부터\n정보를 가져와서 메모리로 할당하여 그 정보를 불러와야 하는 비효율적인 시퀀스를 가지고 있습니다.\n이러한 페이지 폴트 발생 비율이 적은 교체 알고리즘을 좋다고 평가합니다.

\n

그리고 페이지 폴트 횟수페이지 참조열을 통해서 진행합니다.

\n

가령,

\n
\n

2 2 2 3 5 5 5 3 3 7

\n
\n

이라는 페이지 참조가 발생한다면 페이지 참조열은 여기서 연속된 중복을 제거한 순서입니다.

\n
\n

2 3 5 3 7

\n
\n

이 해당 순서에 페이지 참조열이 됩니다. 이렇게 중복을 제거하는 이유는 연속된 참조는 페이지 폴트대상이\n아니기 때문입니다.

\n
\n
\n

FIFO 페이지 교체 알고리즘

\n

FIFO 페이지 교체 알고리즘은 이름 그대로 먼저 들어온 페이지를 먼저 내보내는 방식입니다.

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

해당 그림을 통해 설명하면 2,3,1 번의 순서대로 프레임에 쌓이게 되며 마지막 1번 페이지가 적재 된 이후에는\n프레임이 가득차게 됩니다. 이후 3번은 이미 적재된 페이지이기 때문에 넘어갑니다.

\n

5번 페이지가 적재 되는 시점에 프레임은 가득 차있고, 5번페이지는 적재 되어있지 않기 때문에 선별교체하는\n작업이 필요합니다.

\n

여기서 FIFO방식은 가장 먼저들어온 페이지를 내보낸다라고 설명드린것처럼 처음들어온 2페이지 스왑아웃 시키게 됩니다.\n빈 공간에 필요한 5페이지를 넣게 됩니다.

\n

이렇게 먼저 들어온 페이지를 먼저 내보내는것을 FIFO 교체 알고리즘이라고 명명합니다.

\n

하지만 이러한 방식에는 큰 단점이 있는데, 먼저 들어온 페이지가 실행 내내 사용 될 수도 있습니다.\n즉, 먼저 들어왔다고 해서 교체에 대상이 되기는 합당한 이유가 아니기 때문입니다.

\n
\n
\n

2차 기회 페이지 교체 알고리즘

\n
\n

해당 알고리즘은 FIFO방식을 개선한 알고리즘 입니다. 이름 처럼 한번의 기회를 더 주는 방식입니다.\n두가지 케이스가 있습니다. 기본적으로 가장 오래된 페이지를 스왑 아웃한다는 방식은 같습니다.\n만약 스왑 아웃 시점이 오게 되면, 해당 참조 비트를 확인합니다.

\n

CPU에 의해서 참조 된적이 있다면, 해당 참조 비트를 0으로 바꾸고 적재 시간을 현재로 변경하며,\n참조 비트가 0이라면 오래되면서 참조된적도 없기 떄문에 바로 스왑 아웃 시켜버립니다.

\n
\n
\n

최적 페이지 교체 알고리즘

\n
\n

최적 페이지 교체 방식은 이름그대로 최적의 방안을 찾는 알고리즘입니다.\n미래를 통해 오랫동안 사용되지 않을 페이지를 스왑아웃 시키면서 문제를 해결합니다.

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

해당 그림을 통해 설명하면 5번 페이지를 요청할때 페이지 폴트가 발생하고 그 과정에서 이후 미래를 고려해서\n1번이 사용되지 않는다고 판단해 1번을 스왑 아웃하는 방식입니다.

\n

해당 알고리즘은 페이지 폴트가 가장 낮습니다.\n그렇지만, 현실적인 구현이 어렵습니다. 미래를 예측하는건 어려운 작업입니다. 그렇기 떄문에 현실적으로 가능한\n알고리즘으로 여기기 보단, 페이지 폴트가 가장 낮다는 점을 고려하여 상대적인 성능 평가를 목적으로 사용합니다.

\n

다른 교체 알고리즘의 하한선으로 잡고 비교대상으로 쓰여집니다.

\n
\n
\n

LRU 페이지 교체 알고리즘 (Least Recently Used Page Algorithm)

\n
\n

해당 알고리즘은 최적 페이지 교체 알고리즘을 변형해 미래를 예측하는것이 아닌, 과거를 통해\n사용되지 않은 페이지를 스왑아웃하는 방식을 차용합니다.

\n

'최근에 사용되지 않은 페이지는 앞으로도 사용되지 않을 것이다' 라는 점을 토대로 구성됩니다.

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

페이지마다 마지막으로 사용한 시간을 토대로 최근에 가장 사용이 적었던 페이지를 교체합니다.\n해당 그림에서는 5번 페이지가 적재될 시기에 가장 오래 사용되지 않는 2스왑아웃 시키는것을\n알 수 있습니다.

\n
\n
\n

스래싱과 프레임 할당

\n
\n

요구 페이징을 잘 수행하기 위해 페이지 폴트를 줄이는 방식을 이야기 했습니다.\n이러한 페이지 폴트를 줄이기 위해 교체 알고리즘을 적절하게 선택하는것이 중요하단것을 알게 되었습니다.

\n

하지만, 페이지 폴트를 발생시키는 이유에는 프레임 수의 한정이라는 문제가 있습니다.\n프레임이 무지막지 하게 많다면 모든 프로세스를 할당할 수 있을것이고, 그렇게 되면 스왑 아웃이 발생할 이유도 없을것입니다.

\n

그렇기 때문에 페이지 폴트의 발생을 줄이기 위해 적절하게 프레임을 할당하는 것또한, 중요합니다.

\n

역으로 자원을 효율적으로 사용하고, 가상메모리와 같은 기법을 사용하면서 페이징에 프로세스 실제 실행시간보다\n더큰 리소스를 사용하는 문제가 생길 수도 있습니다.

\n

이렇게 배보다 배꼽이 큰 상황, 플어서 이야기하면

\n
\n

페이징 시간이 프로세스 실제 실행보다 더 길어지는 상황

\n
\n

스레싱이라고 부르게 됩니다.

\n
\n

멀티 프로그래밍 정도

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

해당 그래프는 세로축 CPU 이용률, 가로축 메모리에 올라와 있는 프로세스 수를 나타냅니다.\n그래프에서 알 수 있듯이 프로세스수가 증가하면, CPU이용률 또한 증가합니다 하지만 일정 가로축을 넘어가면\nCPU이용률이 줄어드는 것을 알게 됩니다.

\n

즉, 프로세스가 너무 많이 발생하면 각 프로세스에 할당된 프레임이 부족하고 그런 문제로 인해 페이지 폴트가\n자주 발생하게 됩니다.

\n

CPU를 아무리 좋은것을 사용해도 메모리 공간이 부족하면 컴퓨터 성능이 안좋아지는 이유가 이런이유입니다.

\n
\n
\n

프레임 할당

\n
\n

스래싱의 근본적 이유는 각 프로세스가 필요로 하는 프레임이 부족하기 때문입니다. 그렇기 떄문에\n운영체제는 프레임을 적절하게 할당할 수 있어야 합니다.

\n

이러한 프레임 할당을 크게 두가지로 나눌수 있습니다.

\n
    \n
  1. 정적 할당 방식
  2. \n
  3. 동적 할당 방식
  4. \n
\n
\n
\n

정적 할당 방식

\n
\n

정적할당방식은 두가지로 나누어집니다.

\n
    \n
  1. 균등할당
  2. \n
  3. 비례할당
  4. \n
\n
\n

균등할당

\n

균등할당은 이름에서 알 수 있듯이 모든 프로세스에 프레임을 균등하게 할당하는 방식입니다.\n프로세스가 3개가 있고, 프레임이 300개가 있다면 각 프로세스는 100개의 프레임을 할당받게 됩니다.

\n

이러한 방식은 프로세스 크기도 각자 다른 상황에서 합리적이지 못한 선택입니다.

\n
\n

비례할당

\n

크기가 큰 프로세스에 더 많은 프레임을 할당하는 방식을 비례할당이라고 부릅니다.\n하지만 이러한 방식은 정적이라는 한계점을 가지고 있습니다.

\n

실제 프로세스를 실행해보면 크기와 상관없이 더 많은 프레임을 필요로 하거나 그렇지 않은 프로세스들이 존재합니다.\n이러한 문제 떄문에 비례할당도 합리적이라고 할 수 없습니다.

\n
\n

동적 할당 방식

\n
\n

동적할당방식에는 크게 두가지로 나누어집니다.

\n
    \n
  1. 작업 직합 모델(working set model)
  2. \n
  3. 페이지 폴트 빈도(PFF: page fault frequency)
  4. \n
\n
\n

작업 집합 모델

\n

작업 집합 모델에서는 '프로세스가 일정 기간 동안 참조한 페이지 집합'을 기억하며 빈번한 페이지 교체를 방지합니다.\n예를 들어 프로세스가 3초동안 20개의 페이지를 집중적으로 참조했다면 20개의 프레임을 할당하면 효율적일 것입니다.

\n

이렇게 실행 중인 프로세스가 일정 시간 동안 참조한 페이지의 집합을 작업 집합이라고 합니다.

\n
\n
\n

페이지 폴트 빈도

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

페이지 폴트 빈도 방식은 해당 그래프를 통해 이루어 집니다.\n가로축은 할당된 프레임을 나타내며 세로축은 페이지 폴트율을 나타냅니다.\n할당된 프레임은 적으면 페이지 폴트가 많이 발생하는 형상이 됩니다.

\n

이러한 그래프에서 상한과 하한을 정한다음 해당 적정 구간에 들어올 수 있도록 프레임을 할당해주는\n방식을 페이지 폴트 빈도방식이라고 합니다.

\n

출처

\n
\n

이미지 출처

","frontmatter":{"title":"요구페이징을 잘 수행하기 위해서 필요한 것들","date":"September 26, 2025","update":"September 26, 2025","tags":["운영체제"],"series":"가상메모리, 메모리분할"},"fields":{"slug":"/jc23/","readingTime":{"minutes":16.97}}},"seriesList":{"edges":[{"node":{"id":"e200cc99-336c-511d-886c-4104f5b4002e","fields":{"slug":"/jc20/"},"frontmatter":{"title":"물리주소, 논리주소 그리고 메모리 분할 방식"}}},{"node":{"id":"80145e53-099c-5767-895e-44103f0a9232","fields":{"slug":"/jc21/"},"frontmatter":{"title":"메모리 배치기법 그리고 단편화에 대해"}}},{"node":{"id":"852135ec-8164-5227-aa26-11eb554f0357","fields":{"slug":"/jc22/"},"frontmatter":{"title":"페이징"}}},{"node":{"id":"a8a31830-eb16-5010-9ca4-b9d9c7b0d4bc","fields":{"slug":"/jc23/"},"frontmatter":{"title":"요구페이징을 잘 수행하기 위해서 필요한 것들"}}}]},"previous":{"fields":{"slug":"/jc22/"},"frontmatter":{"title":"페이징"}},"next":null},"pageContext":{"id":"a8a31830-eb16-5010-9ca4-b9d9c7b0d4bc","series":"가상메모리, 메모리분할","previousPostId":"852135ec-8164-5227-aa26-11eb554f0357","nextPostId":null}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc3/page-data.json b/public/page-data/jc3/page-data.json new file mode 100755 index 0000000..e6f31d3 --- /dev/null +++ b/public/page-data/jc3/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc3/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"3b1392c5-94e5-5f2b-889c-04d05775956f","excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비스를 제공받을…","html":"

이중모드

\n
\n

운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다.

\n
\n

그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요?

\n
\n

이에 대한 답은 이중 모드 입니다.

\n
\n

\n \n \n \n \n \n
img.png
\n

\n
\n

위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드커널 모드로 나누어 사용하게 됩니다.

\n
\n

사용자 모드

\n

사용자 모드는 운영체제 서비스를 제공받을 수 없는 실행 모드입니다.\n
CPU가 해당 모드인 경우, 입출력 명령어와 같은 하드웨어 자원 접근 명령을 실행할 수 없습니다. 일반 프로그램은 기본적으로 사용자 모드로 실행됩니다.

\n
\n

커널 모드

\n

커널모드는 운영체제 서비스를 제공받을 수 있는 실행 모드로 커널 영역의 코드를 실행할 수 있습니다.\n
CPU가 커널 모드로 명령어를 실행하면 자원에 접근하는 명령어를 비롯한 모든 명령어를 실행할 수 있으며, 운영체제는 커널 모드로 실행됩니다.

\n
\n

요약 하자면 일반 응용프로그램은 평소에 사용자 모드를 통해서 실행 되다가 실제 운영체제의 코드를 실행하여야 하는 순간이 오면 커널 모드로 전환하여 실행하다가\n운영체제의 코드 실행 지점이 끝난다면 다시 사용자 모드로 전환되게 됩니다.

\n

이러한 방식으로 자원을 운영 체제로 하여금 독자적으로 관리할 수 있게 합니다.

\n
\n
\n

사용자 모드에서 어떻게 커널모드로 전환할까?

\n
\n

사용자 모드에서 커널모드로 전환하는 방식은 시스템 콜에 의해서 발생합니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

그림처럼 사용자 모드로 실행되는 프로그램이 자원에 접근해야 할때 운영체제에 커널 모드로 요청을 보내게 되고 이것을 시스템 콜이라고 부르게 됩니다.

\n

시스템 호출소프트 웨어 인터럽트에 속합니다. 이러한 특징 때문에 CPU시스템 호출을 처리하는 순서가 인터럽트 처리 순서와 비슷합니다.

\n

시스템 호출이 발생하면 지금까지의 작업을 백업 하고, 커널 영역 내의 호출 하여야 하는 코드를 실행 한 뒤 다시 돌아와 기존 프로그램을 계속 실행합니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

그림을 통해서 이해를 하게 되면,

\n
    \n
  1. 응용 프로그램은 일반적인 작업을 수행중 운영체제 코드를 실행 하여야 하는 작업에 도달하게 됩니다.
  2. \n
  3. 그러면 응용프로그램은 운영체제에게 자원 접근에 대한 시스템 콜을 날리게 된다.
  4. \n
  5. 현재 작업을 백업하게 됩니다.
  6. \n
  7. 이후 응용프로그램은 운영체제의 코드를 실행합니다.
  8. \n
  9. 작업이 끝나면 다시 사용자 영역으로 돌아와 멈춰둔 작업을 진행합니다.
  10. \n
\n

이런 세부적인 순서를 진행하게 됩니다.

\n

출처

\n

사진출처

","frontmatter":{"title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리","date":"September 06, 2025","update":"September 06, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/jc3/","readingTime":{"minutes":4.365}}},"seriesList":{"edges":[{"node":{"id":"a856e34f-f9a9-5164-8fb5-befe1aa43bcd","fields":{"slug":"/jc1/"},"frontmatter":{"title":"운영체제의 역할과 커널의 기능"}}},{"node":{"id":"206f7f4e-13af-5568-b55d-4f56ccf6f27d","fields":{"slug":"/jc2/"},"frontmatter":{"title":"CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"3b1392c5-94e5-5f2b-889c-04d05775956f","fields":{"slug":"/jc3/"},"frontmatter":{"title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"c96ac712-ee44-5bd2-8318-3d771e986911","fields":{"slug":"/jc4/"},"frontmatter":{"title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"6fead90c-3201-5834-b766-1a6625757a89","fields":{"slug":"/jc5/"},"frontmatter":{"title":"인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"1460ba25-d467-50f1-873c-d36498b197b7","fields":{"slug":"/jc6/"},"frontmatter":{"title":"동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":{"fields":{"slug":"/jc2/"},"frontmatter":{"title":"CPU 스케줄링, 시스템 자원 관리"}},"next":{"fields":{"slug":"/jc4/"},"frontmatter":{"title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},"pageContext":{"id":"3b1392c5-94e5-5f2b-889c-04d05775956f","series":"운영체제 기본 개념","previousPostId":"206f7f4e-13af-5568-b55d-4f56ccf6f27d","nextPostId":"c96ac712-ee44-5bd2-8318-3d771e986911"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc4/page-data.json b/public/page-data/jc4/page-data.json new file mode 100755 index 0000000..df61074 --- /dev/null +++ b/public/page-data/jc4/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc4/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"c96ac712-ee44-5bd2-8318-3d771e986911","excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. 멀티 프로그래밍 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다.…","html":"

단일 프로세스

\n
\n

초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\nCPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 IO작업동안 CPU는 멈추게\n될것이고 그 상황에서 CPU가 놀고 있게 되는 시간이 늘어나는 것입니다.\n
\n

멀티 프로그래밍

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다.\n이를 멀티 프로그래밍이라고 부르며 그림처럼 CPU 사용률을 높이기 위한 목적이었습니다.

\n

하지만 이러한 방식의 문제는 앞선 프로세스가 길어질 수록 즉 IO사용처럼 비는 시간없이 순수하게 많은 시간을\n쓰게 된다면 이후 프로세스가 계속 기다려야 하는 문제가 있었습니다.

\n
\n

멀티 태스킹

\n

\n \n \n \n \n \n
img.png
\n

\n

멀티 프로그래밍 방식에서 더 나아가 모든 프로세스가 공정하게 특정 짧은 시간만 실행되게 반복한다면 길게 시행되는\n프로세스 뒤에 오는 프로세스가 기다리는 문제가 없을 것이다. 이것이 멀티태스킹을 사용하는 이유입니다.

\n

프로세스1에서 프로세스2로 작업을 스위칭 하는것을 문맥 교환(Context Switching)이라고\n부르게 되는데 이러한 문맥교환은 값싼 작업이 아니고 이러한 작업이 자주 일어나게 된다면 비효율 적인 단점이 부각되다 보니\n새로운 방식을 사용하게 됩니다.

\n
\n

멀티 프로세싱

\n

멀티 프로세싱이란 이전 멀티 태스킹과 이름은 비슷 하지만 완전히 다른 방식입니다.

\n

이전 방식은 하나의 CPU를 어떻게 쪼개서 사용할까라는 목적이였다면, 멀티 프로세싱CPU 작업단위인\n코어 자체를 늘려서 여러 CPU코어가 동시에 작업하는것을 멀티 프로세싱이라고 부르게 됩니다.

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

멀티 프로세싱은 CPU코어 수를 늘리는 방법이기 때문에, 이를 어떻게 처리할까에 대한 내용은 멀티 프로세싱 자체의 내용이 아니고 앞서 나왔던 방법론을 도입할 수 있습니다.\n그림처럼 하나의 프로세스를 여러 코어가 담당하는 방법이나, 여러 프로세스를 여러 코어가 담당 할 수 도 있습니다.

\n

출처

\n

사진출처

","frontmatter":{"title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","date":"September 07, 2025","update":"September 07, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/jc4/","readingTime":{"minutes":3.8}}},"seriesList":{"edges":[{"node":{"id":"a856e34f-f9a9-5164-8fb5-befe1aa43bcd","fields":{"slug":"/jc1/"},"frontmatter":{"title":"운영체제의 역할과 커널의 기능"}}},{"node":{"id":"206f7f4e-13af-5568-b55d-4f56ccf6f27d","fields":{"slug":"/jc2/"},"frontmatter":{"title":"CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"3b1392c5-94e5-5f2b-889c-04d05775956f","fields":{"slug":"/jc3/"},"frontmatter":{"title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"c96ac712-ee44-5bd2-8318-3d771e986911","fields":{"slug":"/jc4/"},"frontmatter":{"title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"6fead90c-3201-5834-b766-1a6625757a89","fields":{"slug":"/jc5/"},"frontmatter":{"title":"인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"1460ba25-d467-50f1-873c-d36498b197b7","fields":{"slug":"/jc6/"},"frontmatter":{"title":"동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":{"fields":{"slug":"/jc3/"},"frontmatter":{"title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}},"next":{"fields":{"slug":"/hs4/"},"frontmatter":{"title":"4. 쓰레드 "}}},"pageContext":{"id":"c96ac712-ee44-5bd2-8318-3d771e986911","series":"운영체제 기본 개념","previousPostId":"3b1392c5-94e5-5f2b-889c-04d05775956f","nextPostId":"3ad80296-57ed-53b0-ada7-f06096fe6849"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc5/page-data.json b/public/page-data/jc5/page-data.json new file mode 100755 index 0000000..67d7ba3 --- /dev/null +++ b/public/page-data/jc5/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc5/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"6fead90c-3201-5834-b766-1a6625757a89","excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","html":"

인터럽트 기반 입출력

\n
\n

인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다.

\n

인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트를 발생시킨\n주체가 무엇인가에 따라 나뉘게 된다.

\n

대표적인 하드웨어 인터럽트는 I/O완료, 대표적인 소프트웨어 인터럽트는 시스템 콜이 있다.

\n
\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

이러한 인터럽트 기반 입출력의 순서를 설명하자면

\n
    \n
  1. CPU가 입출력 장치에 대해 입출력 요청을 보낸다.
  2. \n
  3. CPU는 요청이후 다른 작업을 수행한다.
  4. \n
  5. 입출력 장치가 준비되면 인터럽트를 발생시킨다.
  6. \n
  7. CPU는 현재 실행 중인 작업을 중단하고 인터럽트 서비스 루틴(ISR)을 실행한다.
  8. \n
  9. 데이터를 처리한 후 , CPU는 원래 수행하던 작업을 계속 실행한다.
  10. \n
\n

이러한 인터럽트 기반 입출력의 단점은 인터럽트가 많이 발생하는 상황에서 CPU가 부하될 수 있다는 단점이 있다.

\n
\n
\n

DMA(Direct Memory Access 직접 메모리 접근)

\n
\n

DMA방식은 이름에서 볼 수 있듯이 CPU를 사용하지 않고 입출력 장치가 직접 메로리와 데이터를 교환합니다.

\n

이것이 가능한 이유는 DMA 컨트롤러가 존재해, 메모리와 입출력 장치 사이의 데이터를 관리하기 때문입니다.

\n

DMA에서는 CPU가 전송할 데이터의 위치, 포인터, 바이트 크기만 DMA 컨트롤러에 전달하면,\nDMA가 입출력 작업을 대신 처리하고 전체 작업이 완료될 때만 CPU에 인터럽트를 보냅니다.\n이로 인해 CPU와 여러 입출력 장치가 직접 연결되던 기존 구조에서 CPU-DMA-입출력 장치 구조로 변화했고,\nCPU의 가용 시간이 현저히 증가하는 효과를 얻었습니다.\n이는 교수가 조교에게 학생 관리를 맡기고 최종 결과만 확인하는 것에 비유할 수 있으며,\n현재 DMA는 많은 컴퓨터 장치에서 보편적으로 사용되는 기술이 되었습니다.

\n
\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\nDMA 방식을 순서로 설명하자면\n
    \n
  1. CPU가 DMA 컨트롤러에게 입출력 요청합니다.
  2. \n
  3. DMA 컨트롤러가 메모리와 입출력 장치 간의 데이터 전송을 직접 수행합니다.
  4. \n
  5. 데이터 전송이 완료되면 DMA 컨트롤러가 인터럽트를 발생 시켜 CPU에게 완료를 알립니다.
  6. \n
  7. CPU는 인터럽트를 받아서 필요한 후처리 수행합니다.
  8. \n
","frontmatter":{"title":"인터럽트와 DMA를 통한 효율적 입출력 처리","date":"September 08, 2025","update":"September 08, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/jc5/","readingTime":{"minutes":4.025}}},"seriesList":{"edges":[{"node":{"id":"a856e34f-f9a9-5164-8fb5-befe1aa43bcd","fields":{"slug":"/jc1/"},"frontmatter":{"title":"운영체제의 역할과 커널의 기능"}}},{"node":{"id":"206f7f4e-13af-5568-b55d-4f56ccf6f27d","fields":{"slug":"/jc2/"},"frontmatter":{"title":"CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"3b1392c5-94e5-5f2b-889c-04d05775956f","fields":{"slug":"/jc3/"},"frontmatter":{"title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"c96ac712-ee44-5bd2-8318-3d771e986911","fields":{"slug":"/jc4/"},"frontmatter":{"title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"6fead90c-3201-5834-b766-1a6625757a89","fields":{"slug":"/jc5/"},"frontmatter":{"title":"인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"1460ba25-d467-50f1-873c-d36498b197b7","fields":{"slug":"/jc6/"},"frontmatter":{"title":"동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":{"fields":{"slug":"/hs3/"},"frontmatter":{"title":"3. 프로세스"}},"next":{"fields":{"slug":"/jc6/"},"frontmatter":{"title":"동기식/비동기식 I/O의 차이와 활용 사례"}}},"pageContext":{"id":"6fead90c-3201-5834-b766-1a6625757a89","series":"운영체제 기본 개념","previousPostId":"46425f46-05a1-5269-ad13-c4687acafbf1","nextPostId":"1460ba25-d467-50f1-873c-d36498b197b7"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc6/page-data.json b/public/page-data/jc6/page-data.json new file mode 100755 index 0000000..860b5c3 --- /dev/null +++ b/public/page-data/jc6/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc6/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"1460ba25-d467-50f1-873c-d36498b197b7","excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","html":"

IO란

\n

개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다.

\n

예시를 들어서

\n
    \n
  • 파일 읽기/쓰기 (문서를 열거나 저장하는 행위)
  • \n
  • 네트워크 통신(웹사이트 접속, 이메일 전송)
  • \n
  • 데이터베이스 조회(회원 정보 검색)
  • \n
\n

이런 일련의 행위는 공통적인 특징이 있는데, 물리적인 시간이 걸린다는 점입니다.\n그렇기 떄문에 IO를 어떻게 다룰까에 대한 방법또한 여러가지 존재합니다.

\n
\n
\n

동기와 비동기란

\n

IO를 다루는 방법에는 동기, 비동기에 대한 개념이 등장합니다.\n이러한 개념을 사전에 정의 하고 내려가겠습니다.

\n

동기 (Synchronous)

\n

프로그램에서 말하는 동기란 하나의 작업에 대해서 요청과 응답 과정을 기다리는 행위입니다.\n예를들어, WAS가 데이터베이스에 조회 요청을 하고 데이터베이스는 요청받은 데이터를 돌려줄것입니다.\n이 과정에서 WAS는 요청직후 부터 응답을 받을때 까지 과정에서 데이터베이스의 응답을 기다리게 됩니다. 이것이 동기입니다.

\n
\n

동기의 특징

\n

순차적 실행: 한 작업이 완료되어야 다음 작업이 시작\n블로킹: 현재 작업이 끝날 때까지 다른 작업은 대기\n예측 가능: 코드가 위에서 아래로 순서대로 실행

\n
\n
\n

비동기 (Asynchronous)

\n

그렇다면 비동기는 하나의 작업에 대해서 요청과 응답 과정을 기다리지 않는 행위입니다.\n예를들어, WAS가 데이터베이스에 조회 요청을 하게 되면 데이터베이스가 이를 수행하고 응답할것입니다.\n이 과정 사이에 시간동안 WAS는 본인의 다른 작업을 수행하다가 데이터베이스의 응답을 받게 됩니다.\n즉 요청과 응답 사이 기간동안 WAS는 본인의 일을 하며 무작정 기다리지 않는 것입니다.

\n
\n

비동기의 특징

\n

동시 실행: 여러 작업을 동시에 시작 가능\n논블로킹: 작업 완료를 기다리지 않고 다른 작업 진행\n콜백/Promise: 작업 완료 시 결과를 알려주는 방식

\n
\n

동기식 I/O

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

동기식IO는 IO요청이 발생하였을 때 이전 동기 설명처럼 IO요청이 끝날때 까지 기다리는 방식입니다.\n프로그램이 IO작업을 요청하게 되면, 다른 동작을 수행하지 않고 멈춰서 IO작업이 리턴되기 까지 기다립니다.\nI/O작업이 완료되면 인터럽트를 통해 완료를 알리게 됩니다. 이후 CPU 제어권이 기존 프로그램에게 넘어가게 됩니다.

\n

이러한 방식의 특징은 구현이 쉽다는 특징이 있지만, 연산에 대한 기다림으로 인해 자원 낭비를 하는 특징이 있습니다.

\n

비동기식 I/O

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

비동기식IO는 IO요청이 발생하였을 떄 이전 비동기 설명처럼 IO요청을 기다리지 않는 방식입니다.\n프로그램이 IO 작업을 요청하고, 그 작업이 완료되기를 기다리지 않고 즉시 다음 작업으로 넘어가는 방식입니다.

\n

이러한 방식의 특징은 구현의 복잡성이 높다는 것이지만, 대용량 데이터를 처리하는데 여러 IO작업을 동시에 처리해야 할 떄 유용합니다.

","frontmatter":{"title":"동기식/비동기식 I/O의 차이와 활용 사례","date":"September 09, 2025","update":"September 09, 2025","tags":["운영체제"],"series":"운영체제 기본 개념"},"fields":{"slug":"/jc6/","readingTime":{"minutes":4.945}}},"seriesList":{"edges":[{"node":{"id":"a856e34f-f9a9-5164-8fb5-befe1aa43bcd","fields":{"slug":"/jc1/"},"frontmatter":{"title":"운영체제의 역할과 커널의 기능"}}},{"node":{"id":"206f7f4e-13af-5568-b55d-4f56ccf6f27d","fields":{"slug":"/jc2/"},"frontmatter":{"title":"CPU 스케줄링, 시스템 자원 관리"}}},{"node":{"id":"3b1392c5-94e5-5f2b-889c-04d05775956f","fields":{"slug":"/jc3/"},"frontmatter":{"title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리"}}},{"node":{"id":"c96ac712-ee44-5bd2-8318-3d771e986911","fields":{"slug":"/jc4/"},"frontmatter":{"title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념"}}},{"node":{"id":"6fead90c-3201-5834-b766-1a6625757a89","fields":{"slug":"/jc5/"},"frontmatter":{"title":"인터럽트와 DMA를 통한 효율적 입출력 처리"}}},{"node":{"id":"1460ba25-d467-50f1-873c-d36498b197b7","fields":{"slug":"/jc6/"},"frontmatter":{"title":"동기식/비동기식 I/O의 차이와 활용 사례"}}}]},"previous":{"fields":{"slug":"/jc5/"},"frontmatter":{"title":"인터럽트와 DMA를 통한 효율적 입출력 처리"}},"next":{"fields":{"slug":"/jc7/"},"frontmatter":{"title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},"pageContext":{"id":"1460ba25-d467-50f1-873c-d36498b197b7","series":"운영체제 기본 개념","previousPostId":"6fead90c-3201-5834-b766-1a6625757a89","nextPostId":"0f3ed929-e023-5c69-9609-82bade016409"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc7/page-data.json b/public/page-data/jc7/page-data.json new file mode 100755 index 0000000..7c337f5 --- /dev/null +++ b/public/page-data/jc7/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc7/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"0f3ed929-e023-5c69-9609-82bade016409","excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. 백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는…","html":"

프로세스란 무엇일까?

\n
\n

우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다.

\n

여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다.

\n
\n
\n

\n \n \n \n \n \n
img.png
\n

\n
\n위 사진처럼 보이는 것보다 더 많은 프로세스가 작동하고 있는데, 여기서 사용자가 볼 수 있는 프로세스를 포그라운드 프로세스 라며 명하며,\n보이지 않는 프로세스를 백그라운드 프로세스라고 부르게 됩니다. \n

백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는 다는 뜻은 아닌데 백그라운드 프로세스 중에서 사용자와 상호작용 하지 않고 자신의 일만을 수행하기 위해 존재하는\n프로세스를 데몬(daemon) 프로세스라고 명합니다.

\n
\n

프로세스 제어 블록(PCB)

\n
\n

CPU자원이 한정되어 있는 반면에, 모든 프로세스는 실행을 위해 CPU를 사용하여야 합니다.\n그렇기 떄문에 프로세스들은 한정된 시간 만 CPU를 사용하며 자신의 차례를 기다립니다.

\n

운영체제는 빠르게 번갈아 수행되는 프로세스의 실행 순서를 관리하고, 프로세스에 CPU와 여러가지 자원을 배분합니다.\n이를 위해 운영체제는 프로세스 제어 블록(PCB)를 이용합니다.

\n
\n

PCB는 커널 영역에 생성되고, 수많은 프로세스를 PCB를 통해 태그처럼 사용해 특정 프로세스를 식별하며 해당 프로세스를 처리하는데 필요한 정보를 판단합니다.

\n

즉, 가게 주인이 물건을 태그를 통해 판단하고 가격을 알 수 있고, 생산지를 알 수 있는 것처럼 PCB는 운영체제가 수 많은 프로세스를 식별하고 그 프로세스의 정보를 판단하게 돕습니다.

\n
\n
\n

PCB의 구조

\n
\n
\n

\n \n \n \n \n \n
img.png
\n

\n

사진 출처

\n
\n

위 그림처럼 PCB는 프로세스를 식별하기 위해 여러가지 정보를 담고 있습니다. 프로세스의 ID나,\n레지스터의 값 혹은 상태같이 많은 정보를 담고있으며 이를 알아보고자 합니다.

\n
\n

프로세스 ID

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

프로세스 ID(PID)는 프로세스를 식별하기 위해 존재하는 고유 ID입니다. 메모장을 두개 킨다고 할지라도 다른 프로세스ID가\n만들어지는 것처럼 중복된 활동이여도 하나의 프로세스는 고유한 ID를 가지게 됩니다.

\n
\n

레지스터 값

\n

프로세스는 자신의 실행 차례가 돌아오면 이전까지 사용했던 레지스터의 중간값들을 모두 복원합니다.\n여기에는 프로그램 카운터가 속하게 됩니다.

\n
\n

프로세스 상태

\n

현재 프로세스가 어떤 상태인 기록합니다. 입출력장치를 사용하기 위해 기다리는지 혹은 CPU를 사용하고 있는 상태인지 와 같은\n상태를 기록하며 자세한 상태는 다음장에서 설명합니다.

\n
\n

CPU 스케줄링 정보

\n

프로세스가 언제, 어떤 순서로 CPU를 할당받을지에 대한 정보도 PCB에 기록됩니다.

\n
\n

메모리 관리 정보

\n

프로세스마다 메모리에 저장된 위치가 다릅니다. 그렇기 떄문에 PCB에는 해당 프로세스가 저장된 메모리 위치를 기록해야 합니다.

\n
\n
\n

프로세스의 메모리 영역

\n
\n

프로세스가 생성되면 커널 영역에 PCB가 생성됩니다. 그렇다면 커널 영역이 아닌 사용자 영역에는 어떤 데이터가 들어갈까요?

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

사진출처

\n

위 그림처럼 하나의 프로세스는 크게 코드영역(Text), 데이터 영역(Bss,Gvar), 힙 영역(Heap), 스택 영역(Stack) 4가지로 나뉩니다.

\n

차례대로 설명하자면,

\n
\n
\n

코드영역 or 텍스트영역(Text)

\n

이곳에는 실행할 수 있는 기계어로 이루어진 명령어가 저장됩니다. 가공할 수 있는 데이터가 아닌\nCPU가 실행해야 하는 명령어가 담겨있기 때문에 읽기모드만 지원합니다.

\n
\n

데이터 영역

\n

프로그램을 실행하는 동안 유지되어야 하는 데이터가 저장되는 공간입니다. 대표적은 전역 변수가 이곳에 해당합니다.

\n
\n

코드영역 & 데이터 영역 공통점

\n

위 두 영역은 크기가 변하지 않습니다. 프로그램을 구성하는 명령어가 작동중에 코드 양이 늘어나는 경우가 없으니\n이 두가지 영역을 정적 할당 영역이라고 부릅니다.

\n
\n

힙 영역

\n

프로그래머가 직접 할당할 수 있는 공간입니다. 프로그래밍 과정에서 힙 영역에 데이터를 할당했다면 언젠가는 이 영역에\n데이터를 반환해야 합니다. 그렇지 않다면 메모리 용량은 점점 줄어들어 장애가 발생할 수 있습니다.

\n

이런 문제를 메모리를 할당받고 해제 하지 않았다고 하여 누수가 발생했다. 즉 메모리 누수라고 부릅니다.

\n
\n

스택 영역

\n

스택 영역은 데이터를 일시적으로 저장하는 공간입니다.\n데이터 영역에 담기는 값과는 다르게 잠깐 쓸 데이터를 담아두는 공간입니다.\n함수를 실행하는 동안 필요한 지역변수, 매개 변수가 이곳에 해당합니다.\n그렇기 떄문에 함수가 종료되면 스택 영역에서 해당 함수에 쓰였던 변수들도 같이 없어지게 됩니다.

\n
\n
\n

힙 영역 & 스택 영역 공통점

\n

위 두 영역은 실시간으로 그 크기가 변할 수 있고 그렇기 떄문에 동적 할당 영역이라고 부르게 됩니다.

\n

그림을 보면 unused memory영역이 있는데, 스택 영역과 힙 영역이 동적이기 떄문에 힙은 아래에서 위로, 스택은\n위에서 아래로 주소를 할당하게 됩니다. 그렇게 되면 서로 충돌없이 동적으로 값을 할당할 수 있기 때문입니다.

\n

여기서 만약에 힙이나 스택에 많은 정보가 담겨서 서로의 지점을 충돌 할 수 있는데, 그럴때 각각 stack overflow,\nheap overflow라고 부르게 됩니다.

","frontmatter":{"title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","date":"September 10, 2025","update":"September 10, 2025","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"},"fields":{"slug":"/jc7/","readingTime":{"minutes":9.075}}},"seriesList":{"edges":[{"node":{"id":"0f3ed929-e023-5c69-9609-82bade016409","fields":{"slug":"/jc7/"},"frontmatter":{"title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},{"node":{"id":"f49c1834-3399-5504-9929-1abc15d55888","fields":{"slug":"/jc8/"},"frontmatter":{"title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},{"node":{"id":"6fb64598-2fd1-50e9-bfca-d7513b95df85","fields":{"slug":"/jc9/"},"frontmatter":{"title":"쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},{"node":{"id":"fc9488aa-d0c3-5870-9e9c-afaef4672d71","fields":{"slug":"/jc10/"},"frontmatter":{"title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},{"node":{"id":"5a1e74a6-7abb-5097-97ee-1af020ef9a81","fields":{"slug":"/jc11/"},"frontmatter":{"title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}}]},"previous":{"fields":{"slug":"/jc6/"},"frontmatter":{"title":"동기식/비동기식 I/O의 차이와 활용 사례"}},"next":{"fields":{"slug":"/jc8/"},"frontmatter":{"title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},"pageContext":{"id":"0f3ed929-e023-5c69-9609-82bade016409","series":"프로세스와 쓰레드에 대해서 알아보기","previousPostId":"1460ba25-d467-50f1-873c-d36498b197b7","nextPostId":"f49c1834-3399-5504-9929-1abc15d55888"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc8/page-data.json b/public/page-data/jc8/page-data.json new file mode 100755 index 0000000..7c94deb --- /dev/null +++ b/public/page-data/jc8/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc8/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"f49c1834-3399-5504-9929-1abc15d55888","excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","html":"

문맥교환(Context Switching)

\n
\n

하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요?

\n

프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔을 때 이 과정을 이어받아 작업을 수행할 수 있습니다.

\n

여기서 하나의 프로세스를 실행하기 위해 필요한 정보들을 문맥(Context)라고 부르게 됩니다.\n이러한 문맥값들은 PCB속에 저장됩니다.환

\n
\n

\n \n \n \n
img.png
\n
\n사진출처

\n

결국 프로세스 A에서 B로 프로세스가 넘어가는 순간에 프로세스 A정보를 백업하고 그작업이 끝난다면\n프로세스 B의 문맥을 불러오게 되며 이 것이 프로세스를 교대하는 방법입니다.

\n

문맥교환을 통해 여러개의 프로세스가 병렬적으로 시행되는 것 처럼 보이게 하지만 이러한 문맥교환은\n오버헤드가 발생할 수 있기 때문에 문맥교환이 자주일어나면 오버헤드를 신경써야 합니다.

\n
\n
\n

프로세스 상태

\n
\n

이전에 PCB에 기록되는 정보 중 프로세스 상태가 있다고 합니다. 여기서 말하는 프로세스 상태는 생성이 되었는지\n혹은 CPU를 사용하는지와 같은 정보를 통칭해서 프로세스 상태라고 부르게 됩니다.

\n
\n

프로세스 상태는 크게 다섯가지로 나뉠 수 있습니다.

\n

\n \n \n img.png\n \n
img.png
\n
\n사진출처

\n
\n

1. 생성 상태

\n

프로세스를 생성 중인 상태를 생성 상태라고 부릅니다. 메모리에 적재되어 PCB를 할당받은 상태를 생성상태라고 부르게 됩니다.\n생성 상태가 끝난다고 곧바로 실행되는 것이 아닌 준비 상태가 되어 실행되기를 기다리게 됩니다.

\n
\n

2. 준비 상태

\n

준비 상태는 당장 CPU를 할당받아 실행될 수 있지만, 차례가 오지않아 기다리고 있는 상태입니다.\n이 상태에서 준비가 되면 실행 상태로 넘어 갑니다. 그리고 다른 상태에서 다시 준비 상태로도 전환이 가능합니다.

\n

준비 상태인 프로세스를 실행 상태로 전환하는 것을 디스패치 라고 부릅니다.

\n
\n

3. 실행 상태

\n

실행 상태는 CPU를 할당받아 실행 중인 상태를 지칭 합니다. 실행 상태인 프로세스는 할당된 시간 동안 CPU를 사용할 수 있습니다.\n이때 제한된 시간내 프로세스를 완료하지 못한경우 준비 상태로 전환이 되며, I/O입력처럼 대기해야 하는 상황이 생기면\n대기 상태로 넘어가게 됩니다.

\n
\n

4. 대기 상태

\n

실행 상태에서 I/O입력과 같이 프로세스가 대기해야 하는 상황이 온다면 대기 상태로 진입하게 됩니다.\n대기 상태가 끝난다고 해도 실행 상태가 되는것이 아닌 준비 상태로 넘어가게 됩니다.

\n
\n

5. 종료 상태

\n

프로세스가 종료된 상태입니다. 이 상태에 도달하면 운영체제는 PCB와 프로세스가 사용한 메모리를 정리합니다.

\n
\n
\n

프로세스 계층 구조

\n
\n

프로세스는 실행 도중 시스템 호출을 통해 다른 프로세스를 생성할 수 있습니다.

\n

이때 새 프로세스를 생성한 프로세스를 부모 프로세스라고 부르게 되며, 생성 된 프로세스를 자식 프로세스라고\n부르게 됩니다.\n부모의 프로세스와 자식의 프로세스는 각각 고유한 PID를 가지며 자식프로세스에서 부모프로세스 PID를 PPID로 가지고 있기도 합니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n
\n[사진 출처: 혼자 공부하는 운영체제 저자:강민철]

\n
\n
\n

프로세스 생성기법

\n
\n

그렇다면 부모 프로세스가 어떻게 자식 프로세스를 생성 할까요?

\n

그 방법은 fork, exec라는 명령어를 통해서 생성하게 됩니다.

\n

부모 프로세스는 fork를 통해 자신의 복사본을 자식 프로세스로 생성해내고, 그 복사본은 exec명령어를 통해\n자신의 메모리 공간을 다른 프로그램으로 교체합니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

좀더 자세히 설명하면 fork, exec 모두 시스템 호출로 분류 됩니다.\n부모 프로세스는 fork 시스템 호출을 통해 자신의 복사본을 자식으로써 생성합니다.

\n

여기서 자식은 부모의 복사본이기 때문에 부모 프로세스의 자원들, 예를들면 메모리의 내용, 열린 파일의 목록등을\n상속하게 됩니다. 그렇다고 해서 모든 정보가 같지는 않습니다.

\n

왜냐하면, PID나 메모리 저장구조는 고유한 정보이기 때문에 fork로 만들어진 자식은 PID, 메모리 저장위치\n처럼 고유한 정보에 대해서는 개별적인 값을 가지고 있습니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

fork만 사용한 프로세스는 완전한 자식 프로세스라고 명하기는 조금 어렵습니다.\nPID와 같은 고유한 값을 제외한다면 부모가 가진 리소스를 동일하게 사용하는 대체품이기 때문입니다.

\n

그렇기 때문에 자식 프로세스는 자신의 프로세스를 가지기 위해 exec 시스템 호출을 하게 됩니다.

\n

exec 호출을 진행하게 되면 자신의 메모리 공간을 새로운 프로그램으로 덮어쓰게 됩니다.

\n

코드 영역과 데이터 영역의 내용이 실행한 프로그램으로 바뀌게 되고, 나머지 영역은 초기화 됩니다.

","frontmatter":{"title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","date":"September 11, 2025","update":"September 11, 2025","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"},"fields":{"slug":"/jc8/","readingTime":{"minutes":8.17}}},"seriesList":{"edges":[{"node":{"id":"0f3ed929-e023-5c69-9609-82bade016409","fields":{"slug":"/jc7/"},"frontmatter":{"title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},{"node":{"id":"f49c1834-3399-5504-9929-1abc15d55888","fields":{"slug":"/jc8/"},"frontmatter":{"title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},{"node":{"id":"6fb64598-2fd1-50e9-bfca-d7513b95df85","fields":{"slug":"/jc9/"},"frontmatter":{"title":"쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},{"node":{"id":"fc9488aa-d0c3-5870-9e9c-afaef4672d71","fields":{"slug":"/jc10/"},"frontmatter":{"title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},{"node":{"id":"5a1e74a6-7abb-5097-97ee-1af020ef9a81","fields":{"slug":"/jc11/"},"frontmatter":{"title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}}]},"previous":{"fields":{"slug":"/jc7/"},"frontmatter":{"title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}},"next":{"fields":{"slug":"/hs5/"},"frontmatter":{"title":"5. CPU 스케줄링"}}},"pageContext":{"id":"f49c1834-3399-5504-9929-1abc15d55888","series":"프로세스와 쓰레드에 대해서 알아보기","previousPostId":"0f3ed929-e023-5c69-9609-82bade016409","nextPostId":"cb8ba341-aac3-5491-9121-5bee87c5172c"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/jc9/page-data.json b/public/page-data/jc9/page-data.json new file mode 100755 index 0000000..00d3432 --- /dev/null +++ b/public/page-data/jc9/page-data.json @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-post-jsx","path":"/jc9/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"markdownRemark":{"id":"6fb64598-2fd1-50e9-bfca-d7513b95df85","excerpt":"스레드란? 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이 여러 기능을…","html":"

스레드란?

\n
\n

\n \n \n \n \n \n
img.png
\n

\n
\n

스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다.

\n

또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다.

\n

마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이 여러 기능을 수행할 수 있습니다.

\n
\n

프로세스와 스레드

\n
\n

스레드를 이해하기 위해서는 프로세스와 엮어서 설명하고자 합니다.\n전통적인 CPU는 하나의 프로세스만 처리할 수 있었습니다. 메모장, 워드, 게임등 많은 프로세스가 하나의 실행\n흐름을 가지고 한 번의 하나의 부분만 실행되는 프로세스입니다.

\n

\n \n \n \n \n \n
img.png
\n

\n

이런 프로세스를 단일 스레드 프로세스라고 부릅니다.

\n
\n

하지만, 스레드라는 개념이 도입되면서 하나의 프로세스가 한 번에 여러가지 일을 동시에 처리하는 것이 가능해졌습니다.\n프로세스를 구성하는 명령어를 동시에 처리하는것이 가능해졌습니다.

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n

그림을 통해 스레드를 보게 되면 스레드는 '프로세스를 구성하는 실행의 흐름 단위'라고 표현 가능 할 것입니다.

\n

왜냐하면, 하나의 프로세스 안에 여러가지 스레드가 있고 각각의 작업 흐름을 가지며 프로세스가 하는 일을 병렬적으로 만들어\n주기 때문입니다.

\n
\n
\n

스레드 메모리 구조

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

스레드의 메모리 구조를 이해하기 위해서는 이전 프로세서의 구조를 상기해봐야 합니다.

\n

프로세스는 스택, 힙, 데이터, 코드 영역을 각자 가진다고 합니다.\n스레드는 '프로세스를 구성하는 실행 흐름의 단위'라고 했고, 이 떄문에 스레드는 프로세스의 메모리 구조의 대부분을 공유해서\n사용한다. 그렇기 때문에 여러 스레드의 작업이 하나의 프로세스 안에서 이루어져도 동시작업이 가능한 이유입니다.

\n
\n

그렇다면 어떻게 스레드는 프로세스와 스레드간 데이터를 공유하는 것일까?\n아래 그림을 통해서 보게되면

\n
\n

\n \n \n img.png\n \n
img.png
\n
\n사진출처

\n
\n

우선 하나의 프로세스안에 코드, 데이터, 힙, 스택 영역이 존재합니다. 그리고 프로세스 내부의 개별적인 스레드가 존재합니다.

\n

스레드가 레지스터, 프로그램 카운터, 스택을 개별적으로 가지는 핵심 이유는 독립적인 실행 흐름을 보장하기 위해서입니다.

\n

프로그램 카운터는 각 스레드가 서로 다른 코드 위치에서 실행될 수 있도록 현재 실행 지점을 개별 추적하고,

\n

레지스터는 각 스레드의 작업 데이터를 독립적으로 저장합니다.\n이를 통해 CPU가 스레드 간 전환할 때 현재 상태를 저장하고 복원하여 중단된 지점에서 정확히 재개할 수 있습니다.\n스택 영역을 따로 가지는 이유는 각 스레드가 독립적인 함수 호출 흐름을 가져야 하기 때문입니다.

\n

스택은 함수 호출 시 지역 변수, 매개변수, 리턴 주소를 저장하는데, 만약 스레드들이 스택을 공유한다면 한 스레드의\n함수 호출이 다른 스레드의 함수 실행에 영향을 주어 실행 흐름이 꼬이게 됩니다. 따라서 각 스레드는 독립적인 스택을 가져 서로 다른 함수를 안전하게 호출하고 실행할 수 있습니다.\n결과적으로 이런 구조를 통해 스레드들은 힙과 데이터 영역은 공유하면서도 각자 독립적인 실행 흐름을 유지할 수 있어\n, 하나의 프로세스 내에서 여러 작업을 동시에 효율적으로 처리할 수 있게 됩니다.

\n
\n
\n

TCB란

\n
\n

\n \n \n \n \n \n
img.png
\n

\n

스레드 제어 블록은 운영체제가 각 스레드를 관리하기 위해 유지하는 데이터 구조체입니다.\n프로세스 제어 블록(PCB)과 유사하지만 스레드 수준에서 필요한 정보들을 담고 있습니다.\n링크드 리스트 형태로 구현되어 PCB안에 해당 스레드의 TCB를 내포하고 있는 형태로 저장됩니다.

\n
\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n

\n \n \n \n img.png\n \n \n
img.png
\n

\n
\n
\n

TCB는 사진과 같은 형태로 저장되며, 아래와 같은 정보를 가진다.

\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
정보설명
스레드 식별자각 스레드를 식별하는 고유한 식별자
스레드 상태실행 준비 대기 등 스레드의 현재 상태
프로그램 카운터스레드가 다음에 실행할 명령어의 주소
레지스터스레드가 현재 사용하고 있는 CPU 레지스터의 값을 저장
스레드 우선순위스케줄링 결정에 사용되는 스레드의 우선순위
스레드 스택 포인터스택 내에서 현재 작업의 위치를 가리키는 레지스터
스레드 문맥 정보문맥 교환 시 저장되고 복원되어야 할 정보
","frontmatter":{"title":"쓰레드의 개념, 메모리 공유 구조 및 TCB","date":"September 12, 2025","update":"September 12, 2025","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"},"fields":{"slug":"/jc9/","readingTime":{"minutes":7.34}}},"seriesList":{"edges":[{"node":{"id":"0f3ed929-e023-5c69-9609-82bade016409","fields":{"slug":"/jc7/"},"frontmatter":{"title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기"}}},{"node":{"id":"f49c1834-3399-5504-9929-1abc15d55888","fields":{"slug":"/jc8/"},"frontmatter":{"title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기"}}},{"node":{"id":"6fb64598-2fd1-50e9-bfca-d7513b95df85","fields":{"slug":"/jc9/"},"frontmatter":{"title":"쓰레드의 개념, 메모리 공유 구조 및 TCB"}}},{"node":{"id":"fc9488aa-d0c3-5870-9e9c-afaef4672d71","fields":{"slug":"/jc10/"},"frontmatter":{"title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},{"node":{"id":"5a1e74a6-7abb-5097-97ee-1af020ef9a81","fields":{"slug":"/jc11/"},"frontmatter":{"title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법"}}}]},"previous":{"fields":{"slug":"/hs5/"},"frontmatter":{"title":"5. CPU 스케줄링"}},"next":{"fields":{"slug":"/jc10/"},"frontmatter":{"title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점"}}},"pageContext":{"id":"6fb64598-2fd1-50e9-bfca-d7513b95df85","series":"프로세스와 쓰레드에 대해서 알아보기","previousPostId":"cb8ba341-aac3-5491-9121-5bee87c5172c","nextPostId":"fc9488aa-d0c3-5870-9e9c-afaef4672d71"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/search/page-data.json b/public/page-data/search/page-data.json index 3407228..0436073 100644 --- a/public/page-data/search/page-data.json +++ b/public/page-data/search/page-data.json @@ -1 +1 @@ -{"componentChunkName":"component---src-pages-search-jsx","path":"/search/","result":{"data":{"allMarkdownRemark":{"nodes":[{"excerpt":"동시성 이슈란? img.png 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면…","fields":{"slug":"/11/"},"frontmatter":{"date":"September 14, 2025","title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","tags":["운영체제"]},"rawMarkdownBody":"\n\n## 동시성 이슈란?\n\n---\n\n
\n\n![img.png](동시성이슈.png)\n\n
\n\n동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다.\n\n예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면 11가 됩니다. 하지만 스레드 a와 b는 좋아요 카운트에 동시에 접근해서 초기값 10을 받은 상태라면\n스레드 b는 늘어난 11라는 숫자대신 10을 기준으로 값을 줄이게 됩니다. 그럼 최종 결과는 10이 아닌 9라는 값으로 나오게 됩니다.\n\n이처럼 멀티 스레드 환경에서는 하나의 자원에 동시에 접근하게 되면 이러한 문제가 발생할 수 있다.\n\n
\n
\n\n## 스레드 안전\n\n---\n\n그럼 우리가 추구해야 할 문제는 스레드 안전한 멀티 스레드 프로그래밍을 구현할 수 있어야 한다. 이것을 구현하는\n방법에 대해 이야기 하려고 한다.\n\n
\n
\n\n## 스레드 안전 여부 판단\n\n---\n\n1. 전역 변수나 힙, 파일과 같이 여러 스레드가 동시 접근 가능한 자원을 사용하는가\n2. 핸들과 포인터를 통한 데이터의 간접 접근이 가능한가?\n3. 부수 효과를 가져오는 코드가 있는가?\n\n
\n
\n\n## 스레드 안전을 지키기 위한 4가지 방법\n\n---\n\n1. 상호 배제(Mutual Exclusion)\n\n
\n\n- 공유 자원에 하나의 Thread만 접근할 수 있도록 세마포어/ 뮤텍스락을 통제하는 방법이다.\n\n
\n\n2. 원자 연산(Atomic Operation)\n\n
\n\n- 공유 자원에 접근할 때 원자 연산을 이용하거나 원자적으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현하는 방법이다.\n- Atomic\n - 공유 자원 변경에 필요한 연산을 원자적으로 분리한 뒤에 실제로 데이터의 변경이 이루어지는 시점에 Lock을 걸고, \n 데이터를 변경하는 시간 동안 다른 쓰레드의 접근이 불가능하도록 하는 방법이다.\n\n
\n\n3. Thread-Local Storage (스레드 지역 저장소)\n\n
\n\n- 공유 자원의 사용을 최대한 줄이고 각가의 쓰레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는 방법이다.\n- 일반적으로 공유 상태를 피할 수 없을 때 사용하는 방식이며, 전역 변수 사용을 자제하라는 뜻으로 생각하면 된다.\n\n
\n\n4. Re-entrancy (재진입성)\n\n
\n\n- 쓰레드 호출과 상관 없이 프로그램에 문제가 없도록 작성하는 방법이다.\n- 어떤 함수가 한 스레드에 의해 호출되어 실행 중이라면 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 옳바르게 주어져야 한다.\n- 쓰레드끼리 독립적으로 동작할 수 있도록 코드를 작성하는 것으로 생각하면 된다.\n\n
\n
\n\n\n\n\n"},{"excerpt":"img.png 멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술이다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것이다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세…","fields":{"slug":"/10/"},"frontmatter":{"date":"September 13, 2025","title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","tags":["운영체제"]},"rawMarkdownBody":"\n![img.png](멀티프로세스.png)\n\n멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술이다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것이다.\n\n
\n
\n\n### 어떻게 멀티 프로세스를 생성할까?\n\n멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부모 프로세스가\n여러개의 자식 프로세스를 생성한다.\n\n부모 프로세스는 자식 프로세스의 PID를 알고있으며 자식또한 PID와 PPID를 알고있어\n서로 통신이 가능하다.\n\n이런 성질은 각각 독립적이지만 통신이 가능하게 만들었고 멀티 프로세스의 대표적인 예가\n브라우저의 탭이라고 할 수 있다.\n\n브라우저 탭은 문제가 발생해서 닫아야 하는 상황이여도 다른 탭까지 닫히지 않고 개별적으로\n운용을 할 수 있는걸 기억해보면 독립적이란 말을 더 잘 이해할 수 있을것이다.\n\n
\n
\n\n## 멀티 프로세스의 장점\n\n
\n\n1. 안정성\n\n멀티 프로세스의 안정성은 각각의 프로세스가 독립적이기 떄문에 가능하다.\n대표적인 예로 좀전에 설명을 했던 특정 브라우저 탭이 문제가 발생하여 닫아야 하는 상황에서\n같은 브라우저의 다른 탭까지 닫히지는 않는다.\n이런것이 독립적인 성격에 의한 안정성이라고 할 수 있다.\n\n
\n
\n\n## 멀티 프로세스의 단점\n\n
\n\n1. 문맥교환 (Context Switching) Overhead\n\n멀티 태스킹을 이루는 기술인 문맥 교환 과정에서 성능 저하가 발생할 수 있다.\n프로세스를 컨텍스트 스위칭 하면, CPU는 다음 프로세스의 정보를 불러오기 위해\n메모리를 검색하고, CPU 캐시 메모리를 초기화하며, 프로세스 상태를 저장하고, \n불러올 데이터를 준비해야 하기 떄문에, 빈번한 문맥교환이 발생하고 이 비용은 곧 오버헤드로 발생할 수 있다.\n\n
\n
\n\n2. 자원 공유 비효율성\n\n프로세스는 독립적인 메모리를 가지고, 멀티 프로세스는 독립적인 메모리 공간의 합일 것이다.\n그렇기 때문에 메모리 비효율성을 초래한다.\n\n
\n
\n\n## 멀티 스레드\n\n---\n\n![img.png](멀티스레드.png)\n\n
\n\n이전에 보았던 것처럼 스레드는 하나의 프로세스 내에 있는 실행 흐름이다.\n멀티 스레드는 하나의 프로세스 안에 여러개의 실행흐름을 가지는 것이다.\n멀티 스레드 또한 멀티 프로세스 처럼 여러개의 작업을 동시 실행 할 수 있다.\n\n이전에 보았던 것처럼 멀티 프로세스는 브라우저의 여러개의 탭을 통해 예시를 들었다.\n하지만, 멀티 스레드는 같은 브라우저라 할지라도 동일탭에 여러 실행 흐름을 말하게 되고 \n예를들어 네트워크 처리 스레드, 검색 스레드 와 같이 동일한 프로세스 내 기능들을 말하게 된다.\n\n
\n
\n\n## 멀티 스레드의 장점\n\n---\n\n### 프로세스보다 스레드가 가벼움\n\n스레드는 프로세스보다 용량이 가볍다. 이유는 데이터, 코드, 힙 영역을\n프로세스와 공유해서 사용하기 때문에 내장된 정보다 프로세스보다 작기 떄문이다.\n그렇기 때문에 스레드를 제거하는 작업이 프로세스를 제거하는 작업보다 가볍다.\n\n
\n
\n\n### 자원의 효율성\n\n멀티 스레드는 하나의 프로세스 내에서 스택영역을 제외한 영역을 공유하기 때문에\n프로세스 간 통신을 사용하지 않고도 자원의 공유가 가능하여 자원을 효율적으로 사용할 수 있다.\n\n
\n
\n\n### Context Switching 비용 감소\n\n스레드 문맥 교환 또한 오버헤드가 존재하지만, 프로세스 문맥교환과 비교했을 때,\n상대적으로 오버헤드가 적다.\n\n이유는 프로세스 컨텍스트 스위칭 비용은 스위칭할 때마다 CPU 캐시에 있는 내용을 모두 초기화하고,\n새로운 프로세스 정보를 CPU 캐시에 적재해야 하기 떄문이다.\n하지만, 스레드 문맥교환은 스레드 개별적인 정보만 교체하면 되기 떄문에 비용이 상대적으로 낮다.\n\n
\n
\n\n## 멀티 스레드의 단점\n\n멀티 프로세스는 개별적인 작업으로 인해 독집적이고, 각자의 문제를 전파하지 않는다고 하였다.\n\n하지만, 멀티 스레드는 하나의 스레드가 문제가 발생하면 다른 스레드들고 영향을 받아 전체가 종료가 될 수 있다.\n\n
\n
\n\n## 데드락\n\n데드락이란 하나의 자원을 사용하기위해 여러 곳에서 접근했고, 그상황에서 교착상태가 일어났을때\n여러대의 스레드가 서로 대기하면서 무한정 기다리는 현상을 데드락이라고 한다.\n\n예를들어, 스레드 1 은 자원 A을 점유하고 있는 상태에서 자원 B가 필요한 상황이다. \n그리고 스레드 2 는 자원 B를 점유하고 있는 상태에서 자원 A이 필요한 상황이다. \n하지만 스레드 1은 자원 B가 필요한 상황에서 자원 A을 빌려줄 수 있는 상황이 아니고, \n스레드 2또한 자원 A이 필요한 상태에서 자원 B를 빌려줄 수 없는 상황인 것이다.\n이처럼 다수의 쓰레드가 같은 lock을 동시에, \n다른 명령에 의해 획득하려 할 때 서로 절대 불가능한 일을 계속적으로 기다리는 상황을 이야기 한다.\n\n\n\n"},{"excerpt":"스레드란? img.png 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이…","fields":{"slug":"/9/"},"frontmatter":{"date":"September 12, 2025","title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB","tags":["운영체제"]},"rawMarkdownBody":"\n## 스레드란?\n\n---\n\n![img.png](스레드.png)\n\n
\n\n스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다.\n\n또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다.\n\n마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이 여러 기능을 수행할 수 있습니다.\n\n
\n\n### 프로세스와 스레드\n\n---\n\n스레드를 이해하기 위해서는 프로세스와 엮어서 설명하고자 합니다.\n전통적인 CPU는 하나의 프로세스만 처리할 수 있었습니다. 메모장, 워드, 게임등 많은 프로세스가 하나의 실행\n흐름을 가지고 한 번의 하나의 부분만 실행되는 프로세스입니다.\n\n![img.png](단일스레드 프로세스.png)\n\n이런 프로세스를 단일 스레드 프로세스라고 부릅니다.\n\n
\n\n하지만, 스레드라는 개념이 도입되면서 하나의 프로세스가 한 번에 여러가지 일을 동시에 처리하는 것이 가능해졌습니다.\n프로세스를 구성하는 명령어를 동시에 처리하는것이 가능해졌습니다.\n\n![img.png](멀티스레드 프로세스.png)\n\n
\n\n그림을 통해 스레드를 보게 되면 스레드는 '프로세스를 구성하는 실행의 흐름 단위'라고 표현 가능 할 것입니다.\n\n왜냐하면, 하나의 프로세스 안에 여러가지 스레드가 있고 각각의 작업 흐름을 가지며 프로세스가 하는 일을 병렬적으로 만들어\n주기 때문입니다.\n\n
\n
\n\n## 스레드 메모리 구조\n\n---\n\n![img.png](메모리구조.png)\n\n스레드의 메모리 구조를 이해하기 위해서는 이전 프로세서의 구조를 상기해봐야 합니다.\n\n프로세스는 스택, 힙, 데이터, 코드 영역을 각자 가진다고 합니다.\n스레드는 '프로세스를 구성하는 실행 흐름의 단위'라고 했고, 이 떄문에 스레드는 프로세스의 메모리 구조의 대부분을 공유해서\n사용한다. 그렇기 때문에 여러 스레드의 작업이 하나의 프로세스 안에서 이루어져도 동시작업이 가능한 이유입니다.\n\n
\n\n그렇다면 어떻게 스레드는 프로세스와 스레드간 데이터를 공유하는 것일까?\n아래 그림을 통해서 보게되면\n\n
\n\n![img.png](스레드자원공유.png)\n[사진출처](https://gmlwjd9405.github.io/2017/10/01/basic-concepts-of-development-os.html)\n\n
\n\n우선 하나의 프로세스안에 코드, 데이터, 힙, 스택 영역이 존재합니다. 그리고 프로세스 내부의 개별적인 스레드가 존재합니다.\n\n스레드가 레지스터, 프로그램 카운터, 스택을 개별적으로 가지는 핵심 이유는 독립적인 실행 흐름을 보장하기 위해서입니다.\n\n프로그램 카운터는 각 스레드가 서로 다른 코드 위치에서 실행될 수 있도록 현재 실행 지점을 개별 추적하고, \n\n레지스터는 각 스레드의 작업 데이터를 독립적으로 저장합니다. \n이를 통해 CPU가 스레드 간 전환할 때 현재 상태를 저장하고 복원하여 중단된 지점에서 정확히 재개할 수 있습니다.\n스택 영역을 따로 가지는 이유는 각 스레드가 독립적인 함수 호출 흐름을 가져야 하기 때문입니다. \n\n스택은 함수 호출 시 지역 변수, 매개변수, 리턴 주소를 저장하는데, 만약 스레드들이 스택을 공유한다면 한 스레드의 \n함수 호출이 다른 스레드의 함수 실행에 영향을 주어 실행 흐름이 꼬이게 됩니다. 따라서 각 스레드는 독립적인 스택을 가져 서로 다른 함수를 안전하게 호출하고 실행할 수 있습니다.\n결과적으로 이런 구조를 통해 스레드들은 힙과 데이터 영역은 공유하면서도 각자 독립적인 실행 흐름을 유지할 수 있어\n, 하나의 프로세스 내에서 여러 작업을 동시에 효율적으로 처리할 수 있게 됩니다.\n\n
\n
\n\n## TCB란\n\n---\n\n![img.png](TCB.png)\n\n스레드 제어 블록은 운영체제가 각 스레드를 관리하기 위해 유지하는 데이터 구조체입니다. \n프로세스 제어 블록(PCB)과 유사하지만 스레드 수준에서 필요한 정보들을 담고 있습니다.\n링크드 리스트 형태로 구현되어 PCB안에 해당 스레드의 TCB를 내포하고 있는 형태로 저장됩니다.\n\n
\n\n![img.png](TCB2.png)\n\n\n\n![img.png](TCB확장.png)\n\n\n
\n
\n\nTCB는 사진과 같은 형태로 저장되며, 아래와 같은 정보를 가진다.\n\n| 정보 | 설명 |\n|------------|---------------------------------|\n| 스레드 식별자 | 각 스레드를 식별하는 고유한 식별자 |\n| 스레드 상태 | 실행 준비 대기 등 스레드의 현재 상태 |\n| 프로그램 카운터 | 스레드가 다음에 실행할 명령어의 주소 |\n| 레지스터 | 스레드가 현재 사용하고 있는 CPU 레지스터의 값을 저장 |\n| 스레드 우선순위 | 스케줄링 결정에 사용되는 스레드의 우선순위 |\n| 스레드 스택 포인터 | 스택 내에서 현재 작업의 위치를 가리키는 레지스터 |\n| 스레드 문맥 정보 | 문맥 교환 시 저장되고 복원되어야 할 정보 |\n\n\n\n\n\n\n\n"},{"excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","fields":{"slug":"/8/"},"frontmatter":{"date":"September 11, 2025","title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","tags":["운영체제"]},"rawMarkdownBody":"\n## 문맥교환(Context Switching)\n\n---\n하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요?\n\n프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔을 때 이 과정을 이어받아 작업을 수행할 수 있습니다.\n\n여기서 하나의 프로세스를 실행하기 위해 필요한 정보들을 문맥(Context)라고 부르게 됩니다.\n이러한 문맥값들은 PCB속에 저장됩니다.환\n\n
\n\n![img.png](문맥교환.png)\n[사진출처](https://yoongrammer.tistory.com/53)\n\n결국 프로세스 A에서 B로 프로세스가 넘어가는 순간에 프로세스 A정보를 백업하고 그작업이 끝난다면\n프로세스 B의 문맥을 불러오게 되며 이 것이 프로세스를 교대하는 방법입니다.\n\n문맥교환을 통해 여러개의 프로세스가 병렬적으로 시행되는 것 처럼 보이게 하지만 이러한 문맥교환은\n오버헤드가 발생할 수 있기 때문에 문맥교환이 자주일어나면 오버헤드를 신경써야 합니다.\n\n
\n
\n\n## 프로세스 상태\n\n---\n\n이전에 PCB에 기록되는 정보 중 프로세스 상태가 있다고 합니다. 여기서 말하는 프로세스 상태는 생성이 되었는지\n혹은 CPU를 사용하는지와 같은 정보를 통칭해서 프로세스 상태라고 부르게 됩니다.\n\n
\n\n프로세스 상태는 크게 다섯가지로 나뉠 수 있습니다.\n\n![img.png](프로세스 상태 전이도.png)\n[사진출처](https://thebook.io/080367/0021/)\n\n
\n\n### 1. 생성 상태\n\n프로세스를 생성 중인 상태를 생성 상태라고 부릅니다. 메모리에 적재되어 PCB를 할당받은 상태를 생성상태라고 부르게 됩니다.\n생성 상태가 끝난다고 곧바로 실행되는 것이 아닌 준비 상태가 되어 실행되기를 기다리게 됩니다.\n\n
\n\n### 2. 준비 상태\n\n준비 상태는 당장 CPU를 할당받아 실행될 수 있지만, 차례가 오지않아 기다리고 있는 상태입니다.\n이 상태에서 준비가 되면 실행 상태로 넘어 갑니다. 그리고 다른 상태에서 다시 준비 상태로도 전환이 가능합니다.\n\n준비 상태인 프로세스를 실행 상태로 전환하는 것을 디스패치 라고 부릅니다.\n\n
\n\n### 3. 실행 상태\n\n실행 상태는 CPU를 할당받아 실행 중인 상태를 지칭 합니다. 실행 상태인 프로세스는 할당된 시간 동안 CPU를 사용할 수 있습니다.\n이때 제한된 시간내 프로세스를 완료하지 못한경우 준비 상태로 전환이 되며, I/O입력처럼 대기해야 하는 상황이 생기면\n대기 상태로 넘어가게 됩니다.\n\n
\n\n### 4. 대기 상태\n\n실행 상태에서 I/O입력과 같이 프로세스가 대기해야 하는 상황이 온다면 대기 상태로 진입하게 됩니다.\n대기 상태가 끝난다고 해도 실행 상태가 되는것이 아닌 준비 상태로 넘어가게 됩니다.\n\n
\n\n### 5. 종료 상태\n\n프로세스가 종료된 상태입니다. 이 상태에 도달하면 운영체제는 PCB와 프로세스가 사용한 메모리를 정리합니다.\n\n
\n
\n\n## 프로세스 계층 구조\n\n---\n\n프로세스는 실행 도중 시스템 호출을 통해 다른 프로세스를 생성할 수 있습니다.\n\n이때 새 프로세스를 생성한 프로세스를 부모 프로세스라고 부르게 되며, 생성 된 프로세스를 자식 프로세스라고\n부르게 됩니다.\n부모의 프로세스와 자식의 프로세스는 각각 고유한 PID를 가지며 자식프로세스에서 부모프로세스 PID를 PPID로 가지고 있기도 합니다.\n\n
\n\n![img.png](프로세스 계층 구조.png)\n[사진 출처: 혼자 공부하는 운영체제 저자:강민철]\n\n
\n
\n\n## 프로세스 생성기법\n\n---\n\n그렇다면 부모 프로세스가 어떻게 자식 프로세스를 생성 할까요?\n\n그 방법은 fork, exec라는 명령어를 통해서 생성하게 됩니다.\n\n부모 프로세스는 fork를 통해 자신의 복사본을 자식 프로세스로 생성해내고, 그 복사본은 exec명령어를 통해\n자신의 메모리 공간을 다른 프로그램으로 교체합니다.\n\n
\n\n![img.png](fork.png)\n\n
\n\n좀더 자세히 설명하면 fork, exec 모두 시스템 호출로 분류 됩니다.\n부모 프로세스는 fork 시스템 호출을 통해 자신의 복사본을 자식으로써 생성합니다.\n\n여기서 자식은 부모의 복사본이기 때문에 부모 프로세스의 자원들, 예를들면 메모리의 내용, 열린 파일의 목록등을\n상속하게 됩니다. 그렇다고 해서 모든 정보가 같지는 않습니다.\n\n왜냐하면, PID나 메모리 저장구조는 고유한 정보이기 때문에 fork로 만들어진 자식은 PID, 메모리 저장위치\n처럼 고유한 정보에 대해서는 개별적인 값을 가지고 있습니다.\n\n
\n\n![img.png](exec.png)\n\n
\n\nfork만 사용한 프로세스는 완전한 자식 프로세스라고 명하기는 조금 어렵습니다.\nPID와 같은 고유한 값을 제외한다면 부모가 가진 리소스를 동일하게 사용하는 대체품이기 때문입니다.\n\n그렇기 때문에 자식 프로세스는 자신의 프로세스를 가지기 위해 exec 시스템 호출을 하게 됩니다.\n\nexec 호출을 진행하게 되면 자신의 메모리 공간을 새로운 프로그램으로 덮어쓰게 됩니다.\n\n코드 영역과 데이터 영역의 내용이 실행한 프로그램으로 바뀌게 되고, 나머지 영역은 초기화 됩니다.\n\n"},{"excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. ![img.png](실행중인 프로세스.png) 백그라운드…","fields":{"slug":"/7/"},"frontmatter":{"date":"September 10, 2025","title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","tags":["운영체제"]},"rawMarkdownBody":"\n## 프로세스란 무엇일까?\n\n---\n\n우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다.\n\n여기서 실행된 프로그램을 **프로세스**라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다.\n\n
\n
\n\n![img.png](실행중인 프로세스.png)\n\n
\n위 사진처럼 보이는 것보다 더 많은 프로세스가 작동하고 있는데, 여기서 사용자가 볼 수 있는 프로세스를 포그라운드 프로세스 라며 명하며,\n보이지 않는 프로세스를 백그라운드 프로세스라고 부르게 됩니다. \n\n백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는 다는 뜻은 아닌데 백그라운드 프로세스 중에서 사용자와 상호작용 하지 않고 자신의 일만을 수행하기 위해 존재하는\n프로세스를 **데몬(daemon)** 프로세스라고 명합니다.\n\n
\n\n## 프로세스 제어 블록(PCB)\n\n---\n\nCPU자원이 한정되어 있는 반면에, 모든 프로세스는 실행을 위해 CPU를 사용하여야 합니다. \n그렇기 떄문에 프로세스들은 한정된 시간 만 CPU를 사용하며 자신의 차례를 기다립니다.\n\n운영체제는 빠르게 번갈아 수행되는 프로세스의 실행 순서를 관리하고, 프로세스에 CPU와 여러가지 자원을 배분합니다.\n이를 위해 운영체제는 프로세스 제어 블록(PCB)를 이용합니다.\n\n
\n\nPCB는 커널 영역에 생성되고, 수많은 프로세스를 PCB를 통해 태그처럼 사용해 특정 프로세스를 식별하며 해당 프로세스를 처리하는데 필요한 정보를 판단합니다.\n\n즉, 가게 주인이 물건을 태그를 통해 판단하고 가격을 알 수 있고, 생산지를 알 수 있는 것처럼 PCB는 운영체제가 수 많은 프로세스를 식별하고 그 프로세스의 정보를 판단하게 돕습니다.\n\n
\n
\n\n## PCB의 구조\n\n---\n\n
\n\n![img.png](PCB.png)\n\n[사진 출처](https://binaryterms.com/process-control-block-pcb.html)\n\n
\n\n위 그림처럼 PCB는 프로세스를 식별하기 위해 여러가지 정보를 담고 있습니다. 프로세스의 ID나, \n레지스터의 값 혹은 상태같이 많은 정보를 담고있으며 이를 알아보고자 합니다.\n\n
\n\n### 프로세스 ID\n\n![img.png](프로세스ID.png)\n\n프로세스 ID(PID)는 프로세스를 식별하기 위해 존재하는 고유 ID입니다. 메모장을 두개 킨다고 할지라도 다른 프로세스ID가\n만들어지는 것처럼 중복된 활동이여도 하나의 프로세스는 고유한 ID를 가지게 됩니다.\n\n
\n\n### 레지스터 값\n\n프로세스는 자신의 실행 차례가 돌아오면 이전까지 사용했던 레지스터의 중간값들을 모두 복원합니다.\n여기에는 프로그램 카운터가 속하게 됩니다.\n\n
\n\n### 프로세스 상태\n\n현재 프로세스가 어떤 상태인 기록합니다. 입출력장치를 사용하기 위해 기다리는지 혹은 CPU를 사용하고 있는 상태인지 와 같은\n상태를 기록하며 자세한 상태는 다음장에서 설명합니다.\n\n
\n\n### CPU 스케줄링 정보\n\n프로세스가 언제, 어떤 순서로 CPU를 할당받을지에 대한 정보도 PCB에 기록됩니다.\n\n
\n\n### 메모리 관리 정보\n\n프로세스마다 메모리에 저장된 위치가 다릅니다. 그렇기 떄문에 PCB에는 해당 프로세스가 저장된 메모리 위치를 기록해야 합니다.\n\n
\n
\n\n## 프로세스의 메모리 영역\n\n---\n\n프로세스가 생성되면 커널 영역에 PCB가 생성됩니다. 그렇다면 커널 영역이 아닌 사용자 영역에는 어떤 데이터가 들어갈까요?\n\n\n![img.png](메모리구조.png)\n\n[사진출처](https://www.programmersought.com/article/98613694619/)\n\n위 그림처럼 하나의 프로세스는 크게 코드영역(Text), 데이터 영역(Bss,Gvar), 힙 영역(Heap), 스택 영역(Stack) 4가지로 나뉩니다.\n\n차례대로 설명하자면,\n\n
\n
\n\n### 코드영역 or 텍스트영역(Text)\n\n이곳에는 실행할 수 있는 기계어로 이루어진 명령어가 저장됩니다. 가공할 수 있는 데이터가 아닌\nCPU가 실행해야 하는 명령어가 담겨있기 때문에 읽기모드만 지원합니다.\n\n
\n\n### 데이터 영역\n\n프로그램을 실행하는 동안 유지되어야 하는 데이터가 저장되는 공간입니다. 대표적은 전역 변수가 이곳에 해당합니다.\n\n
\n\n### 코드영역 & 데이터 영역 공통점\n\n위 두 영역은 크기가 변하지 않습니다. 프로그램을 구성하는 명령어가 작동중에 코드 양이 늘어나는 경우가 없으니\n이 두가지 영역을 정적 할당 영역이라고 부릅니다.\n\n
\n\n### 힙 영역\n\n프로그래머가 직접 할당할 수 있는 공간입니다. 프로그래밍 과정에서 힙 영역에 데이터를 할당했다면 언젠가는 이 영역에 \n데이터를 반환해야 합니다. 그렇지 않다면 메모리 용량은 점점 줄어들어 장애가 발생할 수 있습니다.\n\n이런 문제를 메모리를 할당받고 해제 하지 않았다고 하여 누수가 발생했다. 즉 메모리 누수라고 부릅니다.\n\n
\n\n### 스택 영역\n\n스택 영역은 데이터를 일시적으로 저장하는 공간입니다.\n데이터 영역에 담기는 값과는 다르게 잠깐 쓸 데이터를 담아두는 공간입니다.\n함수를 실행하는 동안 필요한 지역변수, 매개 변수가 이곳에 해당합니다.\n그렇기 떄문에 함수가 종료되면 스택 영역에서 해당 함수에 쓰였던 변수들도 같이 없어지게 됩니다.\n\n
\n
\n\n### 힙 영역 & 스택 영역 공통점\n\n위 두 영역은 실시간으로 그 크기가 변할 수 있고 그렇기 떄문에 동적 할당 영역이라고 부르게 됩니다.\n\n그림을 보면 unused memory영역이 있는데, 스택 영역과 힙 영역이 동적이기 떄문에 힙은 아래에서 위로, 스택은 \n위에서 아래로 주소를 할당하게 됩니다. 그렇게 되면 서로 충돌없이 동적으로 값을 할당할 수 있기 때문입니다.\n\n여기서 만약에 힙이나 스택에 많은 정보가 담겨서 서로의 지점을 충돌 할 수 있는데, 그럴때 각각 stack overflow,\nheap overflow라고 부르게 됩니다.\n\n\n\n\n\n"},{"excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","fields":{"slug":"/6/"},"frontmatter":{"date":"September 09, 2025","title":"6. 동기식/비동기식 I/O의 차이와 활용 사례","tags":["운영체제"]},"rawMarkdownBody":"\n## IO란\n\n개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다.\n\n예시를 들어서\n\n- 파일 읽기/쓰기 (문서를 열거나 저장하는 행위)\n- 네트워크 통신(웹사이트 접속, 이메일 전송)\n- 데이터베이스 조회(회원 정보 검색)\n\n이런 일련의 행위는 공통적인 특징이 있는데, 물리적인 시간이 걸린다는 점입니다.\n그렇기 떄문에 IO를 어떻게 다룰까에 대한 방법또한 여러가지 존재합니다.\n\n
\n
\n\n## 동기와 비동기란\n\nIO를 다루는 방법에는 동기, 비동기에 대한 개념이 등장합니다.\n이러한 개념을 사전에 정의 하고 내려가겠습니다.\n\n### 동기 (Synchronous)\n\n프로그램에서 말하는 동기란 하나의 작업에 대해서 요청과 응답 과정을 기다리는 행위입니다.\n예를들어, WAS가 데이터베이스에 조회 요청을 하고 데이터베이스는 요청받은 데이터를 돌려줄것입니다.\n이 과정에서 WAS는 요청직후 부터 응답을 받을때 까지 과정에서 데이터베이스의 응답을 기다리게 됩니다. 이것이 동기입니다.\n\n
\n\n### 동기의 특징\n\n순차적 실행: 한 작업이 완료되어야 다음 작업이 시작\n블로킹: 현재 작업이 끝날 때까지 다른 작업은 대기\n예측 가능: 코드가 위에서 아래로 순서대로 실행\n\n
\n
\n\n### 비동기 (Asynchronous)\n\n그렇다면 비동기는 하나의 작업에 대해서 요청과 응답 과정을 기다리지 않는 행위입니다.\n예를들어, WAS가 데이터베이스에 조회 요청을 하게 되면 데이터베이스가 이를 수행하고 응답할것입니다.\n이 과정 사이에 시간동안 WAS는 본인의 다른 작업을 수행하다가 데이터베이스의 응답을 받게 됩니다.\n즉 요청과 응답 사이 기간동안 WAS는 본인의 일을 하며 무작정 기다리지 않는 것입니다.\n\n
\n\n### 비동기의 특징\n\n동시 실행: 여러 작업을 동시에 시작 가능\n논블로킹: 작업 완료를 기다리지 않고 다른 작업 진행\n콜백/Promise: 작업 완료 시 결과를 알려주는 방식\n\n
\n\n## 동기식 I/O\n\n![img.png](동기식IO.png)\n\n
\n\n동기식IO는 IO요청이 발생하였을 때 이전 동기 설명처럼 IO요청이 끝날때 까지 기다리는 방식입니다.\n프로그램이 IO작업을 요청하게 되면, 다른 동작을 수행하지 않고 멈춰서 IO작업이 리턴되기 까지 기다립니다.\nI/O작업이 완료되면 인터럽트를 통해 완료를 알리게 됩니다. 이후 CPU 제어권이 기존 프로그램에게 넘어가게 됩니다.\n\n이러한 방식의 특징은 구현이 쉽다는 특징이 있지만, 연산에 대한 기다림으로 인해 자원 낭비를 하는 특징이 있습니다.\n\n## 비동기식 I/O\n\n![img.png](비동기식IO.png)\n\n비동기식IO는 IO요청이 발생하였을 떄 이전 비동기 설명처럼 IO요청을 기다리지 않는 방식입니다.\n프로그램이 IO 작업을 요청하고, 그 작업이 완료되기를 기다리지 않고 즉시 다음 작업으로 넘어가는 방식입니다.\n\n이러한 방식의 특징은 구현의 복잡성이 높다는 것이지만, 대용량 데이터를 처리하는데 여러 IO작업을 동시에 처리해야 할 떄 유용합니다.\n"},{"excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","fields":{"slug":"/5/"},"frontmatter":{"date":"September 08, 2025","title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리","tags":["운영체제"]},"rawMarkdownBody":"\n## 인터럽트 기반 입출력\n\n---\n\n인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다.\n\n인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트를 발생시킨\n주체가 무엇인가에 따라 나뉘게 된다.\n\n대표적인 하드웨어 인터럽트는 I/O완료, 대표적인 소프트웨어 인터럽트는 시스템 콜이 있다.\n\n
\n
\n\n![img.png](Interrupts.png)\n\n이러한 인터럽트 기반 입출력의 순서를 설명하자면\n\n1. CPU가 입출력 장치에 대해 입출력 요청을 보낸다.\n2. CPU는 요청이후 다른 작업을 수행한다.\n3. 입출력 장치가 준비되면 인터럽트를 발생시킨다.\n4. CPU는 현재 실행 중인 작업을 중단하고 인터럽트 서비스 루틴(ISR)을 실행한다.\n5. 데이터를 처리한 후 , CPU는 원래 수행하던 작업을 계속 실행한다.\n\n이러한 인터럽트 기반 입출력의 단점은 인터럽트가 많이 발생하는 상황에서 CPU가 부하될 수 있다는 단점이 있다.\n\n\n
\n
\n\n## DMA(Direct Memory Access 직접 메모리 접근)\n\n---\n\nDMA방식은 이름에서 볼 수 있듯이 CPU를 사용하지 않고 입출력 장치가 직접 메로리와 데이터를 교환합니다.\n\n이것이 가능한 이유는 DMA 컨트롤러가 존재해, 메모리와 입출력 장치 사이의 데이터를 관리하기 때문입니다.\n\nDMA에서는 CPU가 전송할 데이터의 위치, 포인터, 바이트 크기만 DMA 컨트롤러에 전달하면, \nDMA가 입출력 작업을 대신 처리하고 전체 작업이 완료될 때만 CPU에 인터럽트를 보냅니다. \n이로 인해 CPU와 여러 입출력 장치가 직접 연결되던 기존 구조에서 CPU-DMA-입출력 장치 구조로 변화했고,\nCPU의 가용 시간이 현저히 증가하는 효과를 얻었습니다. \n이는 교수가 조교에게 학생 관리를 맡기고 최종 결과만 확인하는 것에 비유할 수 있으며, \n현재 DMA는 많은 컴퓨터 장치에서 보편적으로 사용되는 기술이 되었습니다.\n\n
\n
\n\n![img.png](DMA.png)\n\n
\nDMA 방식을 순서로 설명하자면\n\n1. CPU가 DMA 컨트롤러에게 입출력 요청합니다.\n2. DMA 컨트롤러가 메모리와 입출력 장치 간의 데이터 전송을 직접 수행합니다.\n3. 데이터 전송이 완료되면 DMA 컨트롤러가 인터럽트를 발생 시켜 CPU에게 완료를 알립니다.\n4. CPU는 인터럽트를 받아서 필요한 후처리 수행합니다.\n\n\n"},{"excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. img.png 멀티 프로그래밍 img.png 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하…","fields":{"slug":"/4/"},"frontmatter":{"date":"September 07, 2025","title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","tags":["운영체제"]},"rawMarkdownBody":"\n## 단일 프로세스\n\n---\n\n초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다.\n\n
\n\n![img.png](단일프로세스.png)\n\n
\nCPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 IO작업동안 CPU는 멈추게\n될것이고 그 상황에서 CPU가 놀고 있게 되는 시간이 늘어나는 것입니다.\n\n
\n\n## 멀티 프로그래밍\n\n![img.png](멀티프로그래밍.png)\n\n이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다.\n이를 멀티 프로그래밍이라고 부르며 그림처럼 CPU 사용률을 높이기 위한 목적이었습니다.\n\n하지만 이러한 방식의 문제는 앞선 프로세스가 길어질 수록 즉 IO사용처럼 비는 시간없이 순수하게 많은 시간을\n쓰게 된다면 이후 프로세스가 계속 기다려야 하는 문제가 있었습니다.\n\n
\n\n## 멀티 태스킹\n\n![img.png](멀티태스킹.png)\n\n멀티 프로그래밍 방식에서 더 나아가 모든 프로세스가 공정하게 특정 짧은 시간만 실행되게 반복한다면 길게 시행되는\n프로세스 뒤에 오는 프로세스가 기다리는 문제가 없을 것이다. 이것이 멀티태스킹을 사용하는 이유입니다.\n\n**프로세스1**에서 **프로세스2**로 작업을 스위칭 하는것을 문맥 교환(Context Switching)이라고\n부르게 되는데 이러한 문맥교환은 값싼 작업이 아니고 이러한 작업이 자주 일어나게 된다면 비효율 적인 단점이 부각되다 보니\n새로운 방식을 사용하게 됩니다.\n\n
\n\n## 멀티 프로세싱\n\n멀티 프로세싱이란 이전 멀티 태스킹과 이름은 비슷 하지만 완전히 다른 방식입니다.\n\n이전 방식은 하나의 **CPU**를 어떻게 쪼개서 사용할까라는 목적이였다면, **멀티 프로세싱**은 **CPU** 작업단위인\n코어 자체를 늘려서 여러 CPU코어가 동시에 작업하는것을 멀티 프로세싱이라고 부르게 됩니다.\n\n![img.png](멀티프로세싱.png)\n\n멀티 프로세싱은 CPU코어 수를 늘리는 방법이기 때문에, 이를 어떻게 처리할까에 대한 내용은 멀티 프로세싱 자체의 내용이 아니고 앞서 나왔던 방법론을 도입할 수 있습니다.\n그림처럼 하나의 프로세스를 여러 코어가 담당하는 방법이나, 여러 프로세스를 여러 코어가 담당 할 수 도 있습니다.\n\n### 출처\n[사진출처](https://medium.com/@ashappyasiknow/single-process-system-multi-programming-multitasking-%EC%9D%B4%EB%9E%80-9f9b65ec0311)\n"},{"excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. img.png 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비…","fields":{"slug":"/3/"},"frontmatter":{"date":"September 06, 2025","title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리","tags":["운영체제"]},"rawMarkdownBody":"\n## 이중모드\n\n---\n\n운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다.\n\n> 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요?\n\n이에 대한 답은 **이중 모드** 입니다.\n\n
\n\n\n![img.png](이중모드.png)\n\n
\n\n위 사진 처럼 **CPU**가 명령을 실행하는 방식을 **사용자 모드** 와 **커널 모드**로 나누어 사용하게 됩니다.\n\n
\n\n### 사용자 모드\n\n사용자 모드는 운영체제 서비스를 제공받을 수 없는 실행 모드입니다.\n
CPU가 해당 모드인 경우, 입출력 명령어와 같은 하드웨어 자원 접근 명령을 실행할 수 없습니다. 일반 프로그램은 기본적으로 사용자 모드로 실행됩니다.\n\n
\n\n### 커널 모드\n커널모드는 운영체제 서비스를 제공받을 수 있는 실행 모드로 커널 영역의 코드를 실행할 수 있습니다.\n
CPU가 커널 모드로 명령어를 실행하면 자원에 접근하는 명령어를 비롯한 모든 명령어를 실행할 수 있으며, 운영체제는 커널 모드로 실행됩니다.\n\n
\n\n요약 하자면 일반 응용프로그램은 평소에 **사용자 모드**를 통해서 실행 되다가 실제 운영체제의 코드를 실행하여야 하는 순간이 오면 **커널 모드**로 전환하여 실행하다가\n운영체제의 코드 실행 지점이 끝난다면 다시 **사용자 모드**로 전환되게 됩니다.\n\n이러한 방식으로 자원을 **운영 체제**로 하여금 독자적으로 관리할 수 있게 합니다.\n\n
\n\n> 사용자 모드에서 어떻게 커널모드로 전환할까?\n\n사용자 모드에서 커널모드로 전환하는 방식은 **시스템 콜**에 의해서 발생합니다.\n\n
\n\n![img.png](시스템콜.png)\n\n
\n\n그림처럼 사용자 모드로 실행되는 프로그램이 자원에 접근해야 할때 운영체제에 커널 모드로 요청을 보내게 되고 이것을 **시스템 콜**이라고 부르게 됩니다.\n\n**시스템 호출**은 **소프트 웨어 인터럽트**에 속합니다. 이러한 특징 때문에 **CPU**가 **시스템 호출**을 처리하는 순서가 **인터럽트 처리 순서**와 비슷합니다.\n\n**시스템 호출**이 발생하면 **지금까지의 작업을 백업** 하고, 커널 영역 내의 호출 하여야 하는 코드를 실행 한 뒤 다시 돌아와 기존 프로그램을 계속 실행합니다.\n\n
\n\n![img.png](시스템콜작동방식.png)\n\n
\n\n그림을 통해서 이해를 하게 되면,\n\n1. 응용 프로그램은 일반적인 작업을 수행중 운영체제 코드를 실행 하여야 하는 작업에 도달하게 됩니다.\n2. 그러면 응용프로그램은 운영체제에게 자원 접근에 대한 시스템 콜을 날리게 된다.\n3. 현재 작업을 백업하게 됩니다.\n4. 이후 응용프로그램은 운영체제의 코드를 실행합니다.\n5. 작업이 끝나면 다시 사용자 영역으로 돌아와 멈춰둔 작업을 진행합니다.\n\n이런 세부적인 순서를 진행하게 됩니다.\n\n### 출처\n[사진출처](https://hongong.hanbit.co.kr/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EB%9E%80-%EC%BB%A4%EB%84%90%EC%9D%98-%EA%B0%9C%EB%85%90-%EC%9D%91%EC%9A%A9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%8B%A4%ED%96%89%EC%9D%84-%EC%9C%84%ED%95%9C/)\n\n"},{"excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","fields":{"slug":"/2/"},"frontmatter":{"date":"September 05, 2025","title":"2. CPU 스케줄링, 시스템 자원 관리","tags":["운영체제"]},"rawMarkdownBody":"\n## CPU 스케줄링\n\n---\n\n**CPU 스케줄링**은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며, \n
모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다.\n\nCPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n
\n\n### CPU 스케줄링 원칙\n\n---\n\nCPU는 스케줄링을 하면서 두가지 원칙을 중요시 하게 됩니다.\n
\n\n1. 공정함: 특정 프로세스 실행이 무한정 대기하지 않도록 기간을 보장합니다.\n2. 우선순위: 우선순위가 높은 작업에 우선권을 제공 합니다.\n\n
\n\n### CPU 스케줄링 평가 기준\n\n---\n\nCPU는 객관적인 스케줄링을 위해 아래와 같은 평가 기준을 사용합니다.\n\n
\n\n1. CPU 사용률 - CPU가 작업을 수행하는데 사용하는 시간의 비율\n2. 처리량 - 시스템이 단위 시간당 완료할 수 있는 작업의 양\n3. 응답 시간 - 시스템이 사용자의 요청에 반응하여 첫 번째 응답을 생성하기 시작하는데 걸리는 시간\n4. 대기 시간 - 프로세스가 실행되기 위해 CPU를 할당받아 준비 상태에서 대기하는 시간의 총합\n5. 처리 시간 - 특정 작업이 시작되었을 때부터 그 작업이 완전히 끝나는데 걸리는 시간의 총합\n\n"},{"excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","fields":{"slug":"/1/"},"frontmatter":{"date":"September 04, 2025","title":"1. 운영체제의 역할과 커널의 기능","tags":["운영체제"]},"rawMarkdownBody":"\n## 운영체제란 무엇일까?\n\n---\n\n**운영체제**는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 **자원**을 **관리**하고, \n
프로세스를 관리하는 등 여러가지 일을 수행합니다.\n\n이러한 **운영체제**는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다.\n\n\n## 운영체제의 역할\n\n---\n\n### 하드웨어 관리\n\n> 운영체제는 CPU, 메모리, 입출력 장치 등 컴퓨터 하드웨어 자원을 관리합니다.\n>
여기서 말하는 **관리**란 자원의 충돌을 방지하고 사용자가 하드웨어를 **효율**적으로\n> 사용하도록 처리하는것을 의미하게 됩니다.\n\n
\n
\n\n### 프로세스 관리\n\n> 프로세스의 생성과 종료 그리고 CPU 스케줄링을 통해 프로세스의 실행 시간을 관리합니다. \n>
**멀티 태스킹**환경에서 프로세스 전환을 관리합니다.\n\n
\n
\n\n### 메모리 관리\n\n> 각 애플리케이션에 충분한 메모리 공간을 할당하는 기능을 합니다.\n>
또한 가상 메모리를 통해 실제 메모리보다 큰 주소 공간을 제공합니다.\n\n## 커널이란 무엇일까?\n\n---\n\n**커널**이란 운영체제의 핵심 기능을 담당하며, 커널은 하드웨어와 소프트웨어 애플리케이션 간 통신을 관리합니다. 커널의 대표적인 기능으로는 \n
**프로세스 관리**, **메모리 관리**, **파일 시스템**, **입 출력 관리**의 역할을 수행하게 됩니다.\n\n위 설명 처럼 **운영체제**의 핵심기능을 **커널**이 많은 부분을 담당하기 때문에 이전에 설명한 운영체제의 기능이 **커널**의 기능이라고 생각하면 됩니다.\n\n\n## 커널이 자원을 관리하는 이유\n\n---\n\n> **커널**은 어떻게 충돌 없이 자원을 관리할까요?\n\n이 질문에 대한 대답은 자원을 관리하는 지점을 **커널**을 통한 단일 진입점으로 만들게 되면서 해결 하게 됩니다.\n
\n\n> 왜 자원을 **커널**을 통해서만 관리하게 설게 했을까요? \n\n**커널**이 자원을 혼자 관리해야 하는 이유를 예시를 들어서 설명하겠습니다.\n\n유치원 수업시간에 하나의 바구니에 **테이프**, **연필**, **지우개**와 같은 문구용품을 담아두고 선생님이 학생들에게 자율적으로 사용해도 된다고 하게 된다면 어떤일이 벌어질까요?\n\n처음에는 아이들이 각자 필요한 문구 용품을 사용하겠지만 얼마 가지 않아서 **연필**을 찾는 학생,\n
**테이프**를 가지고 누가먼저 쓸지 싸우는 학생,\n
혹은 **지우개**를 망가뜨린 학생등 많은 사고가 있을 것입니다.\n\n이러한 문제가 벌어지는 이유는 공용 문구를 사용할때 **통제권**이 모두에게 있기 떄문입니다. 그렇다면 이를 해결하기 위해서\n모두에게 있는 **통제권**을 하나로 합쳐서 해결하면 되는 문제이고 이것이 자원을 사용하기 위해 **커널의 관리**를 받아야 하는 이유입니다.\n"}]}},"pageContext":{}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file +{"componentChunkName":"component---src-pages-search-jsx","path":"/search/","result":{"data":{"allMarkdownRemark":{"nodes":[{"excerpt":"서론 지금까지 가상 메모리를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다.\n이러한 행위는 한정된 메모리를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다. 그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다. 불필요한 페이지를 선별 후 스왑 아웃 한다. 프로세스에게 적절한 프레임을 할당한다…","fields":{"slug":"/jc23/"},"frontmatter":{"date":"September 26, 2025","title":"요구페이징을 잘 수행하기 위해서 필요한 것들","tags":["운영체제"]},"rawMarkdownBody":"\n## 서론\n\n---\n\n지금까지 **가상 메모리**를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다.\n이러한 행위는 한정된 **메모리**를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다.\n\n그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다.\n\n1. 불필요한 페이지를 **선별** 후 **스왑 아웃** 한다.\n2. 프로세스에게 적절한 **프레임**을 할당한다.\n\n각각 **페이지 교체 알고리즘**, **프레임 할당**이라고 부릅니다.\n\n또한, 이러한 작업은 **요구 페이징(demand paging)** 이라는 작업을 더 효율적으로 할 수 있게 돕습니다.\n\n이 글은 요구 페이징에 대해서 알아보고, 요구 페이징이 안정적으로 작동하기 위해 필연적인 페이지 교체 알고리즘과, 프레임 할당을 설명합니다.\n\n
\n
\n\n## 요구 페이징(demand paging)\n\n---\n\n프로세스를 메모리에 적재할 떄 처음부터 모든 페이지를 적재하지 않고 필요한 페이지만을 메모리에 적재하는 방식을\n**요구 페이징**이라고 부릅니다.\n\n요구 페이징은 다음과 같은 플로우로 진행됩니다.\n\n1. CPU가 특정 페이지에 접근하는 명령어를 내린다.\n2. 페이지가 메모리에 존재하면 **유효비트 1**을 나타내며 해당 프레임에 접근한다.\n3. 존재 하지 않는다면 **유효비트 0**을 나타내며 **페이지 폴트**가 발생한다.\n4. **페이지 폴트**가 발생하면 해당 페이지를 메모리로 적재하고 유효비트를 1로 설정한다.\n5. 1번을 다시 시행한다.\n\n이러한 **요구 페이징**은 필요한 페이지만 그때그때 불러서 적재 후 사용한다는 의미를 나타냅니다.\n\n**요구 페이징**을 안정적으로 수행하기 위해서는 크게 두가지를 고려해야 합니다.\n첫번째는, **요구 페이징**은 메모리 기준 **Input**작업 입니다.\n그렇다면 반대로 **Output**작업도 필요하게 됩니다.\n\n왜냐하면 메모리는 한정되고 상대적으로 덜 필요한 페이지를 **스왑아웃**하는 작업도 필요하기 때문입니다.\n\n이러한 방식을 **페이지 교체** 라고 부르며, 그중 여러가지 방식이 있기 때문에 **페이지 교체 알고리즘**으로 분류하고 명명합니다.\n\n두번째는, 한정된 프레임을 잘 배분하는 것으로 **스왑 아웃**자체를 줄일 수 있기 때문에 **프레임 할당** 또한\n**요구 페이징**을 수행하기 위해 중요합니다.\n\n
\n
\n\n# 페이지 교체 알고리즘\n\n---\n\n페이지 교체 알고리즘은 **스왑 아웃**할 페이지를 **선별**하는 알고리즘입니다.\n그렇기 때문에 어떤 **선별 기준**에 따라 알고리즘을 나누게 됩니다.\n\n일반적으로 **기준**은 **페이지 폴트** 발생 비율입니다. **페이지 폴트**는 보조기억장치로 부터\n정보를 가져와서 메모리로 할당하여 그 정보를 불러와야 하는 비효율적인 시퀀스를 가지고 있습니다.\n이러한 **페이지 폴트** 발생 비율이 적은 교체 알고리즘을 좋다고 평가합니다.\n\n그리고 **페이지 폴트 횟수**는 **페이지 참조열**을 통해서 진행합니다.\n\n가령,\n\n> 2 2 2 3 5 5 5 3 3 7\n\n이라는 페이지 참조가 발생한다면 **페이지 참조열**은 여기서 연속된 중복을 제거한 순서입니다.\n\n> 2 3 5 3 7\n\n이 해당 순서에 **페이지 참조열**이 됩니다. 이렇게 중복을 제거하는 이유는 연속된 참조는 **페이지 폴트**대상이\n아니기 때문입니다.\n\n
\n
\n\n## FIFO 페이지 교체 알고리즘\n\nFIFO 페이지 교체 알고리즘은 이름 그대로 먼저 들어온 페이지를 먼저 내보내는 방식입니다.\n\n![img.png](fifo.png)\n\n해당 그림을 통해 설명하면 2,3,1 번의 순서대로 프레임에 쌓이게 되며 마지막 1번 페이지가 적재 된 이후에는\n프레임이 가득차게 됩니다. 이후 3번은 이미 적재된 페이지이기 때문에 넘어갑니다.\n\n5번 페이지가 적재 되는 시점에 프레임은 가득 차있고, 5번페이지는 적재 되어있지 않기 때문에 **선별**후 **교체**하는\n작업이 필요합니다.\n\n여기서 **FIFO**방식은 가장 먼저들어온 페이지를 내보낸다라고 설명드린것처럼 처음들어온 **2페이지** **스왑아웃** 시키게 됩니다.\n빈 공간에 필요한 **5페이지**를 넣게 됩니다.\n\n이렇게 먼저 들어온 페이지를 먼저 내보내는것을 **FIFO 교체 알고리즘**이라고 명명합니다.\n\n하지만 이러한 방식에는 큰 단점이 있는데, 먼저 들어온 페이지가 실행 내내 사용 될 수도 있습니다.\n즉, 먼저 들어왔다고 해서 교체에 대상이 되기는 합당한 이유가 아니기 때문입니다.\n\n
\n
\n\n## 2차 기회 페이지 교체 알고리즘\n\n---\n\n해당 알고리즘은 **FIFO**방식을 개선한 알고리즘 입니다. 이름 처럼 한번의 기회를 더 주는 방식입니다.\n두가지 케이스가 있습니다. 기본적으로 가장 오래된 페이지를 **스왑 아웃**한다는 방식은 같습니다.\n만약 **스왑 아웃** 시점이 오게 되면, 해당 **참조 비트**를 확인합니다.\n\nCPU에 의해서 **참조** 된적이 있다면, 해당 **참조 비트**를 0으로 바꾸고 적재 시간을 현재로 변경하며,\n**참조 비트**가 0이라면 오래되면서 참조된적도 없기 떄문에 바로 **스왑 아웃** 시켜버립니다.\n\n
\n
\n\n## 최적 페이지 교체 알고리즘\n\n---\n\n**최적 페이지 교체** 방식은 이름그대로 최적의 방안을 찾는 알고리즘입니다.\n미래를 통해 오랫동안 사용되지 않을 페이지를 **스왑아웃** 시키면서 문제를 해결합니다.\n\n![img.png](optimal_page_replace.png)\n\n해당 그림을 통해 설명하면 5번 페이지를 요청할때 페이지 폴트가 발생하고 그 과정에서 이후 미래를 고려해서\n1번이 사용되지 않는다고 판단해 1번을 **스왑 아웃**하는 방식입니다.\n\n해당 알고리즘은 **페이지 폴트**가 가장 낮습니다.\n그렇지만, 현실적인 구현이 어렵습니다. 미래를 예측하는건 어려운 작업입니다. 그렇기 떄문에 현실적으로 가능한\n알고리즘으로 여기기 보단, **페이지 폴트**가 가장 낮다는 점을 고려하여 상대적인 **성능 평가**를 목적으로 사용합니다.\n\n다른 **교체 알고리즘**의 하한선으로 잡고 비교대상으로 쓰여집니다.\n\n
\n
\n\n## LRU 페이지 교체 알고리즘 (Least Recently Used Page Algorithm)\n\n---\n\n해당 알고리즘은 **최적 페이지 교체 알고리즘**을 변형해 **미래**를 예측하는것이 아닌, **과거**를 통해\n사용되지 않은 페이지를 **스왑아웃**하는 방식을 차용합니다.\n\n'최근에 사용되지 않은 페이지는 앞으로도 사용되지 않을 것이다' 라는 점을 토대로 구성됩니다.\n\n![img.png](lru.png)\n\n페이지마다 마지막으로 사용한 시간을 토대로 최근에 가장 사용이 적었던 페이지를 교체합니다.\n해당 그림에서는 5번 페이지가 적재될 시기에 가장 오래 사용되지 않는 **2**를 **스왑아웃** 시키는것을\n알 수 있습니다.\n\n
\n
\n\n## 스래싱과 프레임 할당\n\n---\n\n요구 페이징을 잘 수행하기 위해 **페이지 폴트**를 줄이는 방식을 이야기 했습니다.\n이러한 **페이지 폴트**를 줄이기 위해 **교체 알고리즘**을 적절하게 선택하는것이 중요하단것을 알게 되었습니다.\n\n하지만, **페이지 폴트**를 발생시키는 이유에는 **프레임 수의 한정**이라는 문제가 있습니다.\n프레임이 무지막지 하게 많다면 모든 프로세스를 할당할 수 있을것이고, 그렇게 되면 **스왑 아웃**이 발생할 이유도 없을것입니다.\n\n그렇기 때문에 **페이지 폴트**의 발생을 줄이기 위해 적절하게 **프레임을 할당**하는 것또한, 중요합니다.\n\n역으로 자원을 효율적으로 사용하고, 가상메모리와 같은 기법을 사용하면서 **페이징에 프로세스 실제 실행시간보다\n더큰 리소스를 사용**하는 문제가 생길 수도 있습니다.\n\n이렇게 배보다 배꼽이 큰 상황, 플어서 이야기하면\n> 페이징 시간이 프로세스 실제 실행보다 더 길어지는 상황\n\n을 **스레싱**이라고 부르게 됩니다.\n\n
\n\n### 멀티 프로그래밍 정도\n\n![img.png](degree_of_multiprogramming.png)\n\n해당 그래프는 세로축 **CPU 이용률**, 가로축 **메모리에 올라와 있는 프로세스 수**를 나타냅니다.\n그래프에서 알 수 있듯이 프로세스수가 증가하면, CPU이용률 또한 증가합니다 하지만 일정 가로축을 넘어가면\n**CPU**이용률이 줄어드는 것을 알게 됩니다.\n\n즉, 프로세스가 너무 많이 발생하면 각 프로세스에 할당된 **프레임**이 부족하고 그런 문제로 인해 **페이지 폴트**가\n자주 발생하게 됩니다.\n\nCPU를 아무리 좋은것을 사용해도 메모리 공간이 부족하면 컴퓨터 성능이 안좋아지는 이유가 이런이유입니다.\n\n
\n
\n\n# 프레임 할당\n\n---\n\n스래싱의 근본적 이유는 각 프로세스가 필요로 하는 **프레임**이 부족하기 때문입니다. 그렇기 떄문에\n운영체제는 **프레임**을 적절하게 할당할 수 있어야 합니다.\n\n이러한 **프레임 할당**을 크게 두가지로 나눌수 있습니다.\n\n1. 정적 할당 방식\n2. 동적 할당 방식\n\n
\n
\n\n## 정적 할당 방식\n\n---\n\n정적할당방식은 두가지로 나누어집니다.\n\n1. **균등할당**\n2. **비례할당**\n\n
\n\n### 균등할당\n\n균등할당은 이름에서 알 수 있듯이 모든 프로세스에 프레임을 균등하게 할당하는 방식입니다.\n프로세스가 3개가 있고, 프레임이 300개가 있다면 각 프로세스는 100개의 프레임을 할당받게 됩니다.\n\n이러한 방식은 프로세스 크기도 각자 다른 상황에서 합리적이지 못한 선택입니다.\n\n
\n\n### 비례할당\n\n크기가 큰 프로세스에 더 많은 프레임을 할당하는 방식을 비례할당이라고 부릅니다.\n하지만 이러한 방식은 **정적**이라는 한계점을 가지고 있습니다.\n\n실제 프로세스를 실행해보면 크기와 상관없이 더 많은 프레임을 필요로 하거나 그렇지 않은 프로세스들이 존재합니다.\n이러한 문제 떄문에 비례할당도 합리적이라고 할 수 없습니다.\n\n
\n\n## 동적 할당 방식\n\n---\n\n동적할당방식에는 크게 두가지로 나누어집니다.\n\n1. 작업 직합 모델(working set model)\n2. 페이지 폴트 빈도(PFF: page fault frequency)\n\n
\n\n### 작업 집합 모델\n\n작업 집합 모델에서는 '프로세스가 일정 기간 동안 참조한 페이지 집합'을 기억하며 빈번한 페이지 교체를 방지합니다.\n예를 들어 프로세스가 3초동안 20개의 페이지를 집중적으로 참조했다면 20개의 프레임을 할당하면 효율적일 것입니다.\n\n이렇게 실행 중인 프로세스가 일정 시간 동안 참조한 페이지의 집합을 **작업 집합**이라고 합니다.\n\n
\n
\n\n### 페이지 폴트 빈도\n\n![img.png](page_fault.png)\n\n페이지 폴트 빈도 방식은 해당 그래프를 통해 이루어 집니다.\n가로축은 할당된 프레임을 나타내며 세로축은 페이지 폴트율을 나타냅니다.\n할당된 프레임은 적으면 페이지 폴트가 많이 발생하는 형상이 됩니다.\n\n이러한 그래프에서 상한과 하한을 정한다음 해당 적정 구간에 들어올 수 있도록 프레임을 할당해주는\n방식을 **페이지 폴트 빈도**방식이라고 합니다.\n\n\n\n\n## 출처\n\n---\n\n[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard)\n"},{"excerpt":"연속 할당의 문제점 연속적 할당의 대표적인 문제점은 외부 단편화가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해\n필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다. 이러한 문제를 해결하기 위해서는 불연속 할당 방식 중 대표적인 페이징기법을 사용할 수 있습니다. 페이징이란? 페이징 기법은 프로세스를 일정한 단위로 자릅니다. …","fields":{"slug":"/jc22/"},"frontmatter":{"date":"September 25, 2025","title":"페이징","tags":["운영체제"]},"rawMarkdownBody":"\n### 연속 할당의 문제점\n\n---\n\n연속적 할당의 대표적인 문제점은 **외부 단편화**가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해\n필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다.\n\n이러한 문제를 해결하기 위해서는 **불연속 할당** 방식 중 대표적인 **페이징**기법을 사용할 수 있습니다.\n\n
\n
\n\n## 페이징이란?\n\n---\n\n![img.png](paging.png)\n\n페이징 기법은 프로세스를 일정한 단위로 자릅니다. 또한 프로세스가 들어갈 메모리 공간 또한 일정한 단위로 자릅니다.\n\n여기서 프로세스를 일정한 단위로 자르면 일정한 **논리 주소 공간**이 생기는데 이것을 **페이지**라고 부르며,\n일정한 단위로 잘린 메모리 **물리 주소 공간**은 **프레임**이라고 부르게 됩니다.\n\n여기서 **프레임**, **페이지**의 일정한 단위는 동일한 크기로 자르게 됩니다.\n\n이렇게 만들어진 **페이지**를 **프레임**에 할당하는 가상 메모리 관리 기법을 **페이징**기법이라고 부르게 됩니다.\n\n이렇게 일정한 크기를 정하고 불연속 할당을 수행하면 외부 단편화 문제를 줄일 수 있습니다.\n\n
\n\n### 페이징에서 스와핑\n\n![img.png](paging_swaping.png)\n\n페이징에서도 이전과 마찬가지로 **스와핑**이 사용됩니다. 차이가 있다면 기존 연속 할당 방식 스와핑은\n프로세스 전체가 스왑영역으로 넘어가지만, **페이징 스와핑**은 사용하지 않는 특정 **페이지**만 스왑아웃\n시킬 수 있습니다.\n\n이러한 방식은 이후 **가상메모리** 방식을 사용하는데 핵심이 됩니다.\n\n
\n\n## 페이지 테이블\n\n---\n\n불연속 할당 방식에는 실행순서에 대한 문제가 하나 있습니다. \n연속적 할당 방식에서는 실행순서를 CPU에게 알려줄 필요가 없습니다. 왜냐하면 실제로 물리 메모리에 연속적으로\n프로세스에 대한 정보가 있기 때문에 순서대로 실행시키면 되기 때문입니다.\n\n하지만, **불연속 할당**은 상황이 다릅니다. 메모리상 프로세스에 대한 정보가 연속적이지 않기 떄문에\n이를 실행시키는 **CPU**입장에서는 어떤 프로세스를 실행시켜야 할지 알기 어렵습니다.\n\n
\n\n![img.png](page_table.png)\n\n
\n\n이를 해결하기 위해서 **페이지 테이블**이란것을 사용합니다.\n\n**페이지 테이블**은 **페이지 번호**, **프레임 번호**를 짝지어 줍니다. 그렇게 되면 **CPU**입장에서는\n**페이지 번호**만 알고있다면 **페이지 테이블**을 통해 **프레임**으로 접근이 가능하기 때문입니다.\n\n페이지 테이블은 프로세스마다 각자의 페이지 테이블을 가지게 됩니다.\n\n
\n
\n\n## 페이지 테이블 베이스 레지스터(PTBR)\n\n---\n\n페이지 테이블은 프로세스마다 가지고 있고, 이는 **메모리**에 저장됩니다.\n\n하지만, CPU 입장에서는 결국 **페이지 테이블**의 위치를 알아야 합니다. 이러한 기능을 수행하는게\n**CPU**내의 존재하는 **PTBR**입니다.\n\n**PTBR**은 **CPU**내에 존재하고 **페이지 테이블**의 위치를 기록합니다.\n\n![img.png](ptbr.png)\n\n해당 그림처럼 특정 프로세스 작업을 수행하기 위해서 **CPU**는 해당 **PTBR**내부 프로세스의 페이지 테이블을\n조회합니다. 이후 메모리내부 해당 페이지 테이블 주소로 넘어가서 특정 프로세스의 페이지 까지 접근하게 됩니다.\n\n
\n
\n\n### 비효율적인 접근\n\n---\n\n이전 **페이지 테이블**을 참조하는데 한가지 문제가 있습니다.\n\n**CPU**는 **페이지 테이블**로 접근하고, 해당 값들을 통해 실제 **페이지**로 접근합니다.\n\n즉, 하나의 조회에 대해 두가지 접근을 수행하게 됩니다. 이러한 방식은 비효율적입니다.\n그렇기 때문에 **캐싱**기능을 통해 이를 해결하고 이러한 기능을 수행하는게 **TLB**입니다.\n\n
\n\n## TLB(Translation Lookaside Buffer)\n\n---\n\n![img.png](tlb.png)\n\n**TLB**는 CPU 곁에 존재하며 이는 페이지 테이블에 대한 **캐시 메모리**입니다.\n참조 지역성에 근거해 주로 최근에 사용된 페이지 위주로 가져와서 저장합니다.\n\n여타한 캐싱 기능과동일하게 리소스가 **TLB**를 통해서 나오게 되면, **히트**했다. 그것이 아니라면\n**미스**했다 라고 표현합니다.\n\n\n
\n
\n\n## 페이징에서의 주소 변환\n\n---\n\n**특정 주소**에 접근하기 위해서는 두가지 관점의 정보가 필요하게 됩니다.\n\n1. 어떤 페이지 혹은 프레임에 접근하고 싶은지\n2. 접근하려는 주소가 그 페이지 혹은 프레임으로부터 얼마나 떨어져 있을지\n\n
\n\n이중에서 1번은 기존 **페이지 번호**를 통해서 해결할 수 있습니다.\n하지만, 2번의 말은 조금 애매하게 들리는데 이를 풀어서 설명하면,\n하나의 **주소**내에서도 **논리** 혹은 **물리**주소에 따른 순차적인 주소가 있습니다.\n\nn번지, n+1번지, n+2번지.... 처럼 세부적인 **지점**을 의미합니다.\n\n1번 주소를 통해서 **페이지**혹은 **프레임**에 접근한다면 그 중 명확한 지점을 식별해야 하기 때문에\n\n페이징 시스템에서는 **페이지번호**, **변위**를 이용합니다.\n\n자세한 예시는 아래 그림을 통해서 하겠습니다.\n\n
\n\n![img.png](paging_address_trans.png)\n\n페이지, 페이지 테이블, 프레임을 나타내는 그림입니다. 이러한 그림은 특정 페이지에 접근하기 위해\n페이지 테이블을 참조하고 프레임 번호를 얻어 실제 메모리 프레임에 접근하는 시퀀스 입니다.\n\n만약 **CPU**가 5번페이지에 변위가 2인 곳에 접근하려고 하면 10번지로 접근하게 될것입니다.\n\n1. 5번 페이지는 1번 프레임에 있다.\n2. 1번 프레임의 시작 번지수는 8번지이다\n3. 8번지에 변위 2를 더해서 최종주소는 10이 된다.\n\n여기서 주의 할점은, 논리주소의 변위를 최종 물리 주소상 프레임 번지에 더하였다는 것입니다.\n> 이말은, 논리주소의 변위 == 물리주소의 변위 입니다.\n\n이것이 가능한 이유는 처음 페이징 방식을 사용할때 페이지와 프레임 변환과정에서 **특정 크기**로 나누게 되고,\n그 간격이 같기 때문에 논리주소의 변위랑 물리주소의 변위는 같다는 결론이 나옵니다.\n\n
\n
\n\n## 페이지 테이블 엔트리\n\n---\n\n페이지 테이블 엔트리는 페이지 테이블 **row**를 지칭하는 단위입니다.\n\n![img.png](pte.png)\n\n지금까지는 이러한 페이지 테이블에는 페이지 번호, 프레임 번호만 존재 한다고 설명했습니다.\n하지만, 다른 중요한 정보들도 있습니다.\n\n1. 유효 비트\n2. 보호 비트\n3. 참조 비트\n4. 수정 비트\n\n
\n\n### 유효 비트\n\n유효비트는 해당 페이지에 접근 가능한지 여부를 알려줍니다. 대표적으로 접근 불가능 한 경우는\n**스와핑**으로 인한 해당 **페이지**가 **스왑영역**으로 들어간 경우입니다.\n\n이러한 경 **페이지 폴트**라는 예외가 발생하며, 하드웨어 인터럽트 처럼 처리 됩니다.\n\n1. CPU는 기존 작업 내역을 백업합니다.\n2. 페이지 폴트 처리 루틴을 실행합니다.\n3. 페이지 처리 루틴은 원하는 페이지를 메모리로 가져온 뒤 유효 비트를 1로 변경해줍니다.\n4. 페이지 폴트를 처리했다면 이제 CPU는 해당 페이지에 접근할 수 있게 됩니다.\n\n
\n\n### 보호 비트\n\n보호비트는 페이지 보호 기능을 위해 존재합니다. 리눅스의 읽기 쓰기 권한을 생각하면 됩니다.\n해당 페이지가 읽기 전용 페이지라면 보호비트는 0을 나타내고, 읽고 쓰기가 가능하다면 1을 나타냅니다.\n\n
\n\n### 참조 비트\n\n**CPU**가 접근한적 있는지 여부를 나타냅니다. 참조된 비트라면 1을 나타내며, 그렇기 않다면 0으로 유지됩니다.\n\n
\n\n### 수정 비트\n\n해당 페이지에 데이터를 쓴 적이 있는 여부를 나타냅니다. 수정 여부를 확인해야 하는 이유는 **스와핑** 떄문입니다.\n만약 **CPU**가 페이지에 대한 내용을 수정했다면, 스와핑 과정에서 보조 기억장치에 있는 데이터 또한 수정해야 하기 때문입니다.\n\n\n\n\n\n## 출처\n\n---\n\n[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard)\n"},{"excerpt":"연속 메모리 할당 연속 메모리 할당이란 메모리에 프로세스가 그림처럼 연속적으로 배치되는 상황을 가정합니다. 프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다. 이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 스와핑과 관련이 있습니다. 스와핑이란? 메모리는 실행시킬 프로세스를 적재하게 됩니다. 하…","fields":{"slug":"/jc21/"},"frontmatter":{"date":"September 24, 2025","title":"메모리 배치기법 그리고 단편화에 대해","tags":["운영체제"]},"rawMarkdownBody":"\n## 연속 메모리 할당\n\n---\n\n![img.png](sequencial_memory.png)\n\n**연속 메모리 할당**이란 메모리에 프로세스가 그림처럼 **연속적**으로 배치되는 상황을 가정합니다.\n\n프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다.\n\n이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 **스와핑**과 관련이 있습니다.\n\n
\n\n## 스와핑이란?\n\n---\n\n메모리는 실행시킬 프로세스를 적재하게 됩니다. 하지만, 이런 프로세스들 중에 현재 실행되지 않는 프로세스는 처리해줘야 합니다.\n메모리 리소스가 한정적이기 때문입니다.\n\n여기서 말하는 실행되지 않는 프로세스의 예시는 **I/O**작업, 오랫동안 사용되지 않는 프로세스가 이에 해당합니다.\n\n
\n\n![img.png](swaping.png)\n\n
\n\n그렇다면 이러한 프로세스를 메모리에서 처리하는 방법이 필요한데 그 방법이 **스와핑** 입니다.\n\n**스와핑**은, 두가지 행위를 통해서 수행할 수 있습니다.\n\n> 스왑 아웃: 현재 실행되지 않는 프로세스가 메모리에서 스왑 영역으로 옮겨지는 것 (메모리 -> 스왑 영역)\n\n> 스왑 인: 스왑영역에 있던 프로세스가 다시 메모리로 옮겨지는 것 (스왑 영역 -> 메모리)\n\n또한 메모리에서 보조기억장치로 옮겨질때 **스왑영역**으로 프로세스를 옮겨두는데 그 영역을 **스왑 영역**이라고 합니다.\n\n
\n
\n\n## 메모리 할당 방식\n\n---\n\n프로세스는 메모리 속 비어있는 공간에 적재되어야 합니다. 비어 있는 메모리 공간에 프로세스를 연속적으로 할당하기 위해\n**세가지** 방법을 고려할 수 있습니다.\n\n1. **최초 적합(first fit)**\n2. **최적 적합(best fit)**\n3. **최악 적합(worst fit)**\n\n각방식을 아래 예시를 통해 들어보려 합니다.\n\n프로세스 A,B,C는 이미 적재되어있고, 빈 공간 A,B,C가 있습니다. 앞으로 적재할 프로세스는 20MB크기를 가지고 있으며\n적재 방식에 따라 이를 어디에 적재할지 달라지게 됩니다.\n\n![img.png](memory_stacking.png)\n\n
\n\n## 최초 적합\n\n---\n\n최초 적합은 메모리 내의 빈 공간을 순서대로 검색하다가 적재할 수 있는 공간을 발견하면 그 공간에 프로세스를 배치하는 방식입니다.\n이전 그림에서 운영체제가 빈공간 A,B,C 순서대로 검색을 하였다면 가장 먼저 검색된 A 빈공간에 적재되는 방식입니다.\n\n![img.png](first_fit.png)\n\n적재후 모습은 그림과 같으며 해당 방식은 검색을 최소화 하며 **빠른 할당**을 가능하게 하는 장점이 있습니다.\n하지만, 이후에 보게 될 **외부 단편화**가 생길 가능성이 높아지게 됩니다.\n\n
\n
\n\n## 최적 적합\n\n---\n\n최적 적합은 운영체제가 빈공간을 **모두** 검색한 후 프로세스가 적재될 수 있는 공간 중 가장 **작은 공간**에 프로세스를\n배치하는 방식입니다.\n이전 그림에서는 빈 공간 C가 가장 적합한 크기를 가진 공간이기 때문에 그곳에 적재 됩니다.\n\n![img.png](best_fit.png)\n\n적재후 모습은 그림과 같으며 해당 방식은 적재할 프로세스 크기를 고려한 방식이기 때문에 **외부 단편화**를 \n최소화 할 수 있다는 장점이 있지만, **모든**공간을 검색하는 행위가 **오버헤드**를 발생시키기 때문에 느려집니다.\n\n
\n
\n\n## 최악 적합\n\n---\n\n최악 적합은 운영체제가 빈 공간을 모두 검색한 후, 가장 큰 공간에 프로세스를 적재하는 방식입니다.\n\n![img.png](worst_fit.png)\n\n적재 후 모습은 가장 빈공간의 크기가 큰 B에 적재되는 것을 확인할 수 있습니다. 이러한 방식은\n외부 단편화의 발생 빈도도 크며, 모든 공간을 검색한다는 비효율적인 측면도 가지고 있습니다.\n\n
\n\n지금까지 **외부 단편화**라는 용어가 단점으로 설명했습니다.\n그렇다면, **외부 단편화**는 어떠한 문제일까요?\n\n
\n\n## 단편화\n\n---\n\n단편화는 크게 두가지로 나눌 수 있습니다.\n\n1. 내부 단편화\n2. 외부 단편화\n\n
\n\n### 내부 단편화\n\n![img.png](first_fit.png)\n\n내부 단편화 문제는 이전 **최초 적합** 사례에서 볼 수 있습니다.\n빈공간A의 크기는 30MB인데 적재한 프로세스는 20MB입니다. 이런경우 10MB의 빈공간이 생기게 되고 이러한 비어있는\n공간을 **내부 단편화**가 발생했다고 표현합니다.\n\n
\n\n### 외부 단편화\n\n![img.png](first_fit.png)\n\n외부 단편화 문제는 이전 **최초 적합** 사례를 이어서 설명하겠습니다.\n현재 그림속 비어있는 공간은 **80MB**입니다. 하지만 해당 공간에 **80MB**크기의 프로세스를 적재할 수 없습니다.\n이유는, 빈 공간이 연속적인것이 아닌 프로세스C에 의해 끊어져있기 때문입니다.\n\n이처럼, 프로세스를 할당하기 어려울 만큼 작은 메모리 공간들로 인해 메모리가 낭비되는 현상을 지칭합니다.\n\n이러한 외부 단편화를 해결할 수 있는 대표적인 방안은 메모리를 **압축**하는 방법이 있습니다.\n\n
\n\n## 압축\n\n---\n\n**압축**이란 흩어져 있는 빈 공간들을 하나로 모으는 방식으로 메모리 내에 저장된 프로세스를 재배치 시켜 빈 공간을\n하나의 큰 빈 공간으로 만드는 방법입니다.\n\n이러한 방식은 단점이 있는데, 메모리의 빈공간을 모으는 작업은 시스템을 중지 시킨다는 문제가 있습니다.\n또한, 메모리를 옮기는 작업이 큰 오버헤드를 만들고, 최적화 방법에 대한 정답을 고르기가 어렵습니다.\n\n\n\n\n\n\n\n\n## 출처\n\n---\n\n[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard)\n\n\n\n\n\n\n\n"},{"excerpt":"물리주소와 논리주소 메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다.\n이 저장된 메모리의 데이터를 CPU 혹은 실행중인 프로그램이 읽어 실행하게 됩니다. 해당 그림은 두가지 관점으로 주소를 나누고 사용하는 방식을 그림으로 나타낸 것입니다. 왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요? 이유는 메모리에 저장되어 있는 정보는 변…","fields":{"slug":"/jc20/"},"frontmatter":{"date":"September 23, 2025","title":"물리주소, 논리주소 그리고 메모리 분할 방식","tags":["운영체제"]},"rawMarkdownBody":"\n## 물리주소와 논리주소\n\n---\n\n![img.png](memory_address.png)\n\n메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다.\n이 저장된 메모리의 데이터를 **CPU** 혹은 **실행중인 프로그램**이 읽어 실행하게 됩니다.\n\n해당 그림은 두가지 관점으로 **주소**를 나누고 사용하는 방식을 그림으로 나타낸 것입니다.\n\n왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요?\n\n> 이유는 메모리에 저장되어 있는 정보는 변화가 빠르고 이를 시시각각 알기어렵기 때문에\n\n가령 프로그램이 새롭게 실행될때, 삭제 될때 혹은 같은 프로그램일지라도 실행될때마다 실행되는 주소가 다르기 때문입니다.\n\n그렇기때문에 주소를 두가지 관점으로 나눠서 사용하게 됩니다.\n\n> **물리주소**란 실제로 정보가 저장된 하드웨어상 주소를 의미합니다.\n\n> **논리주소**란 실행중인 프로그램에 부여된 0번지부터 시작되는 주소를 의미합니다.\n\n여기서 주의할점은 **논리주소**는 0번지 부터 시작하는 논리적 주소이기 때문에, **고유성**이 없습니다. 하지만 **물리주소**는\n하드웨어상 주소기 때문에 **고유성**이 있습니다.\n\n
\n
\n\n## 메모리 할당 방식\n\n---\n\n**메모리 할당**이란 주기억 장치에 프로세스를 저장하는 과정입니다.\n이러한 과정은 크게 **두가지**로 나누어집니다.\n\n1. 연속 할당\n2. 불연속 할당\n\n
\n\n## 연속할당\n\n---\n\n연속 할당은 프로세스가 연속된 메모리 영역에 할당되는 방법을 말합니다.\n각 프로세스는 연속적인 메모리 주소 범위 내에 위치하게 됩니다. 이렇게 연속할당을 하게 되면\n빈공간보다 프로세스 공간이 더 작은 경우가 있는데 이러한 현상을 **단편화**라고 합니다.\n\n연속할당의 종류로는 **고정 크기 파티셔닝**, **가변 크기 파티셔닝**이 있습니다.\n\n
\n\n### 고정 크기 파티셔닝\n\n고정 크기 파티셔닝은 메모리를 고정된 크기의 파티션으로 나누어 각 파티션에 프로세스를 할당하는 방식입니다.\n예를들어, 모든 파티션을 10MB로 설정하고 파티션마다 프로세스를 할당하는 방식을 사용할 수 있습니다.\n\n이러한 방식은 모든 프로세스가 지정한 파티션 크기만큼 떨어지는것이 아니기 떄문에 효율적이지 못한 단점이 있습니다.\n\n
\n\n### 가변 크기 파티셔닝\n\n가변 크기 파티셔닝은 파티션의 크기를 유동적으로 조절하는 메모리 할당 방식입니다.\n이러한 방식은 **고정 크기 파티셔닝**보다는 효율적이지만, 메모리 공간에 어떤 프로세스를 저장해야 할지 결정하는게\n복잡합니다.\n\n
\n
\n\n## 불연속 할당\n\n---\n\n불연속 할당은 한 프로세스를 메모리 여러 곳에 분산 저장하는 방법입니다. **페이징**, **세그멘테이션** 이 있습니다.\n\n
\n\n### 페이징\n\n페이징은 프로세스의 주소 공간을 페이지라는 동일한 크기의 구획으로 나누고, 주기억 장치도 페이지와 동일한 크기의\n프레임이라는 구획으로 나눕니다. 이후 한 페이지를 한 프레임에 적재하는 방식입니다.\n\n자세한 내용은 이후에 다루게 됩니다.\n\n
\n\n### 세그멘테이션\n\n프로세스의 주소공간을 세그먼트라는 단위로 나누어 주기억 장치에 적재합니다.\n프로세스는 코드, 데이터, 스택 등으로 구성되기 때문에 각각을 한 세그먼트로 나누어서 메모리에 적재합니다.\n\n이 과정에서, base주소와, limit주소를 이용하여 프로세스가 자신에게 할당된 메모리 영역만 사용하게 합니다.\n\n\n
\n\n\n\n## 출처\n\n---\n\n[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard)\n\n\n"},{"excerpt":"교착상태란?(Dead Lock) 교착상태란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다. 교착상태를 설명하는 대표적인 예시로 식사하는 철학자 문제라는게 있습니다. 식사하는 철학자 식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습…","fields":{"slug":"/jc19/"},"frontmatter":{"date":"September 22, 2025","title":"교착상태와 해결 방법","tags":["운영체제"]},"rawMarkdownBody":"\n## 교착상태란?(Dead Lock)\n\n---\n\n**교착상태**란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다.\n\n**교착상태**를 설명하는 대표적인 예시로 **식사하는 철학자 문제**라는게 있습니다.\n\n
\n\n### 식사하는 철학자\n\n---\n\n![img.png](dpp.png)\n\n
\n\n식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습니다.\n식사를 하려면 두개의 포크를 들어야 하는 상황입니다.\n\n이를 순서도로 표현하면\n\n1. 생각을 하다가 왼쪽 포크를 들 수 있다면 든다.\n2. 생각을 하다가 오른쪽 포크를 들 수 있다면 든다.\n3. 왼쪽, 오른쪽 포크를 모두 집어들면 정해진 시간동안 식사를 한다.\n4. 식사 시간이 끝나면 오른쪽 포크를 내려놓는다.\n5. 나머지 왼쪽 포크도 내려놓는다.\n6. 1번부터 반복한다.\n\n
\n\n위와같은 상황일때 모든 철학자가 왼쪽 포크를 들고 있거나, 반대쪽 포크를 들고 있다면 식사는 영원히 끝나지 않습니다. 이유는 포크라는 자원은\n철학자의 수만큼 존재하고 각 철학자는 두개의 포크를 원하는 상태에서 모든 포크를 얻을때까지 가디라기 떄문에, 모든 철학자가 포크를 기다리기만 하는\n상황이 발생합니다.\n\n이러한 문제는 **일어나지 않을 사건을 기다리며 진행이 멈춰 버리는** **교착상태**와 같습니다.\n\n여기서 철학자를 **프로세스 혹은 스레드** 포크를 **자원** 그리고 생각하는 행위가 자원을 기다리는 것이라고 생각한다면, 프로세스와 스레드는\n**자원**을 사용하기 위해 **기다리는 행위**만 계속하는 상황이 되는것입니다.\n\n
\n
\n\n## 교착상태 발생조건\n\n---\n\n교착상태가 발생할 조건에는 네가지가 있습니다. 차례대로 **상호배제**, **점유와 대기**, **비선점**, **원형 대기**입니다. 해당 조건은\n모두 만족해야지 **교착상태**가 발생하고 하나라도 해당하지 않는다면 **교착상태**는 발생하지 않습니다.\n\n
\n\n### 1. 상호 배제\n\n교착 상태가 발생한 근본적인 원인은 해당 자원을 하나의 프로세스만 사용하기 때문입니다. 프로세스도 마찬가지로 한 프로세스가 사용하는 자원을 다른 프로세스가\n사용할 수 없을때, 교착상태가 발생합니다.\n\n### 2. 점유와 대기\n\n프로세스는 자원을 할당받은 상태에서 다른 자원을 할당받기를 기다린다면 교착 상태가 발생할 수 있습니다. 이렇게 **자원을 할당받은 상태에서 다른 자원을\n할당받기를 기다리는 상태**를 **점유와 대기**라고 합니다.\n\n### 3. 비선점\n\n이전에 **선점**, **비선점**이라는 개념을 보았습니다. **비선점**이란 프로세스나 스레드가 자원을 할당받으면 그 작업이 끝나기전까지 자원을 뻇어갈수 없다는\n특징이 있었습니다. 교착상태가 발생하는 원인은 **점유와 대기**상태중 필요한 자원을 **선점**할수 없이 계속 기다리기만 하여서 발생하는 문제 입니다.\n\n### 4. 원형 대기\n\n**자원 할당 그래프**가 원의 형태로 그려지면 교착 상태가 발생할 수 있습니다. 이렇게 프로세스들이 원의 형태로 자원을 대기하는 것을 **원형 대기**라고 합니다.\n\n
\n
\n\n## 교착상태 해결방법\n\n---\n\n교착상태를 해결하는 방법은 크게 세가지로 나눌수 있습니다.\n> 1. 예방\n> 2. 회피\n> 3. 검출 후 회복\n\n
\n
\n\n## 예방을 통한 해결\n\n---\n\n예방이란 교착상태 발생 조건에 부합하지 않게 자원을 분배하는 방식입니다.\n\n이전에 말한 **교착상태**발생 조건에 해당하는 네 가지 중 하나를 충족 하게 되면 **교착 상태**를 해결할 수 있습니다.\n\n### 상호 배제를 없애는 방식\n\n> 이론적으로는 가능하나, 모든 자원이 상호 배제를 없애기는 어렵기 때문에 비현실적이다.\n\n
\n\n### 점유와 대기를 없애는 방식\n\n> 특정 자원이 먼저 점유를 수행하여 작업을 끝내고, 다른 프로세스에게 자원을 몰아주는 방식으로 해결이 가능합니다.\n> \n> 하지만 이런 방식은 자원 활용률이 낮아 진다는 문제가 있습니다.\n\n
\n\n### 비선점 조건을 없애는 방식\n\n> 비선점 방식으로 작업을 다루게 되면 교착상태가 발생해도 자원을 뺏어 해결 할 수 있습니다.\n> \n> 하지만, 이런방식의 문제점은 모든 자원이 비선점 기능을 사용할 수 없다는 점에 있습니다.\n> \n> 예를들어, 프린터는 비선점 방식을 수행하는 자원입니다.\n\n
\n\n### 원형 대기 조건을 없애는 방식\n\n> 모든 자원에 번홀을 붙이고 오름차순으로 자원을 할당하면 원형 대기는 방생하지 않습니다.\n> 마치 원형이 아닌, 선형으로 자원을 나열하는 방식입니다.\n> \n> 이런 방식은 자원에 일일이 번호를 붙여야 한다는점과, 특정 번호는 자원 활용률이 떨어질수 있다는 문제가 있습니다.\n\n
\n
\n\n## 회피를 통한 해결\n\n---\n\n회피 방식에서는 교착 상태 발생이 한정된 자원을 무분별하게 할당하였서 그렇다고 가정합니다. 그렇기 때문에 회피방식은 자원을 신중하게 할당하는 방식으로\n해결합니다.\n\n즉, 교착 상태가 발생하지 않을 정도의 양만큼만 자원을 배분하는 방법을 **교착 상태 회피**라고 부릅니다.\n\n**안정 상태**, **불안전 상태**가 있습니다. 각각 교착상태가 발생하지 않는 상태를 **안정상태**, 발생할 가능성이 있는 상태를 **불안정 상태**라고 부릅니다.\n\n**회피**를 통해 교착상태를 해결하기 위해 **안전 순서열**을 고려해서 문제를 해결합니다.\n\n> 안전순서열: 교착 상태 없이 안전하게 프로세스들에 자원을 할당할 수 있는 순서를 의미합니다.\n\n
\n\n내용을 종합하면 **안전 순서열**이 있고 그것을 사용할때 상태를 **안정상태**, 안전 순서열이 없을 때 상태는 **불안정상태**라고 부르게 됩니다.\n\n
\n
\n\n## 교착 상태 검출 후 회복\n\n---\n\n마지막으로, 교착상태를 피하기 위해서는 **검출**, **회복** 방식을 사용합니다.\n\n두가지 방식을 고려할 수 있는데,\n\n1. 선점을 통한 회복\n2. 프로세스 강제종료\n\n
\n\n### 선점을 통한 회복\n\n교착 상태가 해결될 때까지 한 프로세스씩 자원을 몰아주는 방식입니다. 교착 상태가 해결될 떄까지 다른 프로세스로부터 자원을 빼앗고 할당하는 방식입니다.\n\n
\n\n### 강제종료를 통한 회복\n\n교착 상태에 놓인 순간 모든 프로세스를 종료 하는 방법 혹은 프로세스를 하나씩 종료해서 확인해보는 방법이 있습니다.\n\n전자는 가장 확실하지만 모든 작업에 대한 진행사항을 잃을 가능성이 있고, 후자는 전자보다 손실에 대한 부담은 적지만 오버헤드가 커진다는 단점이 있습니다.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## 출처\n\n---\n\n[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard)\n\n"},{"excerpt":"상호배제(Mutual Exclusion) 상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다. 일상생활에서 비유하면, 화장실 사용과 같습니다.\n한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다.\n컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 …","fields":{"slug":"/jc18/"},"frontmatter":{"date":"September 21, 2025","title":"상호배제와 동기화 기법","tags":["운영체제"]},"rawMarkdownBody":"\n## 상호배제(Mutual Exclusion)\n\n---\n\n상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다.\n\n일상생활에서 비유하면, 화장실 사용과 같습니다.\n한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다.\n컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 프로세스만 사용할 수 있어야 합니다.\n\n
\n\n## 왜 상호배제가 필요할까?\n현대 운영체제는 멀티태스킹 환경에서 여러 프로세스가 동시에 실행됩니다.\n이때 프로세스들이 공유하는 자원(메모리, 파일, 데이터베이스 등)에 동시에 접근하면 다음과 같은 문제가 발생할 수 있습니다.\n\n### 1.경쟁 상황(Race Condition)\n\n두 프로세스가 동시에 같은 데이터를 수정하려 할 때, 실행 순서에 따라 결과가 달라지는 상황입니다.\n예를 들어, 은행 계좌 잔액을 동시에 업데이트하는 두 거래가 있다면, 최종 잔액이 예상과 다를 수 있습니다.\n\n### 2. 데이터 일관성 파괴\n\n여러 프로세스가 동시에 데이터를 수정하면 데이터의 무결성이 깨질 수 있습니다. 이는 시스템 전체의 신뢰성에 큰 영향을 미칩니다.\n\n
\n
\n\n## 동기화 기법\n\n---\n\n이런 **상호 배제**에 대해 방지하는 방법으로는 **뮤텍스**, **세마포어**, **모니터** 기법이 있습니다.\n\n
\n
\n\n## 뮤텍스 락(Mutex lock)\n\n---\n\n**뮤텍스 락**의 풀네임은 **Mutual Exclusion Lock**입니다. 즉 상호 배제 단어에 lock을 붙인 단어와 일치합니다.\n\n이 말은 상호배제를 구현하기 위해 **Locking**방식을 사용하는 방법입니다.\n\n**뮤텍스 락**은 화장실 사용에 비유해보겠습니다.\n\n![img.png](toilet.png)\n\n
\n\n화장실은 한칸에 한사람만 받을 수 있습니다. 칸에 사람이 들어가있다면 해당 칸에 다른 사람이 들어올 수 없습니다.\n다른 사람이 들어오는 시점은 먼저 사용하던 사람이 해당 칸을 나가게 되면 사용할 수 있습니다.\n\n이 내용을 설명하는 이유는, 위 방식의 흐름이 뮤텍스 락과 동일하기 때문입니다.\n\n간단한 **뮤텍스락**을 코드를 통해서 보겠습니다.\n\n**자물쇠**에 해당하는 전역변수 하나, 그리고 해당 **자물쇠**를 잠구고, 푸는 두가지 함수만 있으면 구현가능합니다.\n\n
\n
\n\n````java\nacquire(){\n while (lock == true){\n .....\n }\n \n lock = true;\n}\n````\n\n````java\nrelease(){\n lock = false;\n }\n````\n\n
\n\n해당 함수들은 차례대로 화장실 문이 잠겼는지 확인하고 잠기지 않았다면 들어가서 잠구는 함수 **Acquire**,\n그리고 화장실을 나올때 잠금을 해제 하는 **Release**로 볼 수 있습니다.\n\n이 함수를 아래 수도코드 처럼, 임계 구역 들어가기전, 나온 후 에 사용하게 되면\n\n````java\nacquire();\n// 임계 구역\nrelease();\n````\n\n**lock**여부를 확인 한 후, 들어가도 되면 본인이 **lock**을 걸고 이미 **lock**이 걸려있다면\n임계 구역 코드 전에서 계속 기다리게 됩니다.\n\n
\n\n### 뮤텍스 락의 단점\n\n\n하지만, 이런 방식에는 큰 문제가 있는데 **바쁜대기(Busy Wait)** 을 수행하게 됩니다.\n명칭 그대로 대기를 하는 상황임에도 바쁘게 행동하는 것을 말하게 됩니다.\n\n**대기**를 하는 상황에 행동을 하는것은 **lock 확인**작업에 **CPU**를 사용하겠다는 것을 의미하고,\n이런 기다림은 해당 **lock** 이 풀릴떄까지 지속됩니다. 즉, 비효율적입니다.\n\n
\n
\n\n## 세마포(semaphore)\n\n---\n\n**세마포**는 동기화 방식중 하나입니다. **뮤텍스 락**과 비교하면 공유자원의 갯수를 다루는 방식이 다릅니다.\n**뮤텍스 락**은 공유자원이 하나라고 가정하고 라킹을 수행하지만, **세마포**는 공유 자원이 여러 개 있을경우\n각 프로세스는 해당 공유자원에 접근이 가능합니다.\n\n마치 공중화장실에서 화장신 칸 수 만큼 공유자원이 있고, 각 칸에 사람이 들어가는 것을 관리하는 방식입니다.\n\n![img.png](semaphore.png)\n\n**세마포**는 사진과 같은 **철도 신호기**에서 유래한 단어 입니다. 그렇기 때문에 철도 신호와 같은 방식을 사용합니다.\n\n**뮤텍스 락**은 공유 자원을 **잠금**, **해제**를 수행하면서 해당 자원을 관리하지만,\n\n**세마포**의 경우 **빨간불**, **초록불** 처럼 가도 되는지, 멈춰야 하는지 상태를 알려줍니다.\n\n**세마포**도 간단하게 코드로 구현이 가능합니다.\n\n먼저 **공유자원의 갯수**를 나타내는 전역 변수 한개와, 임계구역에 들어가도 되는지, 기다려야 할지 알려주는 함수 **Wait**,\n그리고 기다리고 있는 프로세스에게 **이제 출발하라**를 나타내는 **Signal**함수가 있습니다.\n\n
\n\n````java\nwait() {\n while(S <= 0){\n \n }\n S--;\n}\n````\n\n````java\nsignal() {\n S++;\n}\n````\n\n위 코드를 차례대로 **Wait**, **Signal**함수를 구현한것이고 전역 변수 S의 값이 양수, 즉 사용해도 되는\n공유자원이 있을 경우 **Wait**함수의 while문을 탈출합니다.\n\n그 경우 사용가능한 공유 자원 갯수를 하나 줄입니다.\n\n````java\nwait();\n// 임계 구역\nsignal();\n````\n\n임계 구역을 나오게 되면 signal이 수행될것이고, 사용가능한 자원을 하나 반납하게 될것입니다.\n\n
\n\n근데 while문이 있다면 **뮤텍스락**처럼 **바쁜 대기** 상태가 발생할 수 있다는걸 암시하게 됩니다.\n하지만 이는 세마포가 **CPU**를 사용하지 않게 구현하며 해결할 수 있습니다.\n\n
\n\n## 세마포가 busy wait를 해결하는 방법\n\n---\n\n아래 두가지 함수를 통해서 세마포는 **busy wait**를 해결합니다.\n\n````java\nwait(){\n S--;\n if ( S < 0){\n add this process to Queue;\n sleep();\n }\n}\n````\n\n````java\nsignal(){\n S++\n if ( S <= 0){\n remove a process p from Queue;\n wakeup(p);\n } \n}\n````\n위 방식은 이전처럼 while문을 통한 접근 가능여부를 체크하는 것이 아닌 만약 접근 불가능 한경우(사용가능한 공유 자원이 없을떄)\n해당 프로세스의 **PCB**를 **세마포**를 위한 **대기 큐**에 넣습니다.\n\n프로세스는 대기 큐에 들어가게 되면서 이후 해당 **PCB**를 **준비 큐**로 돌리기 전까지 **CPU**자원을 잡아 먹지 않게 됩니다.\n\n
\n
\n\n## 모니터\n\n---\n\n세마포 기법 자체는 동기화도구로써 좋은 효능을 보여주지만, 사용자 측면에서 불편한 점이 있다.\n임계 구역에 앞뒤로 wait, signal 함수를 사용하고 휴먼에러로 인한 실수가 발생한다면 예기치 못한 결과를 발생시킬 수 있기 때문이다.\n\n이에 **모니터**라는 동기화 도구가 생기게 된다.\n\n모니터는 공유 자원과, 공유 자원에 접근하기 위한 인터페이스를 묶어 관리합니다.\n\n
\n\n![img.png](monitor.png)\n\n
\n\n이를 위해 모니터를 통해 공유 자원에 접근하고자 하는 프로세스를 큐에 삽입하고, 큐에 삽입된 순서대로 하나씩 공유 자원을 이용하도록 합니다.\n모니터는 공유 자원을 다루는 인터페이스에 접근하기 위한 큐를 만들고, 모니터 안에 항상 하나의 프로세스만 들어오도록 하여 **상호 배제**를 수행합니다.\n\n또한, 모니터는 **실행 순서**를 제어하는 동기화 또한 수횅합니다. **조건 변수**를 사용해서 실행 순서를 제어하게 됩니다.\n\n
\n\n![img.png](monitor2.png)\n\n
\n\n해당 그림처럼 기존 **상호 배제를 위한 큐**가 아닌 **조건 변수**에 대한 큐가 있습니다. 이 **조건 변수**는 기존처럼 **wait**, **signal** 연산을\n수횅할 수 있습니다.\n\n상호 배제를 위한 큐에서 가장 선두에 있는 프로세스A보다 특정 프로세스B가 더 먼저 시행되어야 한다면, B가 수행되기 전까지 앞선 프로세스들은 **wait** 연산을 통해\n조건 변수에 대한 큐에서 대기하게 되고, 그렇게 대기를 하게되면 최우선 시행되는 프로세스는 **B**가 될것입니다. 이런 형태로 모니터는 실행 순서를 제어합니다.\n\n## 출처\n\n---\n\n[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard)\n\n"},{"excerpt":"공유자원 동시에 실행되는 프로세스에서 공통으로 사용하는 자원을 우리는 공유자원이라고 부릅니다. 임계구역(Critical Section) 공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 임계 구역이라고 부릅니다. 두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한…","fields":{"slug":"/jc17/"},"frontmatter":{"date":"September 20, 2025","title":"임계구역과 경쟁상태","tags":["운영체제"]},"rawMarkdownBody":"\n### 공유자원\n\n---\n\n동시에 실행되는 프로세스에서 **공통**으로 사용하는 자원을 우리는 **공유자원**이라고 부릅니다.\n\n
\n
\n\n## 임계구역(Critical Section)\n\n---\n\n공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 **임계 구역**이라고 부릅니다.\n\n두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한 프로세스의\n작업이 마무리되면 그제서야 기다렸던 프로세스가 임계 구역에 진입 합니다.\n\n![img.png](critical_section.png)\n\n\n
\n
\n\n## 경쟁상태(Race Condition)\n\n---\n\n**임계 구역**은 두 개 이상의 프로세스가 동시에 실행되면 안 되는 영역이지만, 잘못된 실행으로 여러 프로세스가\n**공유 자원**을 사용하는 경우에 문제가 발생합니다.\n이러한 문제를 **경쟁 상태**라고 합니다.\n\n이러한 **경쟁 상태**는 데이터의 일관성이 깨지는 문제를 발생시킵니다.\n\n
\n
\n\n## 운영체제가 임계구역 문제를 해결하는 세가지 원칙\n\n---\n\n### 1. 상호배제: 한 프로세스가 임계 구역에 진입했다면 다른 프로세스가 들어올 수 없다.\n### 2. 진행: 임계구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세는 들어갈 수 있어야 한다.\n### 3. 유한 대기: 한 프로세스가 임계구역에 진입하고 싶다면 언젠가는 임계구역에 들어갈 수 있어야 한다.(무한정 대기x)\n\n## 출처\n\n---\n\n[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard)\n"},{"excerpt":"병행성(Concurrency) 병행성은 다른 말로 동시성이라고 부르는 용어입니다.\n이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 컨텍스트 스위칭을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다.\n이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실…","fields":{"slug":"/jc16/"},"frontmatter":{"date":"September 19, 2025","title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성","tags":["운영체제"]},"rawMarkdownBody":"\n## 병행성(Concurrency)\n\n---\n\n![img.png](concurrency.png)\n\n\n병행성은 다른 말로 **동시성**이라고 부르는 용어입니다.\n이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 **컨텍스트 스위칭**을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다.\n이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실행되는 것은 아닙니다.\n\n동시성의 핵심 키워드는 **동시에 처리되게 보이는것**입니다.\n\n
\n
\n\n## 병렬성(Parallelism)\n\n---\n\n![img.png](parallelism.png)\n\n병렬 처리는 프로그램의 독립적인 작업을 동시에 실행할 수 있는 능력입니다. 이러한 작업은\n다른 프로세스 코어 단위에서, 혹은 분산 시스템 처럼 완전히 다른 컴퓨터에서 동시에 실행될 수 도 있습니다.\n\n병렬성의 핵심 키워드는 **실제로 동시에 처리되고 있는것**입니다.\n\n\n
\n
\n\n## 동기화\n\n---\n\n동시다발적으로 실행되는 프로세스들은 공동의 목적을 수행하기 위해 서로 협력하며 영향을 주고 받기도 합니다.\n조금 전 설명했던 **동시성**, **병렬성** 모두 동시다발적으로 수행되는 환경입니다.\n\n이런 환경의 예시를 하나들면, 워드 프로세스가 있습니다. 해당 프로세스는 글을 쓸수도 있고, 쓰여진 글을 읽을 수도 있고,\n맞춤법을 검사하는 기능도 있습니다. 하지만 해당 프로세스가 따로 동작하는 것이 아닌 모두 하나의 프로그램처럼 보여지고 있습니다.\n\n이런 상황을 **동시 다발적**이란 표현을 통해 하고, 이런 동시 다발적인 상황의 **수행 시기**를 맞춰주는 것이\n**동기화**라고 합니다.\n\n
\n\n### 수행 시기를 맞추다?\n\n이전에 설명한 **수행 시기**를 맞추다는 말은 추상적입니다.\n\n이를 두가지 관점으로 볼 수 있습니다.\n\n1. 실행 순서 제어: 프로세스를 올바른 순서대로 실행하는것\n2. 상호 배제: 동시에 접근해서는 안 되는 자원에 하나의 프로세스만 접근하는 것\n\n다시 말해 **동기화**는 실행 순서를 제어하는 **동기화**와, **상호 배제**를 위한 동기화가 있습니다.\n\n
\n
\n\n## 1. 실행 순서를 제어하는 동기화\n\n---\n\n![img.png](execution_order.png)\n\n실행 순서를 제어한다는 것은 요리 레시피 순서를 지키는것과 같습니다.\n재료를 준비하고, 손질하고, 요리하는 이런 일련의 과정을 지켜 보았을 때\n재료 손질이 준비보다 먼저일 수 없고, 요리또한 손질보다 먼저일 수 없습니다.\n\n프로세스도 마찬가지로 무언가를 읽게 하였는데 읽은 대상이 생성 되어있고, 작성되어있어야 합니다.\n이런 것을 **실행 순서**라고 표현하며 이것을 지키게 하는 것을 **동기화**라고 표현합니다.\n\n\n
\n
\n\n## 2. 상호 배제를 위한 동기화\n\n---\n\n**상호 배제**란 공유가 불가능한 자원의 동시 사용을 피하기 위해 사용하는 알고리즘입니다.\n여기서 말하는 공유가 불가능한 자원은 실제로 공유하면 안되는 자원이 아닌, 동시 사용하는 경우 문제가 발생하는\n자원입니다. \n\n아래 예시를 통해서 보면\n\n![img.png](mutual_exclusion.png)\n\n프로세스A는 현재 잔고에서 2만원을 더하고, 프로세스B는 현재 잔고에서 5만원을 더합니다.\n이러한 경우 총합 7만원을 더하는 형태가 될것입니다.\n\n하지만 프로세스A가 값을 더하고(12만원) 저장하기 전에 **콘텍스트 스위칭**이 일어난다면 다음 프로세스B는\n저장하기 전 값을 조회하고(10만원) 자신의 값을 저장할것 입니다(15만원).\n다시 프로세스 A로 돌아오면 12만원을 저장하고 프로세스 B로 돌아오면 15만원을 저장합니다.\n이과정에서 서로의 결과를 무시하는 방향으로 진행되고 최종적으로 마지막에 저장한 값은 다른 프로세스의 결과를\n반영하지 않는 상태가 됩니다.\n\n이런 상황은 동시에 사용하는 자원에 대해 **동기화**를 이루지 못해서 발생한 경우이고, 이 경우 **상호 배제를 위한 동기화**\n를 진행해야 합니다.\n\n
\n
\n\n## 출처\n\n---\n\n[동시성, 병렬성 출처](https://www.baeldung.com/cs/concurrency-vs-parallelism)\n[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard)\n"},{"excerpt":"다단계 큐 스케쥴링(Multilevel queue scheduling) 멀티 레벨 스케줄링은 우선순위 스케줄링의 발전된 형태입니다.\n아래 그림을 통해 설명 하면, 이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데,\n멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다. 가장 높은 우선순위에 있는 큐들을 처리하고,…","fields":{"slug":"/jc15/"},"frontmatter":{"date":"September 18, 2025","title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링","tags":["운영체제"]},"rawMarkdownBody":"\n## 다단계 큐 스케쥴링(Multilevel queue scheduling)\n\n---\n\n멀티 레벨 스케줄링은 **우선순위** 스케줄링의 발전된 형태입니다. \n아래 그림을 통해 설명 하면,\n\n
\n\n![img.png](multilevel_queue.png)\n\n
\n\n이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데, \n멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다.\n\n가장 높은 우선순위에 있는 큐들을 처리하고, 가장 높은 우선순위 큐가 비게 된다면 그 아래 우선순위의 큐를 처리하게 됩니다.\n그림을 통해 이해하자면, 우선순위 0 -> 우선순위 1 -> 우선순위 2 이렇게 처리하게 되는것입니다.\n\n멀티레벨 큐의 특징으로는 각각의 큐들을 개별적으로 핸들링 할 수 있습니다.\n예를들어, 특정 큐의 타임 슬라이드와 다른 큐의 타임 슬라이드를 다르게 처리 한다던가, 혹은 스케줄링 방식 자체를\nFCFS를 적용하고 다른 곳에서는 라운드로빈을 적용하는것 처럼 개별적인 핸들링이 가능합니다.\n\n
\n
\n\n### 다단계 큐 스케쥴링 문제점\n\n---\n\n다단계 큐 스케줄링의 문제점으로는 **기아** 현상이 있습니다.\n\n멀티레벨 큐 방식에서는 큐간의 이동이 불가능합니다. 그렇기 떄문에 우선순위가 낮은 곳에 배정받은 프로세스들은\n이전에 보았던 **에이징**방식을 사용할수 없습니다. 그렇기 때문에 이러한 방식은 우선순위가 올때 까지 기다려야 하는\n기아 현상을 문제로 가지고 있습니다.\n\n이러한 방식의 해결법은 아래 설명할 다단계 피드백 큐 스케줄링으로 해결이 가능합니다.\n\n
\n
\n\n## 다단계 피드백 큐 스케줄링(multilevel feedback queue scheduling)\n\n---\n\n![img.png](multi_feedback_queue.png)\n\n
\n\n다단계 피드백 큐 스케줄링 같은경우는 프로세스들이 큐 사이로 이동할 수 있습니다. 그렇기 때문에 이전 방식에서 보았던\n**기아**현상을 직접적으로 해결할 수 있습니다.\n\n
\n\n### 다단계 피드백 큐 스케줄링 특징\n\n\n이러한 이동가능한 점 때문에 **멀티 레벨 큐**와 다른 점이 있습니다.\n**멀티 레벨 피드백 큐**는 처음 생성된 프로세스가 우선순위가 가장 높은 큐로 삽입이 됩니다. 그 이후 CPU를 할당받고\n타임슬라이드 동안 실행되며, 이 실행이 끝나게 된다면 다음 우선순위 큐로 넘어 갑니다(우선순위가 낮아짐). 또 다음 우선순위\n큐에서 실행이 끝나지 않는다면 또 다음 우선순위로 넘어가고 이 과정을 반복합니다.\n\n이렇게 우선순위가 낮아지는 방식을 사용함으로써 자동으로 **CPU 버스트**가 많은 프로세스는 우선순위가 낮아지고,\n**IO 버스트**가 많은 프로세스는 상대적으로 우선순위가 높아질것입니다.\n\n### 기아 해결\n\n또한, 프로세스들이 이동가능 하기 때문에 우선순위가 낮아져 **기아**상태에 빠진 프로세스에는 **에이징**기법을 적용해\n다시 우선순위를 높이게 됩니다.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"},{"excerpt":"스케줄링 알고리즘 개요 스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다. 비선점 스케줄링 선입 선처리 스케줄링 (FCFS) 최단 작업 우선 스케줄링 (SJF) 선점 스케줄링 라운드 로빈 스케줄링 최소 잔여 시간 우성 스케줄링 (SRT) 우선순위 스케줄링 비 선점 스케줄링 선입 선처리 스케줄(FCFS) FCFS는 준비 큐에 들…","fields":{"slug":"/jc14/"},"frontmatter":{"date":"September 17, 2025","title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)","tags":["운영체제"]},"rawMarkdownBody":"\n## 스케줄링 알고리즘 개요\n\n---\n\n스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다.\n\n
\n\n- 비선점 스케줄링\n - 선입 선처리 스케줄링 (FCFS)\n - 최단 작업 우선 스케줄링 (SJF)\n\n
\n\n- 선점 스케줄링\n - 라운드 로빈 스케줄링\n - 최소 잔여 시간 우성 스케줄링 (SRT)\n - 우선순위 스케줄링\n\n
\n\n# 비 선점 스케줄링\n\n
\n
\n\n## 선입 선처리 스케줄(FCFS)\n\n---\n\n![img.png](fcfs.png)\n\n
\n\nFCFS는 **준비 큐**에 들어가있는 순서대로 CPU를 할당하는 간단한 스케줄링 입니다.\n\n하지만, FCFS 방식에는 **호위 효과**라는 문제가 있습니다.\n\n그림을 보면 프로세스 A, B, C순서대로 실행되며 각각 실행 시간이 17, 5, 2 ms가 걸리게 됩니다.\n이상황에서 프로세스 B는 실행 상태가 되기 위해 최소 17ms를 기다려야 하며, 프로세스 c는 22ms를 기다리게 됩니다.\n\n> 이러한 현상을 **호위 효과(Convoy effect)** 라고 하며 이것이 FCFS 스케줄링의 단점입니다.\n\n
\n
\n\n하지만, 이러한 FCFS 방식도 배치 처리 시스템이나 작업 길이가 거의 비슷하고 사용자와 상호 작용이 필요하지 않는 환경에는\n적합하며, 멀티프로그래밍이나 실시간 시스템에서는 부적합합니다.\n\n
\n
\n\n## 최단 작업 우선 스케줄링(SJF)\n\n---\n\n![img.png](sjf.png)\n\n
\n\n최단작업 우선 스케줄링(SJF)는 이전 FCFS방식에서 **호위 효과**를 억제하기 위해 사용하는 방식입니다.\n\n**호위 효과**는 실행시간이 긴 프로세스 때문에 다른 프로세스가 기다리는 시간이 길다는 문제가 있고,\n이러한 문제를 실행시간이 짧은 프로세스를 먼저 시행되게 하여 해결하는 방식입니다.\n\n그림을 통해 보면 FCFS방식의 평균 대기시간은 13ms인 반면에 SJF방식의 편균대기 시간은 3ms로 줄어든것을\n확인할 수 있습니다.\n\n> 즉 SJF방식은 호위효과를 줄여 프로세스들의 평균대기시간을 줄이는 방법으로 이해하면 됩니다.\n\n하지만, 이러한 방식도 문제가 있는데, 실행 시간이 긴 프로세스가 **기아**상태에 빠지기 쉽다는 것입니다.\n\n이러한 방식은 평균 대기 시간을 중요하게 여기는 시스템에 적합하며, 실시간 시스템이나 사용자 대화형 시스템에 부적합하게 됩니다.\n\n
\n
\n\n# 선점 스케줄링\n\n
\n
\n\n## 라운드 로빈 스케줄링\n\n---\n\n![img.png](round_robin.png)\n\n
\n\n라운드 로빈 스케줄링은 선입 선처리 방식(FCFS)방식에서 **타임 슬라이스**가 더해진 방식입니다.\n여기서 말하는 **타임 슬라이스**는 CPU를 사용할 수 있는 정해진 시간을 의미합니다.\n\n그림에서처럼 타임 슬라이스가 4ms이면 한번에 4ms까지 CPU를 할당받을 수 있고, 그 이후는 큐 가장 뒤로 들어가며\n콘텍스트 스위칭이 일어나게 됩니다.\n\n
\n\n> 라운드 로빈 방식의 중요한 포인트는 **슬라이스 크기**입니다.\n\n만약 슬라이스 크기가 지나치게 크다면 **FCFS**방식과 다를게 없을 것이고, 지나치게 작다면 콘텍스트 스위칭으로 인한\n오버헤드가 많이 발생할 것입니다.\n\n
\n
\n\n## 최소 잔여 시간 우선 스케줄링 (SRT)\n\n---\n\n![img.png](srt.png)\n\n
\n\n최단 작업 우선 알고리즘(SJF) 그리고 라운드 로빈 알고리즘을 합친 형태입니다.\n즉 작업 시간이 짧은 프로세스를 먼저 실행하되, 타임슬라이스 보다 큰 프로세스는 다시 큐 뒤로 보내고 작업을 이어가는 방식입니다.\n\n위 알고리즘은 특이한 점이 있어서 상세히 설명하겠습니다.\n\n
\n\n### SRT 동작 방식\n\n1. 새로운 프로세스가 도착하면 그 프로세스의 남은 실행 시간을 계산합니다\n2. 준비 큐에 있는 프로세스 중에서 현재 실행 중인 프로세스를 포함하여 가장 짧은 실행 시간을 가진 프로세스에 CPU를 할당합니다\n3. 만약 새로운 프로세스가 도착하고 현재 실행 중인 프로세스 보다 남은 실행 시간이 더 짧다면 현재 프로세스는 중단되고 CPU는 새 프로세스에 할당되는 '선점'이 발생합니다.\n4. 선점이 발생하면 운영체제는 콘텍스트 스위칭으로 CPU자원을 현재 프로세스에서 새 프로세스로 교체합니다.\n5. 선점된 프로세스는 준비 큐로 이동합니다.\n\n
\n\nSRT또한 SJF와 비슷한 장 단점을 공유하는데, 평균 대기 시간을 최소화 하는 장점을 가지지만, 작업 시간이 긴\n프로세스는 CPU 할당을 받기 어렵다는 단점이 있습니다.\n\n
\n
\n\n## 우선 순위 스케줄링\n\n---\n\n우선순위 스케줄링은 우선순위를 부여하고, 가장 높은 우선순위를 가진 프로세스부터 실행하는 알고리즘 입니다.\n만약 같은 우선순위가 있다면 선입 선처리로 처리 됩니다.\n\n이러한 우선순위 알고리즘 방식은 기아(Starvation) 현상을 동반하며 이는 에이징 방식으로 해결가능 하다고 이전 파트에서 설명했으니\n넘어가겠습니다.\n\n\n\n\n\n\n\n\n\n## 출처\n\n---\n\n[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard)\n\n[SRT 출처](https://devshovelinglife.tistory.com/977)\n\n\n\n\n\n\n"},{"excerpt":"선점형? 비선점형? 개요 CPU 스케줄링은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다. 여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다. 선점형 스케줄링 선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다. …","fields":{"slug":"/jc13/"},"frontmatter":{"date":"September 16, 2025","title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법","tags":["운영체제"]},"rawMarkdownBody":"\n## 선점형? 비선점형? 개요\n\n---\n\n**CPU 스케줄링**은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다.\n\n여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다.\n\n
\n
\n\n## 선점형 스케줄링\n\n---\n\n> 선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다.\n\n즉, 어떤 프로세스가 CPU라는 자원을 사용하고 있음에도 운영체제가 CPU를 사용중인 프로세스로부터 자원을 강제로 빼앗아 다른 프로세스에 할당할 수 있는\n스케줄링 방식을 의미합니다.\n\n다르게 표현한다면 어떠한 프로세스도 CPU를 독점할 수 없다는 말입니다.\n\n선점형의 예시중 하나는 지금까지 보았던, 특정 주기마다 CPU에 대한 할당 권한을 다른 프로세스에게 넘겨주는 방식이 있습니다.\n\n
\n\n![img.png](preemptive.png)\n\n
\n
\n\n## 비 선점형 스케줄링\n\n---\n\n비선점형 스케줄링이란 하나의 프로세스가 자원을 사용하고 있다면 그 프로세스가 종료되거나 \n스스로 대기 상태에 접어들기 전까진 다른 프로세스가 끼어들 수 없는 스케줄링입니다.\n\n다르게 표현한다면 특정 프로세스가 CPU를 사용하기 시작했다면 자원 사용을 독점할 수 있는 방식입니다.\n\n
\n\n![img.png](non_preemptive.png)\n\n
\n
\n\n## 선점, 비선점의 장 단점\n\n---\n\n대부분의 운영체제는 **선점형 스케줄링**를 사용중입니다. 그럼에도 **비선점형 스케줄링**를 사용하는 곳이 있는데 그것은 각자의 장 단점이 존재하기 때문입니다.\n\n
\n\n- 선점형 스케줄링 장점\n\n> 선점형 스케줄링은 어는 한 프로세스의 자원 독점을 막고 프로세스들에 골고루 자원을 분배 할 수 있다는 장점이 있습니다.\n\n
\n\n- 선점형 스케줄링 단점\n\n> 콘텍스트 스위칭이 빈번하기 떄문에 오버헤드가 많이 발생합니다.\n\n
\n
\n\n- 비 선점형 스케줄링 장점\n\n> 상대적으로 선점형 보다 콘텍스트 스위칭에 대한 오버헤드가 작게 발생합니다.\n\n
\n\n- 선점형 스케줄링 단점\n\n> 하나의 프로세스가 작업이 끝나기를 기다려야 하기 때문에, 모든 프로세스가 골고루 자원을 사용할 수 없습니다.\n\n\n
\n
\n\n## 기아 상태(Starvation)\n\n---\n\n기아 상태란 우선순위가 밀린 프로세스가 영원히 자신의 우선순위까지 순서가 오지 못해 실행되지 못하는 상태를 기아 상태라고 합니다.\n\n
\n
\n\n## 기아 상태 해결법\n\n---\n\n이러한 기아 상태를 해결하기 위한 방법으로는\n\n**에이징** 기법을 활용하는 것입니다.\n\n기아 상태가 발생하는 이유는 항상 자신보다 높은 우선순위를 가지는 프로세스가 존재하기 떄문입니다.\n\n**에이징** 기법은 준비큐에서 대기가 길어진 프로세스들에게 우선순위를 조금씩 높여주는 방식을 사용합니다.\n결국 조금씩 우선순위가 높아진다면 언젠가는 해당 프로세스가 실행될 수 있게 됩니다.\n\n"},{"excerpt":"CPU 할당? 지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용\n하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등\nCPU사용에 …","fields":{"slug":"/jc12/"},"frontmatter":{"date":"September 15, 2025","title":"CPU 스케줄링의 목적과 스케줄러의 종류","tags":["운영체제"]},"rawMarkdownBody":"\n## CPU 할당?\n\n---\n\n지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용\n하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등\nCPU사용에 여러 변수가 있습니다.\n\n한가지 의문점은, 누가? 어떻게? CPU를 할당하는지 배운적은 없습니다.\n여기서 CPU라는 리소스에 대한 사용을 결정짓는건 운영체제입니다.\n그리고 오늘 글의 주제인 CPU 스케줄링은 운영체제가 CPU라는 자원을 배분하는 행위를 지칭합니다.\n\n
\n
\n\n## CPU 스케줄링 우선순위\n\n---\n\n![img.png](priority.png)\n\n운영체제는 많은 프로세스에게 공정하게 CPU라는 공용자원을 배분하기 위해 고려해야 하는것이 우선순위 입니다.\n우선순위라는 기준을 매겨야 하는 이유는\n운영체제는 어떤 프로세스는 당장 처리해야 할 중요성을 띄거나, IO작업이 많거나, CPU 사용시간 자체가 길거나처럼 각자의 사정이 있고, 이 사정 가운대 효율적으로 자원을 배분해야 하기 떄문입니다. \n\n
\n\n'우선순위가 높다'라는 표현은 CPU 사용에 우선권을 가집니다. 즉 먼저 처리되어야 한다 라는 뜻입니다.\n대표적으로 우선순위가 높은 프로세스는 입출력이 많은 프로세스 입니다.\n(입출력 처리가 많은 프로세스가 우선순위가 높은 이유는 아래에서 설명합니다.)\n\n대부분의 프로세스는 I/O 작업과 CPU처리를 번갈아가면서 수행하게 됩니다. 이 말은 프로세스 상태 변화에서 실행, 대기를 번갈아 가면서 사용한다는 뜻입니다.\n그렇지만 모든 프로세스가 동일한 비율로 I/O와 CPU처리를 하는것은 아닙니다. 여기서 CPU작업의 비율이 많다면 **CPU 집중 프로세스**라고 하게 되며, 반대로 I/O작업의\n비율이 많다면 **입출력 집중 프로세스** 라고 부르게 됩니다.\n\nCPU집중 프로세스는 실행상태가 많고, 입출력 집중 프로세스는 대기 상태가 많으니 입출력 집중 프로세스를 빠르게 대기 상태로 넘겨주는 것이 CPU사용에 대해서 더 효율적인\n방법일것입니다. 그렇기 떄문에 입출력 처리가 많은 프로세스가 우선순위가 높습니다.\n\n여담으로, CPU를 이용하는 작업을 **CPU 버스트**, 입출력을 이용하는 작업을 **입출력 버스트**라고 부르게 됩니다.\n\n
\n
\n\n이러한 우선순위는 **PCB**에 기록됩니다. **PCB** 우선순위 기준으로 먼저 처리할 프로세스를 결정하고 처리하게 됩니다.\n\n
\n
\n\n## 스케줄링 큐\n\n---\n\n![img.png](queue_scheduling.png)\n\n우선순위는 **PCB**에 기록되지만, 운영체제가 매 CPU 할당 과정마다 **PCB**를 확인하고 결정하는건 비효율 적인 방식입니다.\n그렇기 때문에 프로세스는 마치 '줄을 서는것'처럼 대기하게 됩니다. 이것을 **스케줄링 큐**라고 부르게 됩니다.\n\n
\n\n![img.png](ready_queue.png)\n\n
\n\n운영체제는 메모리로 적재되고 싶은 프로세스들을 큐에 삽입하여 줄을 세우고, CPU를 사용하고 싶거나, 특정 입출력장치를 사용하거 싶은 프로세스들을 줄세웁니다.\n이 과정에서 사용할 자원에 따라 다른 큐에서 대기하게 됩니다.\n\n운영체제가 관리하는 큐로는 **준비큐**와 **대기큐**로 이루어 져 있습니다. **준비 큐**는 말그대로 CPU를 이용하고 싶은 프로세스들이 대기하게 되고,\n\n
\n\n![img.png](wait_queue.png)\n\n
\n\n**대기 큐**는\n입출력장치를 이용하기 위한 대기 상태에 돌입한 프로세스들이 서는 줄입니다.\n큐에 들어와 있다고 해도 항상 순서대로 작동하는 것은 아니고 **우선 순위**를 고려합니다.\n\n
\n\n## 출처\n\n---\n\n[이미지 출처](https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard)\n"},{"excerpt":"동시성 이슈란? 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면 11가 됩니…","fields":{"slug":"/jc11/"},"frontmatter":{"date":"September 14, 2025","title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","tags":["운영체제"]},"rawMarkdownBody":"\n\n## 동시성 이슈란?\n\n---\n\n
\n\n![img.png](concurrency.png)\n\n
\n\n동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다.\n\n예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면 11가 됩니다. 하지만 스레드 a와 b는 좋아요 카운트에 동시에 접근해서 초기값 10을 받은 상태라면\n스레드 b는 늘어난 11라는 숫자대신 10을 기준으로 값을 줄이게 됩니다. 그럼 최종 결과는 10이 아닌 9라는 값으로 나오게 됩니다.\n\n이처럼 멀티 스레드 환경에서는 하나의 자원에 동시에 접근하게 되면 이러한 문제가 발생할 수 있습니다.\n\n
\n
\n\n## 스레드 안전\n\n---\n\n그럼 우리가 추구해야 할 문제는 스레드 안전한 멀티 스레드 프로그래밍을 구현할 수 있어야 한다. 이것을 구현하는\n방법에 대해 이야기 하려고 합니다.\n\n
\n
\n\n## 스레드 안전 여부 판단\n\n---\n\n1. 전역 변수나 힙, 파일과 같이 여러 스레드가 동시 접근 가능한 자원을 사용하는가\n2. 핸들과 포인터를 통한 데이터의 간접 접근이 가능한가?\n3. 부수 효과를 가져오는 코드가 있는가?\n\n
\n
\n\n## 스레드 안전을 지키기 위한 4가지 방법\n\n---\n\n1. 상호 배제(Mutual Exclusion)\n\n
\n\n- 공유 자원에 하나의 Thread만 접근할 수 있도록 세마포어/ 뮤텍스락을 통제하는 방법입니다.\n\n
\n\n2. 원자 연산(Atomic Operation)\n\n
\n\n- 공유 자원에 접근할 때 원자 연산을 이용하거나 원자적으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현하는 방법입니다.\n- Atomic\n - 공유 자원 변경에 필요한 연산을 원자적으로 분리한 뒤에 실제로 데이터의 변경이 이루어지는 시점에 Lock을 걸고, \n 데이터를 변경하는 시간 동안 다른 쓰레드의 접근이 불가능하도록 하는 방법입니다.\n\n
\n\n3. Thread-Local Storage (스레드 지역 저장소)\n\n
\n\n- 공유 자원의 사용을 최대한 줄이고 각가의 쓰레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는 방법입니다.\n- 일반적으로 공유 상태를 피할 수 없을 때 사용하는 방식이며, 전역 변수 사용을 자제하라는 뜻으로 생각하면 됩니다.\n\n
\n\n4. Re-entrancy (재진입성)\n\n
\n\n- 쓰레드 호출과 상관 없이 프로그램에 문제가 없도록 작성하는 방법입니다.\n- 어떤 함수가 한 스레드에 의해 호출되어 실행 중이라면 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 옳바르게 주어져야 합니다.\n- 쓰레드끼리 독립적으로 동작할 수 있도록 코드를 작성하는 것으로 생각하면 됩니다.\n\n
\n
\n\n\n\n\n"},{"excerpt":"멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술입니다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것입니다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부…","fields":{"slug":"/jc10/"},"frontmatter":{"date":"September 13, 2025","title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","tags":["운영체제"]},"rawMarkdownBody":"\n![img.png](multi_process.png)\n\n멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술입니다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것입니다.\n\n
\n
\n\n### 어떻게 멀티 프로세스를 생성할까?\n\n멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부모 프로세스가\n여러개의 자식 프로세스를 생성합니다.\n\n부모 프로세스는 자식 프로세스의 PID를 알고있으며 자식또한 PID와 PPID를 알고있어\n서로 통신이 가능합니다.\n\n이런 성질은 각각 독립적이지만 통신이 가능하게 만들었고 멀티 프로세스의 대표적인 예가\n브라우저의 탭이라고 할 수 있습니다.\n\n브라우저 탭은 문제가 발생해서 닫아야 하는 상황이여도 다른 탭까지 닫히지 않고 개별적으로\n운용을 할 수 있는걸 기억해보면 독립적이란 말을 더 잘 이해할 수 있을것이다.\n\n
\n
\n\n## 멀티 프로세스의 장점\n\n
\n\n1. 안정성\n\n멀티 프로세스의 안정성은 각각의 프로세스가 독립적이기 떄문에 가능합니다.\n대표적인 예로 좀전에 설명을 했던 특정 브라우저 탭이 문제가 발생하여 닫아야 하는 상황에서\n같은 브라우저의 다른 탭까지 닫히지는 않습니다.\n이런것이 독립적인 성격에 의한 안정성이라고 할 수 있습니다.\n\n
\n
\n\n## 멀티 프로세스의 단점\n\n
\n\n1. 문맥교환 (Context Switching) Overhead\n\n멀티 태스킹을 이루는 기술인 문맥 교환 과정에서 성능 저하가 발생할 수 있습니다.\n프로세스를 컨텍스트 스위칭 하면, CPU는 다음 프로세스의 정보를 불러오기 위해\n메모리를 검색하고, CPU 캐시 메모리를 초기화하며, 프로세스 상태를 저장하고, \n불러올 데이터를 준비해야 하기 떄문에, 빈번한 문맥교환이 발생하고 이 비용은 곧 오버헤드로 발생할 수 있습니다.\n\n
\n
\n\n2. 자원 공유 비효율성\n\n프로세스는 독립적인 메모리를 가지고, 멀티 프로세스는 독립적인 메모리 공간의 합일 것입니다.\n그렇기 때문에 메모리 비효율성을 초래합니다.\n\n
\n
\n\n## 멀티 스레드\n\n---\n\n![img.png](multi_thread.png)\n\n
\n\n이전에 보았던 것처럼 스레드는 하나의 프로세스 내에 있는 실행 흐름입니다.\n멀티 스레드는 하나의 프로세스 안에 여러개의 실행흐름을 가지는 것입니다.\n멀티 스레드 또한 멀티 프로세스 처럼 여러개의 작업을 동시 실행 할 수 있습니다.\n\n이전에 보았던 것처럼 멀티 프로세스는 브라우저의 여러개의 탭을 통해 예시를 들었습니다.\n하지만, 멀티 스레드는 같은 브라우저라 할지라도 동일탭에 여러 실행 흐름을 말하게 되고 \n예를들어 네트워크 처리 스레드, 검색 스레드 와 같이 동일한 프로세스 내 기능들을 말하게 됩니다.\n\n
\n
\n\n## 멀티 스레드의 장점\n\n---\n\n### 프로세스보다 스레드가 가벼움\n\n스레드는 프로세스보다 용량이 가볍다. 이유는 데이터, 코드, 힙 영역을\n프로세스와 공유해서 사용하기 때문에 내장된 정보다 프로세스보다 작기 떄문입니다.\n그렇기 때문에 스레드를 제거하는 작업이 프로세스를 제거하는 작업보다 가볍습니다.\n\n
\n
\n\n### 자원의 효율성\n\n멀티 스레드는 하나의 프로세스 내에서 스택영역을 제외한 영역을 공유하기 때문에\n프로세스 간 통신을 사용하지 않고도 자원의 공유가 가능하여 자원을 효율적으로 사용할 수 있습니다.\n\n
\n
\n\n### Context Switching 비용 감소\n\n스레드 문맥 교환 또한 오버헤드가 존재하지만, 프로세스 문맥교환과 비교했을 때,\n상대적으로 오버헤드가 적습니다.\n\n이유는 프로세스 컨텍스트 스위칭 비용은 스위칭할 때마다 CPU 캐시에 있는 내용을 모두 초기화하고,\n새로운 프로세스 정보를 CPU 캐시에 적재해야 하기 떄문입니다.\n하지만, 스레드 문맥교환은 스레드 개별적인 정보만 교체하면 되기 떄문에 비용이 상대적으로 낮습니다.\n\n
\n
\n\n## 멀티 스레드의 단점\n\n멀티 프로세스는 개별적인 작업으로 인해 독집적이고, 각자의 문제를 전파하지 않는다고 합니다.\n\n하지만, 멀티 스레드는 하나의 스레드가 문제가 발생하면 다른 스레드들고 영향을 받아 전체가 종료가 될 수 있습니다.\n\n
\n
\n\n## 데드락\n\n데드락이란 하나의 자원을 사용하기위해 여러 곳에서 접근했고, 그상황에서 교착상태가 일어났을때\n여러대의 스레드가 서로 대기하면서 무한정 기다리는 현상을 데드락이라고 합니다.\n\n예를들어, 스레드 1 은 자원 A을 점유하고 있는 상태에서 자원 B가 필요한 상황입니다. \n그리고 스레드 2 는 자원 B를 점유하고 있는 상태에서 자원 A이 필요한 상황입니다. \n하지만 스레드 1은 자원 B가 필요한 상황에서 자원 A을 빌려줄 수 있는 상황이 아니고, \n스레드 2또한 자원 A이 필요한 상태에서 자원 B를 빌려줄 수 없는 상황인 것입니다.\n이처럼 다수의 쓰레드가 같은 lock을 동시에, \n다른 명령에 의해 획득하려 할 때 서로 절대 불가능한 일을 계속적으로 기다리는 상황을 이야기 합니다.\n\n\n\n"},{"excerpt":"기아 상태와 CPU 스케줄링 프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다.\n그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나,\n너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고\n이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다.\n이를 컴퓨팅에서…","fields":{"slug":"/hs5/"},"frontmatter":{"date":"September 12, 2025","title":"5. CPU 스케줄링","tags":["운영체제"]},"rawMarkdownBody":"\n## 기아 상태와 CPU 스케줄링\n\n프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다.\n그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나, \n너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고\n이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다.\n이를 컴퓨팅에서는 기아 현상이라고 하는데,\n이로 인해 프로세스들에게 CPU 자원 할당을 배분해주는 CPU 스케줄링이 개발되었고,\n운영체제에 반드시 필요로 하게 되었습니다.\n\n> 기아 현상에 대한 대표적인 해결 방법은 에이징 기법을 이용하는 것입니다.\n> 오랫동안 대기한 프로세스의 우선순위에 대해 가중치를 주어,\n> 처음에 우선순위가 낮아도 언젠가는 우선순위가 높아져 기아 현상을 막을 수 있습니다.\n> 이와 같이 CPU 스케줄링에서는 이러한 문제 해결을 위한 다양한 방식들이 있습니다. \n\n## 프로세스 우선 순위\n\n스케줄링을 지정하는 것은 순서를 지정하는 것과 같습니다.\n그런데 어떻게 프로세스들 간의 순위를 공정하게 지원하고 있을까요?\n\n### 순차방식\n\n가장 단순하게 생각해보면 요청이 들어온 순서대로 할당하는 방식입니다.\n그러나 이 방식은 빨리 처리해야 하는 프로세스가 있을 수 있는 상황에서 대응하지 못한다는 것입니다.\n\n예시로 CPU를 많이 사용하는 프로세스가 I/O 작업을 하는 프로세스 보다 늦게 들어올 경우,\n순서상으로는 뒤에 있어야 하지만, CPU 자원을 할당한다는 측면에서 볼 떄에는 앞 순위로 두는 것이 효울적일 것입니다.\n\n### 우선순위 지정 방식\n\n위 순차적인 방식이 아닌, 별도의 우선순위를 지정하는 방식도 있습니다.\n이때, 우선순위에 대한 정보는 PCB에 저장이 됩니다.\n\n이로 인해 프로세스의 중요도에 맞게 프로세스가 CPU를 이용할 수 있도록 운영체제가 부여하는 것이 우선순위이며,\n운영체제는 PCB를 기반으로 어떤 프로세스가 CPU를 얼마나 사용하게 될 것인지 등을 결정합니다.\n \n프로세스 우선순위는 간단한 명령어나 프로그램 등으로 확인이 가능한데, \n일부 우선순위의 경우에는 사용자가 직접 설정 가능한 것도 있습니다. \n\n### 스케줄링 큐\n\n프로세스가 여러 개일 경우, 다음 CPU 자원을 이용할 프로세스를 선택하기 위해 매번 모든 프로세스들의 PCB를 다 뒤져보는 것은 매우 비효율적일 것입니다.\n또한, CPU 말고도, 메모리, 입출력 장치를 사용하고자 하는 경우에도 비슷한 상황을 겪을 것입니다.\n\n때문에 운영체제는 어떤 자원을 이용하고자 할 때 대기 하는 스케줄링 큐를 활용하고 있습니다.\n\n이때, 큐라고 해서 반드시 선입선출(FIFO)에 국한되지 않습니다.\n\n## 선점형 스케줄링과 비선점형 스케줄링\n\n스케줄링 방식에는 선점형 스케줄링과 비선점형 스케줄링 방식이 있습니다.\n\n### 선점형 스케줄링\n\n선점형 스케줄링은 현재 CPU를 사용 중인 프로세스로부터 CPU 자원을 뺴앗아 요청한 프로세스에 할당하는 방법입니다.\n어느 한 프로세스의 자원 독점을 막고 프로세스에 골고루 자원을 배분할 수 있으나, 그 만큼 컨텍스트 스위칭 과정에서 오버헤드가 발생할 수 있습니다.\n\n### 비선점형 스케줄링\n\n비선점형 스케줄링은 현재 CPU를 사용 중인 프로세스의 작업이 끝날 때까지 기다리는 방식입니다.\n\n선점형 스케줄링과 반대되는 개념으로, 컨텍스트 스위칭에서 발생하는 오버헤드가 적지만, 한편으로는 모든 프로세스가 골고루 자원을 이용하기 어렵습니다.\n\n## CPU 스케줄링 알고리즘\n\n선점형 스케줄링과 비선점형 스케줄링을 기반으로 다양한 CPU 스케줄링 알고리즘이 있습니다. \n\n### 선입 선처리 스케줄링\n\nFCFS(First Come First Served) 스케줄링으로, 준비 큐에 삽입된 순서대로 처리하는 비선점 스케줄링 방식입니다.\nCPU를 먼저 요청한 프로세스부터 CPU를 할당합니다.\n이로 인해 프로세스들이 기다리는 시간이 매우 길어질 수 있는 부작용이 있으며,\n이를 convoy effect, 호위 효과라고 합니다.\n\n### 최단 작업 우선 스케줄링\n\nSJF(Shortest Job First) 스케줄링으로,\n사용 시간이 긴 프로세스를 나중에 실행하고, \n시간이 짧은 프로세스를 먼저 실행함으로써 평균 대기 시간을 줄일 수 있습니다.\n이 알고리즘은 기본적으로는 비선점형 스케줄링 방식에 속하지만,\n선점형과 비선점형 스케줄링 방식으로 모두 가능합니다.\n\n### 라운드 로빈 스케줄링\n\nRR(Round Robin) 스케줄링으로, \n선입 선처리 스케줄링과 시분할 시스템의 타임 슬라이스(time slice) 개념이 결합된 방식입니디.\n정해진 타임 슬라이스만큼의 시간 동안 돌아가며 CPU를 이용하게 하는 선점형 스케줄링입니다.\n\n### 최소 잔여 시간 우선 스케줄링\n\nSRT(Shortest Remaining Time) 스케줄링으로,\n최단 작업 우선 스케줄링과 라운드 로빈 스케줄링이 결합된 형태입니다.\n정해진 시간만큼 CPU를 이용하되, \n다음으로 CPU를 사용할 프로세스로는 남은 작업 시간이 가장 적은 프로세스를 선택합니다.\n\n### 우선순위 스케줄링\n\n프로세스들에 우선순위를 부여하고, 우선순위가 높은 프로세스부터 실행하는 방식입니다.\n우선순위가 같은 프로세스들은 선입 선처리 스케줄링으로 돌아가고,\n최단 작업 우선 스케줄링이나 최소 잔여 시간 스케줄링은 포괄적인 의미에서 우선순위 스케줄링에 속한다고 할 수 있습니다.\n\n### 다단계 큐 스케줄링\n\n멀티 레벨 큐 스케줄링으로도 불리는데, 우선순위 스케줄링의 발전된 형태입니다.\n우선순위 별로 준비 큐를 여러 개 사용하고, 우선순위가 높은 큐에 있는 프로세스를 먼저 실행합니다.\n우선순위가 높은 큐가 비어 있다면, 그 다음 우선순위 큐에 있는 프로세스를 처리합니다.\n이러한 방식은 프로세스 유형별로 우선순위를 구별하게 하여 관리가 쉬워집니다.\n큐 별로 타임 슬라이스를 여러 개 지정할 수도 있고, 큐마다 다른 스케줄링 알고리즘을 사용할 수도 있습니다.\n기본적으로 큐 간 이동이 불가능하기 때문에, 우선순위가 낮은 프로세스는 계속해서 우선순위가 낮을 수 밖에 없고,\n그로 인해 기아 현상을 겪을 수도 있습니다.\n\n### 다단계 피드백 큐 스케줄링\n\n멀티 레벨 피드백 큐 스케줄링으로도 불리는 이 방식은 다단계 큐 스케줄링의 발전된 형태로,\n큐 간 이동이 가능합니다.\n새로 준비 상태로 된 프로세스가 있으면 가장 우선순위가 높은 큐에 삽입합니다.\n일정 시간 즉, 타임 슬라이스 만큼 CPU를 사용할 수 있는데,\n만약 작업이 끝나지 않았다면,\n그때 우선순위가 다음으로 높은 곳에 삽입을 합니다.\n작업을 많이 있는 프로세스일수록 우선순위가 점점 낮아지게 되고,\n따라서 CPU 집중 프로세스는 상대적으로 우선순위가 낮아지고, 입출력 집중 프로세스는 높아지게 될 겁니다.\n일정 시간 이상 낮은 우선순위에서 기다리고 있던 프로세스가 있었다면 이 프로세스의 우선순위를 점차 높임으로써 기아 현상을 방지할 수 있습니다.\n다단계 피드백 큐 스케줄링은 CPU 사용 시간이 길면 우선순위가 점점 낮아지고, 동시에 어떤 프로세스가 낮은 우선순위 큐에서 너무 오래 기다리면 우선순위를 높일 수도 있습니다.\n다단계 피드백 큐 스케줄링은 복잡하지만, CPU 스케줄링의 가장 일반적인 형태로 알려져 있습니다.\n"},{"excerpt":"스레드란? 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이 여러 기능을…","fields":{"slug":"/jc9/"},"frontmatter":{"date":"September 12, 2025","title":"쓰레드의 개념, 메모리 공유 구조 및 TCB","tags":["운영체제"]},"rawMarkdownBody":"\n## 스레드란?\n\n---\n\n![img.png](thread.png)\n\n
\n\n스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다.\n\n또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다.\n\n마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이 여러 기능을 수행할 수 있습니다.\n\n
\n\n### 프로세스와 스레드\n\n---\n\n스레드를 이해하기 위해서는 프로세스와 엮어서 설명하고자 합니다.\n전통적인 CPU는 하나의 프로세스만 처리할 수 있었습니다. 메모장, 워드, 게임등 많은 프로세스가 하나의 실행\n흐름을 가지고 한 번의 하나의 부분만 실행되는 프로세스입니다.\n\n![img.png](single_process.png)\n\n이런 프로세스를 단일 스레드 프로세스라고 부릅니다.\n\n
\n\n하지만, 스레드라는 개념이 도입되면서 하나의 프로세스가 한 번에 여러가지 일을 동시에 처리하는 것이 가능해졌습니다.\n프로세스를 구성하는 명령어를 동시에 처리하는것이 가능해졌습니다.\n\n![img.png](multi_thread_process.png)\n\n
\n\n그림을 통해 스레드를 보게 되면 스레드는 '프로세스를 구성하는 실행의 흐름 단위'라고 표현 가능 할 것입니다.\n\n왜냐하면, 하나의 프로세스 안에 여러가지 스레드가 있고 각각의 작업 흐름을 가지며 프로세스가 하는 일을 병렬적으로 만들어\n주기 때문입니다.\n\n
\n
\n\n## 스레드 메모리 구조\n\n---\n\n![img.png](memory_model.png)\n\n스레드의 메모리 구조를 이해하기 위해서는 이전 프로세서의 구조를 상기해봐야 합니다.\n\n프로세스는 스택, 힙, 데이터, 코드 영역을 각자 가진다고 합니다.\n스레드는 '프로세스를 구성하는 실행 흐름의 단위'라고 했고, 이 떄문에 스레드는 프로세스의 메모리 구조의 대부분을 공유해서\n사용한다. 그렇기 때문에 여러 스레드의 작업이 하나의 프로세스 안에서 이루어져도 동시작업이 가능한 이유입니다.\n\n
\n\n그렇다면 어떻게 스레드는 프로세스와 스레드간 데이터를 공유하는 것일까?\n아래 그림을 통해서 보게되면\n\n
\n\n![img.png](thread_resource.png)\n[사진출처](https://gmlwjd9405.github.io/2017/10/01/basic-concepts-of-development-os.html)\n\n
\n\n우선 하나의 프로세스안에 코드, 데이터, 힙, 스택 영역이 존재합니다. 그리고 프로세스 내부의 개별적인 스레드가 존재합니다.\n\n스레드가 레지스터, 프로그램 카운터, 스택을 개별적으로 가지는 핵심 이유는 독립적인 실행 흐름을 보장하기 위해서입니다.\n\n프로그램 카운터는 각 스레드가 서로 다른 코드 위치에서 실행될 수 있도록 현재 실행 지점을 개별 추적하고, \n\n레지스터는 각 스레드의 작업 데이터를 독립적으로 저장합니다. \n이를 통해 CPU가 스레드 간 전환할 때 현재 상태를 저장하고 복원하여 중단된 지점에서 정확히 재개할 수 있습니다.\n스택 영역을 따로 가지는 이유는 각 스레드가 독립적인 함수 호출 흐름을 가져야 하기 때문입니다. \n\n스택은 함수 호출 시 지역 변수, 매개변수, 리턴 주소를 저장하는데, 만약 스레드들이 스택을 공유한다면 한 스레드의 \n함수 호출이 다른 스레드의 함수 실행에 영향을 주어 실행 흐름이 꼬이게 됩니다. 따라서 각 스레드는 독립적인 스택을 가져 서로 다른 함수를 안전하게 호출하고 실행할 수 있습니다.\n결과적으로 이런 구조를 통해 스레드들은 힙과 데이터 영역은 공유하면서도 각자 독립적인 실행 흐름을 유지할 수 있어\n, 하나의 프로세스 내에서 여러 작업을 동시에 효율적으로 처리할 수 있게 됩니다.\n\n
\n
\n\n## TCB란\n\n---\n\n![img.png](TCB.png)\n\n스레드 제어 블록은 운영체제가 각 스레드를 관리하기 위해 유지하는 데이터 구조체입니다. \n프로세스 제어 블록(PCB)과 유사하지만 스레드 수준에서 필요한 정보들을 담고 있습니다.\n링크드 리스트 형태로 구현되어 PCB안에 해당 스레드의 TCB를 내포하고 있는 형태로 저장됩니다.\n\n
\n\n![img.png](TCB2.png)\n\n\n\n![img.png](TCB3.png)\n\n\n
\n
\n\nTCB는 사진과 같은 형태로 저장되며, 아래와 같은 정보를 가진다.\n\n| 정보 | 설명 |\n|------------|---------------------------------|\n| 스레드 식별자 | 각 스레드를 식별하는 고유한 식별자 |\n| 스레드 상태 | 실행 준비 대기 등 스레드의 현재 상태 |\n| 프로그램 카운터 | 스레드가 다음에 실행할 명령어의 주소 |\n| 레지스터 | 스레드가 현재 사용하고 있는 CPU 레지스터의 값을 저장 |\n| 스레드 우선순위 | 스케줄링 결정에 사용되는 스레드의 우선순위 |\n| 스레드 스택 포인터 | 스택 내에서 현재 작업의 위치를 가리키는 레지스터 |\n| 스레드 문맥 정보 | 문맥 교환 시 저장되고 복원되어야 할 정보 |\n\n\n\n\n\n\n\n"},{"excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","fields":{"slug":"/jc8/"},"frontmatter":{"date":"September 11, 2025","title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","tags":["운영체제"]},"rawMarkdownBody":"\n## 문맥교환(Context Switching)\n\n---\n하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요?\n\n프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔을 때 이 과정을 이어받아 작업을 수행할 수 있습니다.\n\n여기서 하나의 프로세스를 실행하기 위해 필요한 정보들을 문맥(Context)라고 부르게 됩니다.\n이러한 문맥값들은 PCB속에 저장됩니다.환\n\n
\n\n![img.png](context_switching.png)\n[사진출처](https://yoongrammer.tistory.com/53)\n\n결국 프로세스 A에서 B로 프로세스가 넘어가는 순간에 프로세스 A정보를 백업하고 그작업이 끝난다면\n프로세스 B의 문맥을 불러오게 되며 이 것이 프로세스를 교대하는 방법입니다.\n\n문맥교환을 통해 여러개의 프로세스가 병렬적으로 시행되는 것 처럼 보이게 하지만 이러한 문맥교환은\n오버헤드가 발생할 수 있기 때문에 문맥교환이 자주일어나면 오버헤드를 신경써야 합니다.\n\n
\n
\n\n## 프로세스 상태\n\n---\n\n이전에 PCB에 기록되는 정보 중 프로세스 상태가 있다고 합니다. 여기서 말하는 프로세스 상태는 생성이 되었는지\n혹은 CPU를 사용하는지와 같은 정보를 통칭해서 프로세스 상태라고 부르게 됩니다.\n\n
\n\n프로세스 상태는 크게 다섯가지로 나뉠 수 있습니다.\n\n![img.png](process_state.png)\n[사진출처](https://thebook.io/080367/0021/)\n\n
\n\n### 1. 생성 상태\n\n프로세스를 생성 중인 상태를 생성 상태라고 부릅니다. 메모리에 적재되어 PCB를 할당받은 상태를 생성상태라고 부르게 됩니다.\n생성 상태가 끝난다고 곧바로 실행되는 것이 아닌 준비 상태가 되어 실행되기를 기다리게 됩니다.\n\n
\n\n### 2. 준비 상태\n\n준비 상태는 당장 CPU를 할당받아 실행될 수 있지만, 차례가 오지않아 기다리고 있는 상태입니다.\n이 상태에서 준비가 되면 실행 상태로 넘어 갑니다. 그리고 다른 상태에서 다시 준비 상태로도 전환이 가능합니다.\n\n준비 상태인 프로세스를 실행 상태로 전환하는 것을 디스패치 라고 부릅니다.\n\n
\n\n### 3. 실행 상태\n\n실행 상태는 CPU를 할당받아 실행 중인 상태를 지칭 합니다. 실행 상태인 프로세스는 할당된 시간 동안 CPU를 사용할 수 있습니다.\n이때 제한된 시간내 프로세스를 완료하지 못한경우 준비 상태로 전환이 되며, I/O입력처럼 대기해야 하는 상황이 생기면\n대기 상태로 넘어가게 됩니다.\n\n
\n\n### 4. 대기 상태\n\n실행 상태에서 I/O입력과 같이 프로세스가 대기해야 하는 상황이 온다면 대기 상태로 진입하게 됩니다.\n대기 상태가 끝난다고 해도 실행 상태가 되는것이 아닌 준비 상태로 넘어가게 됩니다.\n\n
\n\n### 5. 종료 상태\n\n프로세스가 종료된 상태입니다. 이 상태에 도달하면 운영체제는 PCB와 프로세스가 사용한 메모리를 정리합니다.\n\n
\n
\n\n## 프로세스 계층 구조\n\n---\n\n프로세스는 실행 도중 시스템 호출을 통해 다른 프로세스를 생성할 수 있습니다.\n\n이때 새 프로세스를 생성한 프로세스를 부모 프로세스라고 부르게 되며, 생성 된 프로세스를 자식 프로세스라고\n부르게 됩니다.\n부모의 프로세스와 자식의 프로세스는 각각 고유한 PID를 가지며 자식프로세스에서 부모프로세스 PID를 PPID로 가지고 있기도 합니다.\n\n
\n\n![img.png](process_layer.png)\n[사진 출처: 혼자 공부하는 운영체제 저자:강민철]\n\n
\n
\n\n## 프로세스 생성기법\n\n---\n\n그렇다면 부모 프로세스가 어떻게 자식 프로세스를 생성 할까요?\n\n그 방법은 fork, exec라는 명령어를 통해서 생성하게 됩니다.\n\n부모 프로세스는 fork를 통해 자신의 복사본을 자식 프로세스로 생성해내고, 그 복사본은 exec명령어를 통해\n자신의 메모리 공간을 다른 프로그램으로 교체합니다.\n\n
\n\n![img.png](fork.png)\n\n
\n\n좀더 자세히 설명하면 fork, exec 모두 시스템 호출로 분류 됩니다.\n부모 프로세스는 fork 시스템 호출을 통해 자신의 복사본을 자식으로써 생성합니다.\n\n여기서 자식은 부모의 복사본이기 때문에 부모 프로세스의 자원들, 예를들면 메모리의 내용, 열린 파일의 목록등을\n상속하게 됩니다. 그렇다고 해서 모든 정보가 같지는 않습니다.\n\n왜냐하면, PID나 메모리 저장구조는 고유한 정보이기 때문에 fork로 만들어진 자식은 PID, 메모리 저장위치\n처럼 고유한 정보에 대해서는 개별적인 값을 가지고 있습니다.\n\n
\n\n![img.png](exec.png)\n\n
\n\nfork만 사용한 프로세스는 완전한 자식 프로세스라고 명하기는 조금 어렵습니다.\nPID와 같은 고유한 값을 제외한다면 부모가 가진 리소스를 동일하게 사용하는 대체품이기 때문입니다.\n\n그렇기 때문에 자식 프로세스는 자신의 프로세스를 가지기 위해 exec 시스템 호출을 하게 됩니다.\n\nexec 호출을 진행하게 되면 자신의 메모리 공간을 새로운 프로그램으로 덮어쓰게 됩니다.\n\n코드 영역과 데이터 영역의 내용이 실행한 프로그램으로 바뀌게 되고, 나머지 영역은 초기화 됩니다.\n\n"},{"excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. 백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는…","fields":{"slug":"/jc7/"},"frontmatter":{"date":"September 10, 2025","title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","tags":["운영체제"]},"rawMarkdownBody":"\n## 프로세스란 무엇일까?\n\n---\n\n우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다.\n\n여기서 실행된 프로그램을 **프로세스**라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다.\n\n
\n
\n\n![img.png](process_in_mac.png)\n\n
\n위 사진처럼 보이는 것보다 더 많은 프로세스가 작동하고 있는데, 여기서 사용자가 볼 수 있는 프로세스를 포그라운드 프로세스 라며 명하며,\n보이지 않는 프로세스를 백그라운드 프로세스라고 부르게 됩니다. \n\n백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는 다는 뜻은 아닌데 백그라운드 프로세스 중에서 사용자와 상호작용 하지 않고 자신의 일만을 수행하기 위해 존재하는\n프로세스를 **데몬(daemon)** 프로세스라고 명합니다.\n\n
\n\n## 프로세스 제어 블록(PCB)\n\n---\n\nCPU자원이 한정되어 있는 반면에, 모든 프로세스는 실행을 위해 CPU를 사용하여야 합니다. \n그렇기 떄문에 프로세스들은 한정된 시간 만 CPU를 사용하며 자신의 차례를 기다립니다.\n\n운영체제는 빠르게 번갈아 수행되는 프로세스의 실행 순서를 관리하고, 프로세스에 CPU와 여러가지 자원을 배분합니다.\n이를 위해 운영체제는 프로세스 제어 블록(PCB)를 이용합니다.\n\n
\n\nPCB는 커널 영역에 생성되고, 수많은 프로세스를 PCB를 통해 태그처럼 사용해 특정 프로세스를 식별하며 해당 프로세스를 처리하는데 필요한 정보를 판단합니다.\n\n즉, 가게 주인이 물건을 태그를 통해 판단하고 가격을 알 수 있고, 생산지를 알 수 있는 것처럼 PCB는 운영체제가 수 많은 프로세스를 식별하고 그 프로세스의 정보를 판단하게 돕습니다.\n\n
\n
\n\n## PCB의 구조\n\n---\n\n
\n\n![img.png](PCB.png)\n\n[사진 출처](https://binaryterms.com/process-control-block-pcb.html)\n\n
\n\n위 그림처럼 PCB는 프로세스를 식별하기 위해 여러가지 정보를 담고 있습니다. 프로세스의 ID나, \n레지스터의 값 혹은 상태같이 많은 정보를 담고있으며 이를 알아보고자 합니다.\n\n
\n\n### 프로세스 ID\n\n![img.png](process_id.png)\n\n프로세스 ID(PID)는 프로세스를 식별하기 위해 존재하는 고유 ID입니다. 메모장을 두개 킨다고 할지라도 다른 프로세스ID가\n만들어지는 것처럼 중복된 활동이여도 하나의 프로세스는 고유한 ID를 가지게 됩니다.\n\n
\n\n### 레지스터 값\n\n프로세스는 자신의 실행 차례가 돌아오면 이전까지 사용했던 레지스터의 중간값들을 모두 복원합니다.\n여기에는 프로그램 카운터가 속하게 됩니다.\n\n
\n\n### 프로세스 상태\n\n현재 프로세스가 어떤 상태인 기록합니다. 입출력장치를 사용하기 위해 기다리는지 혹은 CPU를 사용하고 있는 상태인지 와 같은\n상태를 기록하며 자세한 상태는 다음장에서 설명합니다.\n\n
\n\n### CPU 스케줄링 정보\n\n프로세스가 언제, 어떤 순서로 CPU를 할당받을지에 대한 정보도 PCB에 기록됩니다.\n\n
\n\n### 메모리 관리 정보\n\n프로세스마다 메모리에 저장된 위치가 다릅니다. 그렇기 떄문에 PCB에는 해당 프로세스가 저장된 메모리 위치를 기록해야 합니다.\n\n
\n
\n\n## 프로세스의 메모리 영역\n\n---\n\n프로세스가 생성되면 커널 영역에 PCB가 생성됩니다. 그렇다면 커널 영역이 아닌 사용자 영역에는 어떤 데이터가 들어갈까요?\n\n\n![img.png](memory_model.png)\n\n[사진출처](https://www.programmersought.com/article/98613694619/)\n\n위 그림처럼 하나의 프로세스는 크게 코드영역(Text), 데이터 영역(Bss,Gvar), 힙 영역(Heap), 스택 영역(Stack) 4가지로 나뉩니다.\n\n차례대로 설명하자면,\n\n
\n
\n\n### 코드영역 or 텍스트영역(Text)\n\n이곳에는 실행할 수 있는 기계어로 이루어진 명령어가 저장됩니다. 가공할 수 있는 데이터가 아닌\nCPU가 실행해야 하는 명령어가 담겨있기 때문에 읽기모드만 지원합니다.\n\n
\n\n### 데이터 영역\n\n프로그램을 실행하는 동안 유지되어야 하는 데이터가 저장되는 공간입니다. 대표적은 전역 변수가 이곳에 해당합니다.\n\n
\n\n### 코드영역 & 데이터 영역 공통점\n\n위 두 영역은 크기가 변하지 않습니다. 프로그램을 구성하는 명령어가 작동중에 코드 양이 늘어나는 경우가 없으니\n이 두가지 영역을 정적 할당 영역이라고 부릅니다.\n\n
\n\n### 힙 영역\n\n프로그래머가 직접 할당할 수 있는 공간입니다. 프로그래밍 과정에서 힙 영역에 데이터를 할당했다면 언젠가는 이 영역에 \n데이터를 반환해야 합니다. 그렇지 않다면 메모리 용량은 점점 줄어들어 장애가 발생할 수 있습니다.\n\n이런 문제를 메모리를 할당받고 해제 하지 않았다고 하여 누수가 발생했다. 즉 메모리 누수라고 부릅니다.\n\n
\n\n### 스택 영역\n\n스택 영역은 데이터를 일시적으로 저장하는 공간입니다.\n데이터 영역에 담기는 값과는 다르게 잠깐 쓸 데이터를 담아두는 공간입니다.\n함수를 실행하는 동안 필요한 지역변수, 매개 변수가 이곳에 해당합니다.\n그렇기 떄문에 함수가 종료되면 스택 영역에서 해당 함수에 쓰였던 변수들도 같이 없어지게 됩니다.\n\n
\n
\n\n### 힙 영역 & 스택 영역 공통점\n\n위 두 영역은 실시간으로 그 크기가 변할 수 있고 그렇기 떄문에 동적 할당 영역이라고 부르게 됩니다.\n\n그림을 보면 unused memory영역이 있는데, 스택 영역과 힙 영역이 동적이기 떄문에 힙은 아래에서 위로, 스택은 \n위에서 아래로 주소를 할당하게 됩니다. 그렇게 되면 서로 충돌없이 동적으로 값을 할당할 수 있기 때문입니다.\n\n여기서 만약에 힙이나 스택에 많은 정보가 담겨서 서로의 지점을 충돌 할 수 있는데, 그럴때 각각 stack overflow,\nheap overflow라고 부르게 됩니다.\n\n\n\n\n\n"},{"excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","fields":{"slug":"/jc6/"},"frontmatter":{"date":"September 09, 2025","title":"동기식/비동기식 I/O의 차이와 활용 사례","tags":["운영체제"]},"rawMarkdownBody":"\n## IO란\n\n개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다.\n\n예시를 들어서\n\n- 파일 읽기/쓰기 (문서를 열거나 저장하는 행위)\n- 네트워크 통신(웹사이트 접속, 이메일 전송)\n- 데이터베이스 조회(회원 정보 검색)\n\n이런 일련의 행위는 공통적인 특징이 있는데, 물리적인 시간이 걸린다는 점입니다.\n그렇기 떄문에 IO를 어떻게 다룰까에 대한 방법또한 여러가지 존재합니다.\n\n
\n
\n\n## 동기와 비동기란\n\nIO를 다루는 방법에는 동기, 비동기에 대한 개념이 등장합니다.\n이러한 개념을 사전에 정의 하고 내려가겠습니다.\n\n### 동기 (Synchronous)\n\n프로그램에서 말하는 동기란 하나의 작업에 대해서 요청과 응답 과정을 기다리는 행위입니다.\n예를들어, WAS가 데이터베이스에 조회 요청을 하고 데이터베이스는 요청받은 데이터를 돌려줄것입니다.\n이 과정에서 WAS는 요청직후 부터 응답을 받을때 까지 과정에서 데이터베이스의 응답을 기다리게 됩니다. 이것이 동기입니다.\n\n
\n\n### 동기의 특징\n\n순차적 실행: 한 작업이 완료되어야 다음 작업이 시작\n블로킹: 현재 작업이 끝날 때까지 다른 작업은 대기\n예측 가능: 코드가 위에서 아래로 순서대로 실행\n\n
\n
\n\n### 비동기 (Asynchronous)\n\n그렇다면 비동기는 하나의 작업에 대해서 요청과 응답 과정을 기다리지 않는 행위입니다.\n예를들어, WAS가 데이터베이스에 조회 요청을 하게 되면 데이터베이스가 이를 수행하고 응답할것입니다.\n이 과정 사이에 시간동안 WAS는 본인의 다른 작업을 수행하다가 데이터베이스의 응답을 받게 됩니다.\n즉 요청과 응답 사이 기간동안 WAS는 본인의 일을 하며 무작정 기다리지 않는 것입니다.\n\n
\n\n### 비동기의 특징\n\n동시 실행: 여러 작업을 동시에 시작 가능\n논블로킹: 작업 완료를 기다리지 않고 다른 작업 진행\n콜백/Promise: 작업 완료 시 결과를 알려주는 방식\n\n
\n\n## 동기식 I/O\n\n![img.png](synchronous_io.png)\n\n
\n\n동기식IO는 IO요청이 발생하였을 때 이전 동기 설명처럼 IO요청이 끝날때 까지 기다리는 방식입니다.\n프로그램이 IO작업을 요청하게 되면, 다른 동작을 수행하지 않고 멈춰서 IO작업이 리턴되기 까지 기다립니다.\nI/O작업이 완료되면 인터럽트를 통해 완료를 알리게 됩니다. 이후 CPU 제어권이 기존 프로그램에게 넘어가게 됩니다.\n\n이러한 방식의 특징은 구현이 쉽다는 특징이 있지만, 연산에 대한 기다림으로 인해 자원 낭비를 하는 특징이 있습니다.\n\n## 비동기식 I/O\n\n![img.png](asynchronous_io.png)\n\n비동기식IO는 IO요청이 발생하였을 떄 이전 비동기 설명처럼 IO요청을 기다리지 않는 방식입니다.\n프로그램이 IO 작업을 요청하고, 그 작업이 완료되기를 기다리지 않고 즉시 다음 작업으로 넘어가는 방식입니다.\n\n이러한 방식의 특징은 구현의 복잡성이 높다는 것이지만, 대용량 데이터를 처리하는데 여러 IO작업을 동시에 처리해야 할 떄 유용합니다.\n"},{"excerpt":"쓰레드란? 쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다. 그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다.\n이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다. 사용자 수준 쓰레드와 커널 수준 쓰레드의 차이 사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다.\n쓰레드와 관련된 모든 행위를 사용자 영…","fields":{"slug":"/hs4/"},"frontmatter":{"date":"September 08, 2025","title":"4. 쓰레드 ","tags":["운영체제"]},"rawMarkdownBody":"\n## 쓰레드란?\n\n쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다. \n\n![](img.png)\n\n그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다.\n이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다.\n\n> #### 사용자 수준 쓰레드와 커널 수준 쓰레드의 차이 \n> 사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다. \n> 쓰레드와 관련된 모든 행위를 사용자 영역에서 하기 때문에, \n> 커널은 사용자 수준 쓰레드의 존재를 알지 못하고 쓰레드 교환에 개입하지 않습니다. \n> 커널 수준 쓰레드란, 커널이 직접 생성하고 관리하는 쓰레드를 의미합니다.\n\n## 쓰레드의 메모리 공간\n\n같은 프로세스의 쓰레드는 프로세스로부터 각각의 스택을 나눠갖지만 Code, Data, Heap 메모리 영역을 공유합니다.\n하지만, 쓰레드 ID, 스택, PC나 레지스터 같은 쓰레드 컨텍스트에 대해서는 각기 다른 값을 가지고 있습니다.\n\n![](img_1.png)\n\n이렇게 각자의 PC, 레지스터, 스택을 가지고 있기에 쓰레드마다 독립적으로 실행할 수 있습니다.\n\n여기서 중요한 점은 프로세스의 쓰레드들은 실행에 필요한 최소한의 정보(PC, 레지스터, 스택)만을 유지한 채\n프로세스 자원을 공유하며 실행된다는 점입니다.\n\n## TCB(쓰레드 제어블록)\n\n쓰레드 또한 프로세스의 PCB(프로세스 제어 블록)처럼 TCB(쓰레드 제어 블록)을 통해 관리됩니다.\nTCB는 각 쓰레드에 위치하고, 커널은 TCB를 통해 쓰레드를 관리합니다.\n\n그럼 TCB에는 어떤 정보가 담겨있을까요?\nTCB에는 아래와 같은 쓰레드의 메타데이터들이 담겨져 있습니다.\n\n![](img_2.png)\n\n- 쓰레드 번호(TID, Thread ID): 각 쓰레드의 고유 식별 번호입니다.\n- 스택 포인터 (Stack Pointer): 쓰레드가 존재하는 프로세스의 PCB에 대한 포인터\n- 프로그램 카운터(PC, Program Counter): 이 쓰레드에서 실행될 다음 명령어의 주소를 가리키는 포인터(주소)입니다.\n- 쓰레드 상태(Thread State): 쓰레드가 현재 어떤 상태인지를 나타내는 정보(new, ready, running, waiting, end)입니다.\n- 레지스터 상태(Register State): 쓰레드의 레지스터 값 세트입니다.\n\n각 프로세스에 대한 중요 정보를 강조하는 특정 정보가 쓰레드 제어 블록에 저장됩니다.\n\n## 프로세스와 쓰레드의 차이\n\n프로세스는 각각 독립된 메모리 영역(Code, Data, Heap, Stack)을 할당받고 고유 프로세스 ID를 가지는 특성으로 인해,\n프로세스끼리는 서로의 영역에 접근할 수 없습니다.\n그래서 한 프로세스가 다른 프로세스의 자원에 접근하려면 IPC(inter-process communication)을 사용해야 합니다.\n\n하지만, 쓰레드는 IPC와 같은 별도의 통신 방법 없이도 앞서 언급한 것처럼 프로세스의 Code, Data, Heap 메모리 영역을 공유합니다.\n\n이처럼 프로세스들 사이의 통신에 대한 어려움 해소 및 빠른 컨텍스트 스위칭으로 인해 쓰레드가 프로세스보다 더 가벼운 실행 단위로 사용됩니다.\n이로 인해 현대에 와서 운영체제의 실행단위는 프로세스에서 쓰레드로 바뀌어 가고 있습니다.\n\n## 동시성 환경에서의 차이\n\n동시성 환경에서는 어떤지 알아볼까요?\n여러 프로세스를 동시에 실행하는 멀티 프로세스와 한 프로세스에서 여러 쓰레드를 동시에 실행하는 멀티 쓰레드가 있습니다.\n\n\n![](img_3.png)\n\n여기서 가장 큰 차이점은 프로세스끼리는 기본적으로 공유하지 않지만, 쓰레드끼리는 같은 프로세스 내의 자원을 공유한다는 점입니다.\n\n즉, 멀티 프로세스는 여러 프로세스를 동시에 실행해 각각의 독립적인 프로세스 간 자원을 공유하지 않기 때문에 프로세스 간 통신 (IPC) 방식을 써야 합니다.\n또한, 메모리에 동일한 내용들이 중복해서 존재하기 때문에 메모리에도 부담이 될 수 있습니다.\n그러나 한편으로는 자원을 공유하지 않는 덕분에 하나의 프로세스에 문제가 생겨도 다른 프로세스들에는 문제가 발생하지 않는다는 장점이 있기도 합니다.\n\n반면, 멀티 쓰레드는 실행에 필요한 최소한의 정보(PC, 레지스터, 스택)만을 유지한 채 프로세스 자원을 공유하며 실행되기에\n커널의 개입 없이 쓰레드간 통신을 할 수 있고, 메모리에도 부담이 덜합니다.\n또한 fork로 인한 생성이 공유하는 부분을 제외한 부분만 복사하면 되기 때문에 프로세스보다 빠릅니다.(쓰레드가 접근하는 공유 데이터에 대해 동기화 작업을 수행해야 합니다)\n
\n하지만, 하나의 쓰레드에 문제가 생기면 같은 프로세스 내의 다른 쓰레드들에도 문제가 발생할 수 있다는 단점이 있습니다.\n"},{"excerpt":"프로세스란? 컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 인스턴스를 의미합니다.\n여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다. 프로세스의 메모리 공간 프로세스는 다음 4개의 메모리 영역으로 구성되고 가상 메모리 공간에 독립적으로 형성됩니다. 코드 영역(Cod…","fields":{"slug":"/hs3/"},"frontmatter":{"date":"September 08, 2025","title":"3. 프로세스","tags":["운영체제"]},"rawMarkdownBody":"\n## 프로세스란? \n\n![](img.png)\n\n컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 [인스턴스](https://ko.wikipedia.org/wiki/%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99)#:~:text=%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4(instance)%EB%8A%94%20%ED%95%B4%EB%8B%B9%20%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98%20%EA%B5%AC%EC%A1%B0%EB%A1%9C%20%EC%BB%B4%ED%93%A8%ED%84%B0%20%EC%A0%80%EC%9E%A5%EA%B3%B5%EA%B0%84%EC%97%90%EC%84%9C%20%ED%95%A0%EB%8B%B9%EB%90%9C%20%EC%8B%A4%EC%B2%B4%EB%A5%BC%20%EC%9D%98%EB%AF%B8%ED%95%9C%EB%8B%A4.)를 의미합니다.\n여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다.\n\n## 프로세스의 메모리 공간\n\n프로세스는 다음 4개의 메모리 영역으로 구성되고 [가상 메모리](https://ko.wikipedia.org/wiki/%EA%B0%80%EC%83%81_%EB%A9%94%EB%AA%A8%EB%A6%AC#:~:text=%EA%B0%80%EC%83%81%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EB%98%90%EB%8A%94%20%EA%B0%80%EC%83%81%20%EA%B8%B0%EC%96%B5%20%EC%9E%A5%EC%B9%98(%EB%AC%B8%ED%99%94%EC%96%B4%3A%20%EA%B0%80%EC%83%81%EA%B8%B0%EC%96%B5%EA%B8%B0%2C%20virtual%20memory%2C%20virtual%20storage)%EB%8A%94%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EA%B4%80%EB%A6%AC%20%EA%B8%B0%EB%B2%95%EC%9D%98%20%ED%95%98%EB%82%98%EB%A1%9C%2C%20%EC%BB%B4%ED%93%A8%ED%84%B0%20%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90%20%EC%8B%A4%EC%A0%9C%EB%A1%9C%20%EC%9D%B4%EC%9A%A9%20%EA%B0%80%EB%8A%A5%ED%95%9C%20%EA%B8%B0%EC%96%B5%20%EC%9E%90%EC%9B%90%EC%9D%84%20%EC%9D%B4%EC%83%81%EC%A0%81%EC%9C%BC%EB%A1%9C%20%EC%B6%94%EC%83%81%ED%99%94%ED%95%98%EC%97%AC%5B1%5D%20%EC%82%AC%EC%9A%A9%EC%9E%90%EB%93%A4%EC%97%90%EA%B2%8C%20%EB%A7%A4%EC%9A%B0%20%ED%81%B0%20(%EC%A3%BC)%20%EB%A9%94%EB%AA%A8%EB%A6%AC%EB%A1%9C%20%EB%B3%B4%EC%9D%B4%EA%B2%8C%20%EB%A7%8C%EB%93%9C%EB%8A%94%20%EA%B2%83%EC%9D%84%20%EB%A7%90%ED%95%9C%EB%8B%A4.%5B2%5D%20%EA%B0%81%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%97%90%20%EC%8B%A4%EC%A0%9C%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EC%A3%BC%EC%86%8C%EA%B0%80%20%EC%95%84%EB%8B%8C%20%EA%B0%80%EC%83%81%EC%9D%98%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EC%A3%BC%EC%86%8C%EB%A5%BC%20%EC%A3%BC%EB%8A%94%20%EB%B0%A9%EC%8B%9D%EC%9D%B4%EB%8B%A4.) 공간에 독립적으로 형성됩니다.\n\n- 코드 영역(Code) : 프로그램 실행 코드가 적재되는 영역입니다. 읽기 모드만 지원합니다.\n- 데이터 영역(Data) : 프로세스의 초기화 된 데이터들인 전역 변수와 정적 변수들이 적재되는 영역입니다.\n- 힙 영역(Heap) : 런타임 동안 생성된 데이터를 보관하기 위해 동적으로 할당받는 영역입니다.\n- 스택 영역(Stack) : 지역변수, 매개변수, 리턴 값, 복귀 주소 등이 저장되는 영역입니다.\n\n이렇게 영역이 나눠진 이유는 최대한 중복적인 데이터를 방지하여 메모리 사용량을 줄이는데 목적이 있습니다.\n\n> 예를 들면, 코드에서 공통으로 사용하는 부분을 전역 변수로 지정하는 행위와 같다.\n\n## PCB(프로세스 제어 블록)\n\n커널은 시스템 전체에 대해 레지스터에 하나의 프로세스 테이블을 두고 모든 프로세스의 정보를 관리합니다.\n여기서의 프로세스 정보는 해당 프로세스를 실행하기 위해 필요한 정보들로 컨텍스트라고 부릅니다. \n여기서 프로세스의 상태에 따라 프로세스를 교체하는 작업인 컨텍스트 스위칭 작업 이루어 지는데,\n이와 같은 상황에서 여러 프로세스를 관리하기 위해 각 프로세스들에 대해 식별이 가능해야 관리가 가능하기에 해당 프로세스의 정보가 필요합니다.\n\n예를 들어, 인터럽트가 발생해서 자원을 할당받은 프로세스가 대기 상태가 되고 다른 프로세스를 실행 상태로 올릴 때\n대기 중인 프로세스를 나중에 다시 수행하기 위해 대기 중인 프로세스의 상태와 같은 정보를 알아야 할 것입니다.\n\n운영체제의 커널은 이러한 이유로 활성된 프로세스를 관리하기 위해 해당 프로세스에 대한 정보를 PCB(프로세스 제어 블록)이라는 데이터 구조에 저장합니다.\n(\"PCB는 운영 체제가 프로세스를 표현한 것이다.\"라는 말도 있습니다.)\n\n![](img_1.png)\n\n> PCB는 해당 프로세스가 실행되면 생성되어 종료 시 제거가 되는데 이 과정에서 PCB의 삽입 및 삭제가 용이한 연결 리스트(Linked List) 방식으로 관리됩니다.\n\n## Process Metadata\n\n그럼 PCB에는 어떤 정보가 담겨있을까요?\nPCB에는 아래와 같은 프로세스의 메타데이터들이 담겨져 있습니다.\n\n- 프로세스 번호(PID, Process ID): 각 프로세스의 고유 식별 번호입니다.(PPID: 부모 프로세스 ID)\n- 프로세스 상태(Process State): 프로세스가 현재 어떤 상태인지를 나타내는 정보(new, ready, running, waiting, end)입니다.\n- 프로그램 카운터(PC, Program Counter): 이 프로세스에서 실행될 다음 명령어의 주소를 가리키는 포인터(주소)입니다.\n- 레지스터 상태(Register State): 프로세스의 레지스터 값 세트로, 프로세스를 다시 실행할 때 현재 상태를 복원하는 데 사용됩니다. \n- 스케줄링 정보(Scheduling Information): CPU 시간 스케줄링에 대한 정보입니다.\n- 메모리 관리 정보 (Memory Management Information): 프로세스의 메모리 할당과 사용에 관한 정보입니다.\n- 입출력 상태 (I/O Status): 프로세스가 입출력 작업을 수행 중인 경우, 해당 상태 정보 및 장치 정보입니다.\n\n## 프로세스 상태\n\n운영체제의 커널은 프로세스를 관리하기 위해 프로세스 정보를 알아야 해서 PCB를 생성하는 것을 알았습니다.\n여기서 커널의 프로세스 관리는 프로세스 상태를 관리하는 것이기도 합니다.\n\n프로세스 상태는 위에서 언급한대로 프로세스가 현재 어떤 상태인지를 나타내는 정보로, \n프로세스의 상태에 따라 CPU를 할당하거나 대기 상태로 전환하는 등의 작업이 이루어집니다.\n프로세스 상태는 일반적으로 다음과 같은 상태로 구분됩니다.\n\n![](img_2.png)\n\n- New(생성) : 프로세스는 저장장치에서 메모리로 로드되어 생성됩니다. 이후 커널은 메모리를 할당하고 PCB를 생성하고 프로세스 테이블에 등록합니다. 실행 준비를 마치면 ready 상태로 전이됩니다.\n- Ready(준비) : 프로세스가 CPU를 사용하고 있지는 않지만 언제든지 사용할 수 있는 상태로, 해당 상태의 프로세스들은 커널에 있는 준비 큐([우선순위 큐](https://ko.wikipedia.org/wiki/%EB%B9%84%EC%9C%A8_%EB%8B%A8%EC%A1%B0_%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81))에 들어갑니다. 스케줄러가 컨텍스트 스위칭을 수행할 때, 준비 큐에서 우선순위가 높은 프로세스가 CPU 스케줄링에 따라 리소스를 할당받아 running 상태로 전이(디스패치)됩니다.\n- Running(실행) : 프로세스가 CPU를 차지하여 명령어들이 실행되고 있는 상태입니다. 할당된 시간을 모두 사용(타임아웃)했다면 타이머 인터럽트가 발생되어 준비 상태로 전이되고, 입출력 요청이나 자원 요청 등으로 인해 대기 상태로 전이될 수도 있습니다.\n- Waiting(대기) : 프로세스 실행 도중 입출력 완료(주된 원인)와 같은 수신 등을 대기하는 상태를 말합니다.\n- End(=terminated, 종료) : 프로세스의 실행이 종료된 상태입니다. 이떄, PCB와 프로세스의 메모리를 해제 또는 정리합니다.\n\n## 프로세스 계층 구조\n\n프로세스는 실행 도중 시스템 콜을 통해 다른 프로세스를 생성할 수 있습니다. \n이때 시스템 콜을 호출한 프로세스를 부모 프로세스, 생성된 프로세스를 자식 프로세스라 합니다.\n\n> 서로 다른 프로세스라 서로 다른 PID를 가집니다. \n> 일부 운영체제에서는 자식 프로세스의 PCB에 부모 프로세스의 PID (PPID)가 기록되기도 합니다.\n\n프로세스 생성 기법은 복제와 교체 과정을 통한 방식을 사용합니다.\n\n![](img_3.png)\n\n흐름의 시작인 부모 프로세스는 fork(복제) 시스템 콜을 통해 자신의 복사본을 자식 프로세스로 생성합니다.\n자식 프로세스는 exec(교체) 시스템 콜을 통해 자신의 메모리 공간을 다른 프로그램으로 교체합니다.\n이때, 자식 프로세스의 메모리 공간을 새로운 프로그램으로 덮어쓰게 합니다.(코드/데이터는 내용만 바꾸고, 나머지는 초기화)\n자식 프로세스가 exec 시스템 콜을 호출하지 않을 경우, 부모 프로세스와 자식 프로세스는 같은 코드를 병행하여 실행하는 프로세스가 됩니다.\n이러한 과정을 통해 프로세스는 계층 구조를 이루어 관리할 수 있습니다.\n\n많은 운영체제에서는 이처럼 프로세스를 낳는 계층적인 구조로써 프로세스들을 관리합니다.\n컴퓨터가 부팅될 때 실행되는 최초의 프로세스가 자식 프로세스들을 생성하고, \n생성된 자식 프로세스들이 새로운 프로세스들을 낳는 형식으로 여러 프로세스가 동시에 실행되는 것입니다.\n\n## 프로세스 간 통신\n\n앞서 언급했던 것처럼 프로세스는 서로 독립된 메모리 공간을 가지므로, 프로세스끼리는 서로의 영역에 접근 또는 간섭할 수 없습니다.\n이러한 이유로 통신이 필요할 경우, [IPC](https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4_%EA%B0%84_%ED%86%B5%EC%8B%A0#:~:text=%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%20%EA%B0%84%20%ED%86%B5%EC%8B%A0(Inter%2DProcess%20Communication%2C%20IPC)%EC%9D%B4%EB%9E%80%20%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%93%A4%20%EC%82%AC%EC%9D%B4%EC%97%90%20%EC%84%9C%EB%A1%9C%20%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC%20%EC%A3%BC%EA%B3%A0%EB%B0%9B%EB%8A%94%20%ED%96%89%EC%9C%84%20%EB%98%90%EB%8A%94%20%EA%B7%B8%EC%97%90%20%EB%8C%80%ED%95%9C%20%EB%B0%A9%EB%B2%95%EC%9D%B4%EB%82%98%20%EA%B2%BD%EB%A1%9C%EB%A5%BC%20%EB%9C%BB%ED%95%9C%EB%8B%A4.)를 통해 프로세스 간에 통신을 할 수 있습니다.\nIPC에는 공유 메모리를 이용한 통신과 파일을 통한 프로세스 간 통신 이렇게 두 가지 방법이 있습니다.\n\n> IPC 통신 시, 프로세스 간 데이터를 동기화하고 보호하기 위해 [세마포어](https://ko.wikipedia.org/wiki/%EC%84%B8%EB%A7%88%ED%8F%AC%EC%96%B4)와 [뮤텍스](https://ko.wikipedia.org/wiki/%EC%83%81%ED%98%B8_%EB%B0%B0%EC%A0%9C)를 사용합니다."},{"excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","fields":{"slug":"/jc5/"},"frontmatter":{"date":"September 08, 2025","title":"인터럽트와 DMA를 통한 효율적 입출력 처리","tags":["운영체제"]},"rawMarkdownBody":"\n## 인터럽트 기반 입출력\n\n---\n\n인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다.\n\n인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트를 발생시킨\n주체가 무엇인가에 따라 나뉘게 된다.\n\n대표적인 하드웨어 인터럽트는 I/O완료, 대표적인 소프트웨어 인터럽트는 시스템 콜이 있다.\n\n
\n
\n\n![img.png](Interrupts.png)\n\n이러한 인터럽트 기반 입출력의 순서를 설명하자면\n\n1. CPU가 입출력 장치에 대해 입출력 요청을 보낸다.\n2. CPU는 요청이후 다른 작업을 수행한다.\n3. 입출력 장치가 준비되면 인터럽트를 발생시킨다.\n4. CPU는 현재 실행 중인 작업을 중단하고 인터럽트 서비스 루틴(ISR)을 실행한다.\n5. 데이터를 처리한 후 , CPU는 원래 수행하던 작업을 계속 실행한다.\n\n이러한 인터럽트 기반 입출력의 단점은 인터럽트가 많이 발생하는 상황에서 CPU가 부하될 수 있다는 단점이 있다.\n\n\n
\n
\n\n## DMA(Direct Memory Access 직접 메모리 접근)\n\n---\n\nDMA방식은 이름에서 볼 수 있듯이 CPU를 사용하지 않고 입출력 장치가 직접 메로리와 데이터를 교환합니다.\n\n이것이 가능한 이유는 DMA 컨트롤러가 존재해, 메모리와 입출력 장치 사이의 데이터를 관리하기 때문입니다.\n\nDMA에서는 CPU가 전송할 데이터의 위치, 포인터, 바이트 크기만 DMA 컨트롤러에 전달하면, \nDMA가 입출력 작업을 대신 처리하고 전체 작업이 완료될 때만 CPU에 인터럽트를 보냅니다. \n이로 인해 CPU와 여러 입출력 장치가 직접 연결되던 기존 구조에서 CPU-DMA-입출력 장치 구조로 변화했고,\nCPU의 가용 시간이 현저히 증가하는 효과를 얻었습니다. \n이는 교수가 조교에게 학생 관리를 맡기고 최종 결과만 확인하는 것에 비유할 수 있으며, \n현재 DMA는 많은 컴퓨터 장치에서 보편적으로 사용되는 기술이 되었습니다.\n\n
\n
\n\n![img.png](DMA.png)\n\n
\nDMA 방식을 순서로 설명하자면\n\n1. CPU가 DMA 컨트롤러에게 입출력 요청합니다.\n2. DMA 컨트롤러가 메모리와 입출력 장치 간의 데이터 전송을 직접 수행합니다.\n3. 데이터 전송이 완료되면 DMA 컨트롤러가 인터럽트를 발생 시켜 CPU에게 완료를 알립니다.\n4. CPU는 인터럽트를 받아서 필요한 후처리 수행합니다.\n\n\n"},{"excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. 멀티 프로그래밍 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다.…","fields":{"slug":"/jc4/"},"frontmatter":{"date":"September 07, 2025","title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","tags":["운영체제"]},"rawMarkdownBody":"\n## 단일 프로세스\n\n---\n\n초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다.\n\n
\n\n![img.png](single_process.png)\n\n
\nCPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 IO작업동안 CPU는 멈추게\n될것이고 그 상황에서 CPU가 놀고 있게 되는 시간이 늘어나는 것입니다.\n\n
\n\n## 멀티 프로그래밍\n\n![img.png](multiprograming.png)\n\n이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다.\n이를 멀티 프로그래밍이라고 부르며 그림처럼 CPU 사용률을 높이기 위한 목적이었습니다.\n\n하지만 이러한 방식의 문제는 앞선 프로세스가 길어질 수록 즉 IO사용처럼 비는 시간없이 순수하게 많은 시간을\n쓰게 된다면 이후 프로세스가 계속 기다려야 하는 문제가 있었습니다.\n\n
\n\n## 멀티 태스킹\n\n![img.png](multitasking.png)\n\n멀티 프로그래밍 방식에서 더 나아가 모든 프로세스가 공정하게 특정 짧은 시간만 실행되게 반복한다면 길게 시행되는\n프로세스 뒤에 오는 프로세스가 기다리는 문제가 없을 것이다. 이것이 멀티태스킹을 사용하는 이유입니다.\n\n**프로세스1**에서 **프로세스2**로 작업을 스위칭 하는것을 문맥 교환(Context Switching)이라고\n부르게 되는데 이러한 문맥교환은 값싼 작업이 아니고 이러한 작업이 자주 일어나게 된다면 비효율 적인 단점이 부각되다 보니\n새로운 방식을 사용하게 됩니다.\n\n
\n\n## 멀티 프로세싱\n\n멀티 프로세싱이란 이전 멀티 태스킹과 이름은 비슷 하지만 완전히 다른 방식입니다.\n\n이전 방식은 하나의 **CPU**를 어떻게 쪼개서 사용할까라는 목적이였다면, **멀티 프로세싱**은 **CPU** 작업단위인\n코어 자체를 늘려서 여러 CPU코어가 동시에 작업하는것을 멀티 프로세싱이라고 부르게 됩니다.\n\n![img.png](multiprocessing.png)\n\n멀티 프로세싱은 CPU코어 수를 늘리는 방법이기 때문에, 이를 어떻게 처리할까에 대한 내용은 멀티 프로세싱 자체의 내용이 아니고 앞서 나왔던 방법론을 도입할 수 있습니다.\n그림처럼 하나의 프로세스를 여러 코어가 담당하는 방법이나, 여러 프로세스를 여러 코어가 담당 할 수 도 있습니다.\n\n### 출처\n[사진출처](https://medium.com/@ashappyasiknow/single-process-system-multi-programming-multitasking-%EC%9D%B4%EB%9E%80-9f9b65ec0311)\n"},{"excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비스를 제공받을…","fields":{"slug":"/jc3/"},"frontmatter":{"date":"September 06, 2025","title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리","tags":["운영체제"]},"rawMarkdownBody":"\n## 이중모드\n\n---\n\n운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다.\n\n> 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요?\n\n이에 대한 답은 **이중 모드** 입니다.\n\n
\n\n\n![img.png](dual_mode.png)\n\n
\n\n위 사진 처럼 **CPU**가 명령을 실행하는 방식을 **사용자 모드** 와 **커널 모드**로 나누어 사용하게 됩니다.\n\n
\n\n### 사용자 모드\n\n사용자 모드는 운영체제 서비스를 제공받을 수 없는 실행 모드입니다.\n
CPU가 해당 모드인 경우, 입출력 명령어와 같은 하드웨어 자원 접근 명령을 실행할 수 없습니다. 일반 프로그램은 기본적으로 사용자 모드로 실행됩니다.\n\n
\n\n### 커널 모드\n커널모드는 운영체제 서비스를 제공받을 수 있는 실행 모드로 커널 영역의 코드를 실행할 수 있습니다.\n
CPU가 커널 모드로 명령어를 실행하면 자원에 접근하는 명령어를 비롯한 모든 명령어를 실행할 수 있으며, 운영체제는 커널 모드로 실행됩니다.\n\n
\n\n요약 하자면 일반 응용프로그램은 평소에 **사용자 모드**를 통해서 실행 되다가 실제 운영체제의 코드를 실행하여야 하는 순간이 오면 **커널 모드**로 전환하여 실행하다가\n운영체제의 코드 실행 지점이 끝난다면 다시 **사용자 모드**로 전환되게 됩니다.\n\n이러한 방식으로 자원을 **운영 체제**로 하여금 독자적으로 관리할 수 있게 합니다.\n\n
\n\n> 사용자 모드에서 어떻게 커널모드로 전환할까?\n\n사용자 모드에서 커널모드로 전환하는 방식은 **시스템 콜**에 의해서 발생합니다.\n\n
\n\n![img.png](system_call.png)\n\n
\n\n그림처럼 사용자 모드로 실행되는 프로그램이 자원에 접근해야 할때 운영체제에 커널 모드로 요청을 보내게 되고 이것을 **시스템 콜**이라고 부르게 됩니다.\n\n**시스템 호출**은 **소프트 웨어 인터럽트**에 속합니다. 이러한 특징 때문에 **CPU**가 **시스템 호출**을 처리하는 순서가 **인터럽트 처리 순서**와 비슷합니다.\n\n**시스템 호출**이 발생하면 **지금까지의 작업을 백업** 하고, 커널 영역 내의 호출 하여야 하는 코드를 실행 한 뒤 다시 돌아와 기존 프로그램을 계속 실행합니다.\n\n
\n\n![img.png](system_call_method.png)\n\n
\n\n그림을 통해서 이해를 하게 되면,\n\n1. 응용 프로그램은 일반적인 작업을 수행중 운영체제 코드를 실행 하여야 하는 작업에 도달하게 됩니다.\n2. 그러면 응용프로그램은 운영체제에게 자원 접근에 대한 시스템 콜을 날리게 된다.\n3. 현재 작업을 백업하게 됩니다.\n4. 이후 응용프로그램은 운영체제의 코드를 실행합니다.\n5. 작업이 끝나면 다시 사용자 영역으로 돌아와 멈춰둔 작업을 진행합니다.\n\n이런 세부적인 순서를 진행하게 됩니다.\n\n### 출처\n[사진출처](https://hongong.hanbit.co.kr/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EB%9E%80-%EC%BB%A4%EB%84%90%EC%9D%98-%EA%B0%9C%EB%85%90-%EC%9D%91%EC%9A%A9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%8B%A4%ED%96%89%EC%9D%84-%EC%9C%84%ED%95%9C/)\n\n"},{"excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","fields":{"slug":"/jc2/"},"frontmatter":{"date":"September 05, 2025","title":"CPU 스케줄링, 시스템 자원 관리","tags":["운영체제"]},"rawMarkdownBody":"\n## CPU 스케줄링\n\n---\n\n**CPU 스케줄링**은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며, \n
모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다.\n\nCPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n
\n\n### CPU 스케줄링 원칙\n\n---\n\nCPU는 스케줄링을 하면서 두가지 원칙을 중요시 하게 됩니다.\n
\n\n1. 공정함: 특정 프로세스 실행이 무한정 대기하지 않도록 기간을 보장합니다.\n2. 우선순위: 우선순위가 높은 작업에 우선권을 제공 합니다.\n\n
\n\n### CPU 스케줄링 평가 기준\n\n---\n\nCPU는 객관적인 스케줄링을 위해 아래와 같은 평가 기준을 사용합니다.\n\n
\n\n1. CPU 사용률 - CPU가 작업을 수행하는데 사용하는 시간의 비율\n2. 처리량 - 시스템이 단위 시간당 완료할 수 있는 작업의 양\n3. 응답 시간 - 시스템이 사용자의 요청에 반응하여 첫 번째 응답을 생성하기 시작하는데 걸리는 시간\n4. 대기 시간 - 프로세스가 실행되기 위해 CPU를 할당받아 준비 상태에서 대기하는 시간의 총합\n5. 처리 시간 - 특정 작업이 시작되었을 때부터 그 작업이 완전히 끝나는데 걸리는 시간의 총합\n\n"},{"excerpt":"앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다.\n이제 커널이 어떻게 작동하는지 제대로 알아보자. 먼저 인터럽트(Interrupt)에 대해 알아야 한다. 컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데\n이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다.\n이중 하나가 인터럽트이다. \n인터럽트는 중단시키다라…","fields":{"slug":"/hs2/"},"frontmatter":{"date":"September 04, 2025","title":"2. 커널의 작동 방식","tags":["운영체제"]},"rawMarkdownBody":"\n앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다.\n이제 커널이 어떻게 작동하는지 제대로 알아보자.\n\n먼저 인터럽트(Interrupt)에 대해 알아야 한다.\n\n![img_3.png](img_3.png)\n\n컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데 \n이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다.\n이중 하나가 인터럽트이다. \n\n![](img.png)\n인터럽트는 중단시키다라는 의미로 초인종과 같다고 할 수 있다.\n즉, 인터럽트가 발생하면 잠깐 멈추고 다시 실행된다.\n\n![](img_1.png)\n\n실제 발생하는 대부분의 인터럽트는 I/O 인터럽트이다.\n예를들면, 우리가 자바에서 print을 할 때 print라는 API를 파일이라는 인터페이스를 통해서 유저모드에서 커널 모드로 시스템 콜이 발생한다.\n유저모드 API에서 커널모드 구성요소에서 시스템 콜이 이어지고 디바이스 드라이버를 제어하기 시작하는데\n[이때 디바이스 드라이버가 인터럽트를 CPU에 요청한다. 이 행위를 IRQ라고 한다.](https://en.wikipedia.org/wiki/Interrupt_request#:~:text=In%20a%20computer,or%20mouse%20movements.)\n이러한 IRQ는 장치마다 다른 번호로 관리하게 된다.\n아무튼 출력기기에 출력이 되면, 다시 역순으로 디바이스(하드웨어)에서 디바이스 드라이버로,\n디바이스 드라이버에서 커널 모드로 해서 최종적으로 유저 모드로 다시 돌아오게 된다.\n\n![](img_4.png)\n이때, 이러한 행위 도중 wait을 걸면 블라킹(동기) 안걸면 논블라킹(비동기)으로 동작하게 된다.\n\n인터럽트에는 우선순위가 있고 외부 인터럽트인지 내부 인터럽트인지에 따라 우선순위가 달라진다.\n\n먼저, 외부 인터럽트로 내부 인터럽트보다 우선 시 된다.\n\n그 중에서도 우선 순위가 있는데, 다음과 같다.\n- 전원 이상 인터럽트: 말 그대로 정전 또는 파워 이상\n- 기계 착오 인터럽트: CPU의 기능적인 오류.\n- 외부 신호 인터럽트: 타이머 또는, 키보드 인터럽트 키(Ctrl + Alt + Delete). 외부장치로부터 인터럽트 요청이 있는 경우. I/O 인터럽트와 다른 개념이다.\n- 입출력 인터럽트: 입출력 장치가 데이터 전송을 요구하거나 전송이 끝나 다음 동작이 수행되어야 할 경우. 입출력 데이터에 이상이 있는 경우. 우리가 자주 다루게 될 인터럽트 부분이다.\n\n이제 내부 인터럽트인데, 사실 우리가 주로 다루게 될 것은 외부 인터럽트에 있어 내부 인터럽트는 뭐가 있는지만 대강 본다.\n\n- 명령어 잘못 인터럽트: 잘못된 명령어나 잘못된 데이터를 사용할 때 발생하며 Trap이라 부른다,\n- 프로그램 검사\n- 소프트웨어 인터럽트(=SVC, SuperVisor Call)\n\n인터럽트 동작 순서에 대해 다시 살펴보면 다음과 같은데,\n\n1. 인터럽트 요청\n2. 프로그램 실행 중단\n3. 현재 프로그램 상태 보존 -> PCB(Process Control Block), PC(Program Counter) 등\n4. 인터럽트 서비스 루틴 실행: 인터럽트 처리 코드\n5. 상태 복구\n6. 중단 프로그램 실행 재개\n\n![](img_2.png)\n\n이 과정에서 유저모드에서 커널모드로 넘어갈 떄 컨텍스트 스위칭이 되면서 오버헤드가 발생하는데 이로 인해 시스템 상 지연이 발생한다.\n하지만 고성능 어플리케이션을 할 때 이 지연은 꽤나 치명적일 것이다. \n그래서 위와 같이 DMA(Direct Memory Access)라는 기술을 사용하게 됐다.\n예를들어, DirectX라는 것이 있는데 이는 게임을 할 때 이러한 컨텍스트 스위칭 되는 부분을 건너뛰어 직접 드라이버까지 가는 방식이 있다.\n이렇듯 DirectX처럼 인터럽트 시 컨텍스트 스위칭으로 인한 오버헤드가 발생하면서 지연이 발생하는데 이걸 해소하는 것이 DMA인 것이다.\n정리하자면, [DMA는 RAM에 일정 부분을 예약해 불필요한 컨텍스트 스위칭을 스킵해 오버헤드 방지 및 지연을 획기적으로 줄이는 방식이다.](https://en.wikipedia.org/wiki/Direct_memory_access#:~:text=DMA%20(%20Direct%20Memory%20Access%20)%EB%8A%94%20%ED%8A%B9%EC%A0%95%20%ED%95%98%EB%93%9C%EC%9B%A8%EC%96%B4%20%ED%95%98%EC%9C%84%20%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%B4%20%EC%A4%91%EC%95%99%20%EC%B2%98%EB%A6%AC%20%EC%9E%A5%EC%B9%98%20(CPU)%20%EC%99%80%20%EB%8F%85%EB%A6%BD%EC%A0%81%EC%9C%BC%EB%A1%9C%20%EC%A3%BC%20%EC%8B%9C%EC%8A%A4%ED%85%9C%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EC%97%90%20%EC%95%A1%EC%84%B8%EC%8A%A4%ED%95%A0%20%EC%88%98%20%EC%9E%88%EB%8F%84%EB%A1%9D%20%ED%95%98%EB%8A%94%20%EC%BB%B4%ED%93%A8%ED%84%B0%20%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98%20%EA%B8%B0%EB%8A%A5%EC%9E%85%EB%8B%88%EB%8B%A4%20.)\n\n\n\n\n"},{"excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","fields":{"slug":"/jc1/"},"frontmatter":{"date":"September 04, 2025","title":"운영체제의 역할과 커널의 기능","tags":["운영체제"]},"rawMarkdownBody":"\n## 운영체제란 무엇일까?\n\n---\n\n**운영체제**는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 **자원**을 **관리**하고, \n
프로세스를 관리하는 등 여러가지 일을 수행합니다.\n\n이러한 **운영체제**는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다.\n\n\n## 운영체제의 역할\n\n---\n\n### 하드웨어 관리\n\n> 운영체제는 CPU, 메모리, 입출력 장치 등 컴퓨터 하드웨어 자원을 관리합니다.\n>
여기서 말하는 **관리**란 자원의 충돌을 방지하고 사용자가 하드웨어를 **효율**적으로\n> 사용하도록 처리하는것을 의미하게 됩니다.\n\n
\n
\n\n### 프로세스 관리\n\n> 프로세스의 생성과 종료 그리고 CPU 스케줄링을 통해 프로세스의 실행 시간을 관리합니다. \n>
**멀티 태스킹**환경에서 프로세스 전환을 관리합니다.\n\n
\n
\n\n### 메모리 관리\n\n> 각 애플리케이션에 충분한 메모리 공간을 할당하는 기능을 합니다.\n>
또한 가상 메모리를 통해 실제 메모리보다 큰 주소 공간을 제공합니다.\n\n## 커널이란 무엇일까?\n\n---\n\n**커널**이란 운영체제의 핵심 기능을 담당하며, 커널은 하드웨어와 소프트웨어 애플리케이션 간 통신을 관리합니다. 커널의 대표적인 기능으로는 \n
**프로세스 관리**, **메모리 관리**, **파일 시스템**, **입 출력 관리**의 역할을 수행하게 됩니다.\n\n위 설명 처럼 **운영체제**의 핵심기능을 **커널**이 많은 부분을 담당하기 때문에 이전에 설명한 운영체제의 기능이 **커널**의 기능이라고 생각하면 됩니다.\n\n\n## 커널이 자원을 관리하는 이유\n\n---\n\n> **커널**은 어떻게 충돌 없이 자원을 관리할까요?\n\n이 질문에 대한 대답은 자원을 관리하는 지점을 **커널**을 통한 단일 진입점으로 만들게 되면서 해결 하게 됩니다.\n
\n\n> 왜 자원을 **커널**을 통해서만 관리하게 설게 했을까요? \n\n**커널**이 자원을 혼자 관리해야 하는 이유를 예시를 들어서 설명하겠습니다.\n\n유치원 수업시간에 하나의 바구니에 **테이프**, **연필**, **지우개**와 같은 문구용품을 담아두고 선생님이 학생들에게 자율적으로 사용해도 된다고 하게 된다면 어떤일이 벌어질까요?\n\n처음에는 아이들이 각자 필요한 문구 용품을 사용하겠지만 얼마 가지 않아서 **연필**을 찾는 학생,\n
**테이프**를 가지고 누가먼저 쓸지 싸우는 학생,\n
혹은 **지우개**를 망가뜨린 학생등 많은 사고가 있을 것입니다.\n\n이러한 문제가 벌어지는 이유는 공용 문구를 사용할때 **통제권**이 모두에게 있기 떄문입니다. 그렇다면 이를 해결하기 위해서\n모두에게 있는 **통제권**을 하나로 합쳐서 해결하면 되는 문제이고 이것이 자원을 사용하기 위해 **커널의 관리**를 받아야 하는 이유입니다.\n"},{"excerpt":"운영체제(OS, Operating System) 운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다. 운영체제가 없으면 어떻게 될까? 꼭 필요할까? A computer is a machine that can be programmed to automatically carry ou…","fields":{"slug":"/hs1/"},"frontmatter":{"date":"September 03, 2025","title":"1. 운영체제의 개념과 구조","tags":["운영체제"]},"rawMarkdownBody":"\n## 운영체제(OS, Operating System)\n\n[운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다.](https://en.wikipedia.org/wiki/Operating_system#:~:text=An%20operating%20system%20(OS)%20is%20system%20software%20that%20manages%20computer%20hardware%20and%20software%20resources%2C%20and%20provides%20common%20services%20for%20computer%20programs.)\n\n![](img.png)\n\n운영체제가 없으면 어떻게 될까? 꼭 필요할까?\n\n> _A computer is a machine that can be programmed to automatically carry out sequences of arithmetic or logical operations_\n> (컴퓨터는 산술적 또는 논리적 연산(계산)의 순서를 자동으로 수행하도록 프로그래밍할 수 있는 기계이다).\n> [ - wikepedia](https://en.wikipedia.org/wiki/Computer#:~:text=A%20computer%20is%20a%20machine%20that%20can%20be%20programmed%20to%20automatically%20carry%20out%20sequences%20of%20arithmetic%20or%20logical%20operations%20(computation).)\n\n운영체제가 없다면 컴퓨터는 그저 하드웨어의 집합체에 불과하다. \n사용자는 프로그램을 실행하기 위해서 매번 하드웨어를 직접 제어해야 하며, 이렇게 하는 것은 매우 비효율적일거다. \n또한 직접 제어를 한다고 해도 하드웨어의 성능은 제한적이므로 이 환경에서 최대한의 성능을 끌어내기 위해 최적화라는 고통스러운 작업을 해야 할 것이다.\n이러한 상황을 상상해보면 \"배보다 배꼽이 더 크다\"라는 말이 떠오른다.\n\n실제로 운영체제라는 개념이 있기 전에는 사용자들이 하나의 작업을 위해 펀치카드를 소지하며 관리해야 했다.\n그리고 단순 하드웨어에 올려 실행하는 과정의 방식이기에 한 번에 하나의 프로그램만 실행할 수 있었고, 해당 프로그램이 끝나야 다른 프로그램을 수행할 수 있었다. \n지금처럼 복잡한 방식의 프로그램은 꿈도 꿀 수 없었을 것이다.\n\n이러한 문제를 해결하기 위해 운영체제가 나왔고, 다음과 같은 목적을 지닌다.\n\n- 사용자에게 컴퓨터의 프로그램을 쉽고 효율적으로 실행할 수 있는 환경을 제공한다.\n- 컴퓨터 시스템 하드웨어 및 소프트웨어 자원을 여러 사용자 간에 효율적 할당, 관리, 보호하는 것\n- 운영체제는 제어 프로그램으로서 사용자 프로그램의 오류나 잘못된 자원 사용을 감시하는 것과 입출력 장치 등의 자원에 대한 연산과 제어를 관리한다.\n\n운영체제은 위와 같은 목적을 위해 다양한 방식을 가지고 있다.\n\n### 일괄 처리 시스템 (Batch Operating System)\n\n사용자의 개입없이 비슷한 작업들을 모아서 순차적으로 처리하는 방식이다. \n한 작업이 끝나야 다음 작업이 실행되기 때문에 모든 작업이 완료될 때까지 기다릴 수 있는 환경에서 사용된다. \n주로 대용량 데이터를 처리하거나 시간이 많이 소요되는 작업에 활용되며, 사용자의 개입이 필요하지 않고 반복적인 작업을 일괄적으로 처리할 수 있다.\n\n### 다중 프로그래밍 시스템 (Multi Programming System)\n\n이 방식은 CPU을 최대한 사용하고 하는 방식으로,\n여러 응용프로그램을 메모리에 동시에 올라가 CPU가 쉬지 않고 여러 작업을 번갈아서 실행하며 항상 연산을 수행하는 상태로 활용하는 방식이다.\n하나의 프로그램을 실행하는 동안 다른 프로그램은 대기하거나 I/O 작업 등을 수행하며 메모리에 올라간 상태로 대기하게 된다.\n운영 체제는 이런 과정에서 CPU를 배분하는 작업 스케줄링과 CPU 스케줄링을 진행하며, \n이를 통해 시스템 자원을 효율적으로 활용하고 응용 프로그램들이 서로 영향을 주지 않으면서 병렬적으로 실행된다.\n\n### 시분할 시스템 (Time Sharing System)\n\n이 방식은 CPU에 대해 일정 시간을 할당 받아 짧은 간격으로 번갈아 실행하는 방식이다. \n다중 프로그래밍 시스템에서는 Context Switching(CPU 점유 권한 전환)이 I/O작업에서만 발생한다.\n이를 통해서만 스케줄링을 할 경우 하나의 프로세스가 아주 오래 CPU를 독점하고 있는 상태가 발생할 수 있다는 문제점이 있다.\n이를 해결하기 위한 것이 시분할 시스템으로, 다중 프로그래밍과 비슷하지만 모든 프로세스가 특정 시간만 CPU를 점유하고 다른 프로세스에 권한을 넘겨주는 방식으로\nContext Switching 기준 시간으로 시분할을 구현해서 RR(Round-Robin) 알고리즘으로 스케줄링을 한다.\n\n### 대화형 시스템(Interactive System)\n\n앞서 설명한 일괄 처리 시스템은 처리해야할 작업들을 한번에 정의하고 일괄적으로 처리하는 방식이었다.\n이러한 일괄 처리 시스템의 문제점은 처리가 이루어지는 중에 시스템의 상태를 확인하기가 힘들고, \n작업이 끝나 결과가 도출되기 전까지는 작업을 수정할 수도 없다는 문제점이 있었다.\n이를 보완하기위해 등장한 시스템이 대화형 시스템으로, \n작업 중에도 사용자가 데이터, 명령 또는 작업을 입력하면 컴퓨터가 즉각적으로 해당 입력에 응답하는 사용자와 컴퓨터 간의 상호작용을 통해 작동하는 방식이다.\n\n## 커널(Kernel)\n\n그럼 우리들의 컴퓨터 속 운영체제는 어떻게 이러한 기능을 수행하고 있을까?\n\n[운영체제의 이러한 핵심적인 부분을 담당하고 수행하는 것이 바로 커널이다.](https://en.wikipedia.org/wiki/Kernel_(operating_system)#:~:text=A%20kernel%20is%20a%20computer%20program%20at%20the%20core%20of%20a%20computer%27s%20operating%20system%20that%20always%20has%20complete%20control%20over%20everything%20in%20the%20system.) \n\n![](img_3.png)\n커널을 한글로 번역하면 핵심이다! 재밌지 아니한가? 아무튼 다시 돌아와서 커널은 어떻게 운영체제의 기능을 수행할까? \n\n[커널은 하드웨어를 인터페이스로 제공하여 여러 사용자 또는 여러 프로세스가 하드웨어 즉 리소스를 효율적으로 관리하며 작업을 수행할 수 있도록 해준다.](https://en.wikipedia.org/wiki/Kernel_(operating_system)#:~:text=The%20kernel%27s%20interface%20is%20a%20low%2Dlevel%20abstraction%20layer.%20When%20a%20process%20requests%20a%20service%20from%20the%20kernel%2C%20it%20must%20invoke%20a%20system%20call%2C%20usually%20through%20a%20wrapper%20function.)\n여기서 중요한 점은 커널은 사용자가 직접 제어할 수는 없다.\n그 이유는 보안상 유저 어플리케이션이 함부로 운영체제의 리소스를 건들지 못하게 하기 위해서다.\n그래서 커널에는 하드웨어에 접근이 허가된 커널모드와 그렇지 못한 유저모드로 분리가 되어있다.\n\n![](img_1.png)\n\n커널의 구조는 위 사진과 같은데, 간단한 흐름을 설명하자면 사용자가 유저모드인 어플리케이션을 실행하면서 발생하는 요청이 시스템 콜을 통해 커널 모드로 전환이 된다.\n애플리케이션은 커널모드로 전환되었다가 작업을 끝낸 후 응답을 반환하면서 다시 유저모드로 되돌아 가게 된다.\n여기서 시스템 콜은 뭐지 싶을텐데 [어플리케이션의 요청이 커널에 접근해 시스템에 요청하는 것](https://en.wikipedia.org/wiki/System_call#:~:text=In%20computing%2C%20a%20system%20call%20(syscall)%20is%20the%20programmatic%20way%20in%20which%20a%20computer%20program%20requests%20a%20service%20from%20the%20operating%20system%5Ba%5D%20on%20which%20it%20is%20executed.)으로 간단히 유저모드에서 커널모드로 전환하는 것이라고 생각하면 된다. \n\n![](img_4.png)\n\n이러한 방식을 통해 사용자의 프로세스가 직접적으로 운영체제의 리소스를 함부로 변경하지 못하게 보호해준다.\n\n"}]}},"pageContext":{}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git "a/public/page-data/series/CPU-\354\212\244\354\274\200\354\244\204\353\247\201/page-data.json" "b/public/page-data/series/CPU-\354\212\244\354\274\200\354\244\204\353\247\201/page-data.json" new file mode 100644 index 0000000..77e88b5 --- /dev/null +++ "b/public/page-data/series/CPU-\354\212\244\354\274\200\354\244\204\353\247\201/page-data.json" @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-series-jsx","path":"/series/CPU-스케줄링/","result":{"data":{"posts":{"nodes":[{"excerpt":"CPU 할당? 지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용\n하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등\nCPU사용에 …","fields":{"slug":"/jc12/"},"frontmatter":{"date":"September 15, 2025","update":"Sep 15, 2025","title":"CPU 스케줄링의 목적과 스케줄러의 종류","tags":["운영체제"]}},{"excerpt":"선점형? 비선점형? 개요 CPU 스케줄링은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다. 여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다. 선점형 스케줄링 선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다. …","fields":{"slug":"/jc13/"},"frontmatter":{"date":"September 16, 2025","update":"Sep 16, 2025","title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법","tags":["운영체제"]}},{"excerpt":"스케줄링 알고리즘 개요 스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다. 비선점 스케줄링 선입 선처리 스케줄링 (FCFS) 최단 작업 우선 스케줄링 (SJF) 선점 스케줄링 라운드 로빈 스케줄링 최소 잔여 시간 우성 스케줄링 (SRT) 우선순위 스케줄링 비 선점 스케줄링 선입 선처리 스케줄(FCFS) FCFS는 준비 큐에 들…","fields":{"slug":"/jc14/"},"frontmatter":{"date":"September 17, 2025","update":"Sep 17, 2025","title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)","tags":["운영체제"]}},{"excerpt":"다단계 큐 스케쥴링(Multilevel queue scheduling) 멀티 레벨 스케줄링은 우선순위 스케줄링의 발전된 형태입니다.\n아래 그림을 통해 설명 하면, 이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데,\n멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다. 가장 높은 우선순위에 있는 큐들을 처리하고,…","fields":{"slug":"/jc15/"},"frontmatter":{"date":"September 18, 2025","update":"Sep 18, 2025","title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링","tags":["운영체제"]}}]}},"pageContext":{"series":"CPU 스케줄링"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/series/page-data.json b/public/page-data/series/page-data.json index 313d8d2..3b848dd 100644 --- a/public/page-data/series/page-data.json +++ b/public/page-data/series/page-data.json @@ -1 +1 @@ -{"componentChunkName":"component---src-pages-series-jsx","path":"/series/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"allMarkdownRemark":{"group":[{"fieldValue":"운영체제","totalCount":11}],"nodes":[{"excerpt":"동시성 이슈란? img.png 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면…","fields":{"slug":"/11/"},"frontmatter":{"date":"September 14, 2025","update":"Sep 14, 2025","title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"}},{"excerpt":"img.png 멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술이다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것이다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세…","fields":{"slug":"/10/"},"frontmatter":{"date":"September 13, 2025","update":"Sep 13, 2025","title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"}},{"excerpt":"스레드란? img.png 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이…","fields":{"slug":"/9/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"}},{"excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","fields":{"slug":"/8/"},"frontmatter":{"date":"September 11, 2025","update":"Sep 11, 2025","title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"}},{"excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. ![img.png](실행중인 프로세스.png) 백그라운드…","fields":{"slug":"/7/"},"frontmatter":{"date":"September 10, 2025","update":"Sep 10, 2025","title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"}},{"excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","fields":{"slug":"/6/"},"frontmatter":{"date":"September 09, 2025","update":"Sep 09, 2025","title":"6. 동기식/비동기식 I/O의 차이와 활용 사례","tags":["운영체제"],"series":"운영체제 기본 개념"}},{"excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","fields":{"slug":"/5/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리","tags":["운영체제"],"series":"운영체제 기본 개념"}},{"excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. img.png 멀티 프로그래밍 img.png 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하…","fields":{"slug":"/4/"},"frontmatter":{"date":"September 07, 2025","update":"Sep 07, 2025","title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","tags":["운영체제"],"series":"운영체제 기본 개념"}},{"excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. img.png 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비…","fields":{"slug":"/3/"},"frontmatter":{"date":"September 06, 2025","update":"Sep 06, 2025","title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리","tags":["운영체제"],"series":"운영체제 기본 개념"}},{"excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","fields":{"slug":"/2/"},"frontmatter":{"date":"September 05, 2025","update":"Sep 05, 2025","title":"2. CPU 스케줄링, 시스템 자원 관리","tags":["운영체제"],"series":"운영체제 기본 개념"}},{"excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","fields":{"slug":"/1/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"1. 운영체제의 역할과 커널의 기능","tags":["운영체제"],"series":"운영체제 기본 개념"}}]}},"pageContext":{}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file +{"componentChunkName":"component---src-pages-series-jsx","path":"/series/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"allMarkdownRemark":{"group":[{"fieldValue":"운영체제","totalCount":28}],"nodes":[{"excerpt":"서론 지금까지 가상 메모리를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다.\n이러한 행위는 한정된 메모리를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다. 그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다. 불필요한 페이지를 선별 후 스왑 아웃 한다. 프로세스에게 적절한 프레임을 할당한다…","fields":{"slug":"/jc23/"},"frontmatter":{"date":"September 26, 2025","update":"Sep 26, 2025","title":"요구페이징을 잘 수행하기 위해서 필요한 것들","tags":["운영체제"],"series":"가상메모리, 메모리분할"}},{"excerpt":"연속 할당의 문제점 연속적 할당의 대표적인 문제점은 외부 단편화가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해\n필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다. 이러한 문제를 해결하기 위해서는 불연속 할당 방식 중 대표적인 페이징기법을 사용할 수 있습니다. 페이징이란? 페이징 기법은 프로세스를 일정한 단위로 자릅니다. …","fields":{"slug":"/jc22/"},"frontmatter":{"date":"September 25, 2025","update":"Sep 25, 2025","title":"페이징","tags":["운영체제"],"series":"가상메모리, 메모리분할"}},{"excerpt":"연속 메모리 할당 연속 메모리 할당이란 메모리에 프로세스가 그림처럼 연속적으로 배치되는 상황을 가정합니다. 프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다. 이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 스와핑과 관련이 있습니다. 스와핑이란? 메모리는 실행시킬 프로세스를 적재하게 됩니다. 하…","fields":{"slug":"/jc21/"},"frontmatter":{"date":"September 24, 2025","update":"Sep 24, 2025","title":"메모리 배치기법 그리고 단편화에 대해","tags":["운영체제"],"series":"가상메모리, 메모리분할"}},{"excerpt":"물리주소와 논리주소 메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다.\n이 저장된 메모리의 데이터를 CPU 혹은 실행중인 프로그램이 읽어 실행하게 됩니다. 해당 그림은 두가지 관점으로 주소를 나누고 사용하는 방식을 그림으로 나타낸 것입니다. 왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요? 이유는 메모리에 저장되어 있는 정보는 변…","fields":{"slug":"/jc20/"},"frontmatter":{"date":"September 23, 2025","update":"Sep 23, 2025","title":"물리주소, 논리주소 그리고 메모리 분할 방식","tags":["운영체제"],"series":"가상메모리, 메모리분할"}},{"excerpt":"교착상태란?(Dead Lock) 교착상태란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다. 교착상태를 설명하는 대표적인 예시로 식사하는 철학자 문제라는게 있습니다. 식사하는 철학자 식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습…","fields":{"slug":"/jc19/"},"frontmatter":{"date":"September 22, 2025","update":"Sep 22, 2025","title":"교착상태와 해결 방법","tags":["운영체제"],"series":"프로세스 동기화"}},{"excerpt":"상호배제(Mutual Exclusion) 상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다. 일상생활에서 비유하면, 화장실 사용과 같습니다.\n한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다.\n컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 …","fields":{"slug":"/jc18/"},"frontmatter":{"date":"September 21, 2025","update":"Sep 21, 2025","title":"상호배제와 동기화 기법","tags":["운영체제"],"series":"프로세스 동기화"}},{"excerpt":"공유자원 동시에 실행되는 프로세스에서 공통으로 사용하는 자원을 우리는 공유자원이라고 부릅니다. 임계구역(Critical Section) 공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 임계 구역이라고 부릅니다. 두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한…","fields":{"slug":"/jc17/"},"frontmatter":{"date":"September 20, 2025","update":"Sep 20, 2025","title":"임계구역과 경쟁상태","tags":["운영체제"],"series":"프로세스 동기화"}},{"excerpt":"병행성(Concurrency) 병행성은 다른 말로 동시성이라고 부르는 용어입니다.\n이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 컨텍스트 스위칭을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다.\n이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실…","fields":{"slug":"/jc16/"},"frontmatter":{"date":"September 19, 2025","update":"Sep 19, 2025","title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성","tags":["운영체제"],"series":"프로세스 동기화"}},{"excerpt":"다단계 큐 스케쥴링(Multilevel queue scheduling) 멀티 레벨 스케줄링은 우선순위 스케줄링의 발전된 형태입니다.\n아래 그림을 통해 설명 하면, 이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데,\n멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다. 가장 높은 우선순위에 있는 큐들을 처리하고,…","fields":{"slug":"/jc15/"},"frontmatter":{"date":"September 18, 2025","update":"Sep 18, 2025","title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링","tags":["운영체제"],"series":"CPU 스케줄링"}},{"excerpt":"스케줄링 알고리즘 개요 스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다. 비선점 스케줄링 선입 선처리 스케줄링 (FCFS) 최단 작업 우선 스케줄링 (SJF) 선점 스케줄링 라운드 로빈 스케줄링 최소 잔여 시간 우성 스케줄링 (SRT) 우선순위 스케줄링 비 선점 스케줄링 선입 선처리 스케줄(FCFS) FCFS는 준비 큐에 들…","fields":{"slug":"/jc14/"},"frontmatter":{"date":"September 17, 2025","update":"Sep 17, 2025","title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)","tags":["운영체제"],"series":"CPU 스케줄링"}},{"excerpt":"선점형? 비선점형? 개요 CPU 스케줄링은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다. 여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다. 선점형 스케줄링 선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다. …","fields":{"slug":"/jc13/"},"frontmatter":{"date":"September 16, 2025","update":"Sep 16, 2025","title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법","tags":["운영체제"],"series":"CPU 스케줄링"}},{"excerpt":"CPU 할당? 지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용\n하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등\nCPU사용에 …","fields":{"slug":"/jc12/"},"frontmatter":{"date":"September 15, 2025","update":"Sep 15, 2025","title":"CPU 스케줄링의 목적과 스케줄러의 종류","tags":["운영체제"],"series":"CPU 스케줄링"}},{"excerpt":"동시성 이슈란? 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면 11가 됩니…","fields":{"slug":"/jc11/"},"frontmatter":{"date":"September 14, 2025","update":"Sep 14, 2025","title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"}},{"excerpt":"멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술입니다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것입니다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부…","fields":{"slug":"/jc10/"},"frontmatter":{"date":"September 13, 2025","update":"Sep 13, 2025","title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"}},{"excerpt":"기아 상태와 CPU 스케줄링 프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다.\n그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나,\n너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고\n이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다.\n이를 컴퓨팅에서…","fields":{"slug":"/hs5/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"5. CPU 스케줄링","tags":["운영체제"],"series":"운영체제"}},{"excerpt":"스레드란? 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이 여러 기능을…","fields":{"slug":"/jc9/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"쓰레드의 개념, 메모리 공유 구조 및 TCB","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"}},{"excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","fields":{"slug":"/jc8/"},"frontmatter":{"date":"September 11, 2025","update":"Sep 11, 2025","title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"}},{"excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. 백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는…","fields":{"slug":"/jc7/"},"frontmatter":{"date":"September 10, 2025","update":"Sep 10, 2025","title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","tags":["운영체제"],"series":"프로세스와 쓰레드에 대해서 알아보기"}},{"excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","fields":{"slug":"/jc6/"},"frontmatter":{"date":"September 09, 2025","update":"Sep 09, 2025","title":"동기식/비동기식 I/O의 차이와 활용 사례","tags":["운영체제"],"series":"운영체제 기본 개념"}},{"excerpt":"쓰레드란? 쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다. 그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다.\n이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다. 사용자 수준 쓰레드와 커널 수준 쓰레드의 차이 사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다.\n쓰레드와 관련된 모든 행위를 사용자 영…","fields":{"slug":"/hs4/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"4. 쓰레드 ","tags":["운영체제"],"series":"운영체제"}},{"excerpt":"프로세스란? 컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 인스턴스를 의미합니다.\n여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다. 프로세스의 메모리 공간 프로세스는 다음 4개의 메모리 영역으로 구성되고 가상 메모리 공간에 독립적으로 형성됩니다. 코드 영역(Cod…","fields":{"slug":"/hs3/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"3. 프로세스","tags":["운영체제"],"series":"운영체제"}},{"excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","fields":{"slug":"/jc5/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"인터럽트와 DMA를 통한 효율적 입출력 처리","tags":["운영체제"],"series":"운영체제 기본 개념"}},{"excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. 멀티 프로그래밍 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다.…","fields":{"slug":"/jc4/"},"frontmatter":{"date":"September 07, 2025","update":"Sep 07, 2025","title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","tags":["운영체제"],"series":"운영체제 기본 개념"}},{"excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비스를 제공받을…","fields":{"slug":"/jc3/"},"frontmatter":{"date":"September 06, 2025","update":"Sep 06, 2025","title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리","tags":["운영체제"],"series":"운영체제 기본 개념"}},{"excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","fields":{"slug":"/jc2/"},"frontmatter":{"date":"September 05, 2025","update":"Sep 05, 2025","title":"CPU 스케줄링, 시스템 자원 관리","tags":["운영체제"],"series":"운영체제 기본 개념"}},{"excerpt":"앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다.\n이제 커널이 어떻게 작동하는지 제대로 알아보자. 먼저 인터럽트(Interrupt)에 대해 알아야 한다. 컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데\n이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다.\n이중 하나가 인터럽트이다. \n인터럽트는 중단시키다라…","fields":{"slug":"/hs2/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"2. 커널의 작동 방식","tags":["운영체제"],"series":"운영체제"}},{"excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","fields":{"slug":"/jc1/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"운영체제의 역할과 커널의 기능","tags":["운영체제"],"series":"운영체제 기본 개념"}},{"excerpt":"운영체제(OS, Operating System) 운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다. 운영체제가 없으면 어떻게 될까? 꼭 필요할까? A computer is a machine that can be programmed to automatically carry ou…","fields":{"slug":"/hs1/"},"frontmatter":{"date":"September 03, 2025","update":"Sep 03, 2025","title":"1. 운영체제의 개념과 구조","tags":["운영체제"],"series":"운영체제"}}]}},"pageContext":{}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git "a/public/page-data/series/\352\260\200\354\203\201\353\251\224\353\252\250\353\246\254,-\353\251\224\353\252\250\353\246\254\353\266\204\355\225\240/page-data.json" "b/public/page-data/series/\352\260\200\354\203\201\353\251\224\353\252\250\353\246\254,-\353\251\224\353\252\250\353\246\254\353\266\204\355\225\240/page-data.json" new file mode 100755 index 0000000..e1c4c26 --- /dev/null +++ "b/public/page-data/series/\352\260\200\354\203\201\353\251\224\353\252\250\353\246\254,-\353\251\224\353\252\250\353\246\254\353\266\204\355\225\240/page-data.json" @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-series-jsx","path":"/series/가상메모리,-메모리분할/","result":{"data":{"posts":{"nodes":[{"excerpt":"물리주소와 논리주소 메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다.\n이 저장된 메모리의 데이터를 CPU 혹은 실행중인 프로그램이 읽어 실행하게 됩니다. 해당 그림은 두가지 관점으로 주소를 나누고 사용하는 방식을 그림으로 나타낸 것입니다. 왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요? 이유는 메모리에 저장되어 있는 정보는 변…","fields":{"slug":"/jc20/"},"frontmatter":{"date":"September 23, 2025","update":"Sep 23, 2025","title":"물리주소, 논리주소 그리고 메모리 분할 방식","tags":["운영체제"]}},{"excerpt":"연속 메모리 할당 연속 메모리 할당이란 메모리에 프로세스가 그림처럼 연속적으로 배치되는 상황을 가정합니다. 프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다. 이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 스와핑과 관련이 있습니다. 스와핑이란? 메모리는 실행시킬 프로세스를 적재하게 됩니다. 하…","fields":{"slug":"/jc21/"},"frontmatter":{"date":"September 24, 2025","update":"Sep 24, 2025","title":"메모리 배치기법 그리고 단편화에 대해","tags":["운영체제"]}},{"excerpt":"연속 할당의 문제점 연속적 할당의 대표적인 문제점은 외부 단편화가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해\n필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다. 이러한 문제를 해결하기 위해서는 불연속 할당 방식 중 대표적인 페이징기법을 사용할 수 있습니다. 페이징이란? 페이징 기법은 프로세스를 일정한 단위로 자릅니다. …","fields":{"slug":"/jc22/"},"frontmatter":{"date":"September 25, 2025","update":"Sep 25, 2025","title":"페이징","tags":["운영체제"]}},{"excerpt":"서론 지금까지 가상 메모리를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다.\n이러한 행위는 한정된 메모리를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다. 그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다. 불필요한 페이지를 선별 후 스왑 아웃 한다. 프로세스에게 적절한 프레임을 할당한다…","fields":{"slug":"/jc23/"},"frontmatter":{"date":"September 26, 2025","update":"Sep 26, 2025","title":"요구페이징을 잘 수행하기 위해서 필요한 것들","tags":["운영체제"]}}]}},"pageContext":{"series":"가상메모리, 메모리분할"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git "a/public/page-data/series/\354\232\264\354\230\201\354\262\264\354\240\234-\352\270\260\353\263\270-\352\260\234\353\205\220/page-data.json" "b/public/page-data/series/\354\232\264\354\230\201\354\262\264\354\240\234-\352\270\260\353\263\270-\352\260\234\353\205\220/page-data.json" index 794f592..bbada01 100644 --- "a/public/page-data/series/\354\232\264\354\230\201\354\262\264\354\240\234-\352\270\260\353\263\270-\352\260\234\353\205\220/page-data.json" +++ "b/public/page-data/series/\354\232\264\354\230\201\354\262\264\354\240\234-\352\270\260\353\263\270-\352\260\234\353\205\220/page-data.json" @@ -1 +1 @@ -{"componentChunkName":"component---src-templates-series-jsx","path":"/series/운영체제-기본-개념/","result":{"data":{"posts":{"nodes":[{"excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","fields":{"slug":"/1/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"1. 운영체제의 역할과 커널의 기능","tags":["운영체제"]}},{"excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","fields":{"slug":"/2/"},"frontmatter":{"date":"September 05, 2025","update":"Sep 05, 2025","title":"2. CPU 스케줄링, 시스템 자원 관리","tags":["운영체제"]}},{"excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. img.png 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비…","fields":{"slug":"/3/"},"frontmatter":{"date":"September 06, 2025","update":"Sep 06, 2025","title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리","tags":["운영체제"]}},{"excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. img.png 멀티 프로그래밍 img.png 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하…","fields":{"slug":"/4/"},"frontmatter":{"date":"September 07, 2025","update":"Sep 07, 2025","title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","tags":["운영체제"]}},{"excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","fields":{"slug":"/5/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리","tags":["운영체제"]}},{"excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","fields":{"slug":"/6/"},"frontmatter":{"date":"September 09, 2025","update":"Sep 09, 2025","title":"6. 동기식/비동기식 I/O의 차이와 활용 사례","tags":["운영체제"]}}]}},"pageContext":{"series":"운영체제 기본 개념"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file +{"componentChunkName":"component---src-templates-series-jsx","path":"/series/운영체제-기본-개념/","result":{"data":{"posts":{"nodes":[{"excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","fields":{"slug":"/jc1/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"운영체제의 역할과 커널의 기능","tags":["운영체제"]}},{"excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","fields":{"slug":"/jc2/"},"frontmatter":{"date":"September 05, 2025","update":"Sep 05, 2025","title":"CPU 스케줄링, 시스템 자원 관리","tags":["운영체제"]}},{"excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비스를 제공받을…","fields":{"slug":"/jc3/"},"frontmatter":{"date":"September 06, 2025","update":"Sep 06, 2025","title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리","tags":["운영체제"]}},{"excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. 멀티 프로그래밍 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다.…","fields":{"slug":"/jc4/"},"frontmatter":{"date":"September 07, 2025","update":"Sep 07, 2025","title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","tags":["운영체제"]}},{"excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","fields":{"slug":"/jc5/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"인터럽트와 DMA를 통한 효율적 입출력 처리","tags":["운영체제"]}},{"excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","fields":{"slug":"/jc6/"},"frontmatter":{"date":"September 09, 2025","update":"Sep 09, 2025","title":"동기식/비동기식 I/O의 차이와 활용 사례","tags":["운영체제"]}}]}},"pageContext":{"series":"운영체제 기본 개념"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git "a/public/page-data/series/\354\232\264\354\230\201\354\262\264\354\240\234/page-data.json" "b/public/page-data/series/\354\232\264\354\230\201\354\262\264\354\240\234/page-data.json" new file mode 100755 index 0000000..454e969 --- /dev/null +++ "b/public/page-data/series/\354\232\264\354\230\201\354\262\264\354\240\234/page-data.json" @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-series-jsx","path":"/series/운영체제/","result":{"data":{"posts":{"nodes":[{"excerpt":"운영체제(OS, Operating System) 운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다. 운영체제가 없으면 어떻게 될까? 꼭 필요할까? A computer is a machine that can be programmed to automatically carry ou…","fields":{"slug":"/hs1/"},"frontmatter":{"date":"September 03, 2025","update":"Sep 03, 2025","title":"1. 운영체제의 개념과 구조","tags":["운영체제"]}},{"excerpt":"앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다.\n이제 커널이 어떻게 작동하는지 제대로 알아보자. 먼저 인터럽트(Interrupt)에 대해 알아야 한다. 컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데\n이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다.\n이중 하나가 인터럽트이다. \n인터럽트는 중단시키다라…","fields":{"slug":"/hs2/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"2. 커널의 작동 방식","tags":["운영체제"]}},{"excerpt":"쓰레드란? 쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다. 그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다.\n이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다. 사용자 수준 쓰레드와 커널 수준 쓰레드의 차이 사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다.\n쓰레드와 관련된 모든 행위를 사용자 영…","fields":{"slug":"/hs4/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"4. 쓰레드 ","tags":["운영체제"]}},{"excerpt":"프로세스란? 컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 인스턴스를 의미합니다.\n여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다. 프로세스의 메모리 공간 프로세스는 다음 4개의 메모리 영역으로 구성되고 가상 메모리 공간에 독립적으로 형성됩니다. 코드 영역(Cod…","fields":{"slug":"/hs3/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"3. 프로세스","tags":["운영체제"]}},{"excerpt":"기아 상태와 CPU 스케줄링 프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다.\n그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나,\n너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고\n이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다.\n이를 컴퓨팅에서…","fields":{"slug":"/hs5/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"5. CPU 스케줄링","tags":["운영체제"]}}]}},"pageContext":{"series":"운영체제"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git "a/public/page-data/series/\355\224\204\353\241\234\354\204\270\354\212\244-\353\217\231\352\270\260\355\231\224/page-data.json" "b/public/page-data/series/\355\224\204\353\241\234\354\204\270\354\212\244-\353\217\231\352\270\260\355\231\224/page-data.json" new file mode 100644 index 0000000..85ea8bf --- /dev/null +++ "b/public/page-data/series/\355\224\204\353\241\234\354\204\270\354\212\244-\353\217\231\352\270\260\355\231\224/page-data.json" @@ -0,0 +1 @@ +{"componentChunkName":"component---src-templates-series-jsx","path":"/series/프로세스-동기화/","result":{"data":{"posts":{"nodes":[{"excerpt":"병행성(Concurrency) 병행성은 다른 말로 동시성이라고 부르는 용어입니다.\n이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 컨텍스트 스위칭을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다.\n이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실…","fields":{"slug":"/jc16/"},"frontmatter":{"date":"September 19, 2025","update":"Sep 19, 2025","title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성","tags":["운영체제"]}},{"excerpt":"공유자원 동시에 실행되는 프로세스에서 공통으로 사용하는 자원을 우리는 공유자원이라고 부릅니다. 임계구역(Critical Section) 공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 임계 구역이라고 부릅니다. 두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한…","fields":{"slug":"/jc17/"},"frontmatter":{"date":"September 20, 2025","update":"Sep 20, 2025","title":"임계구역과 경쟁상태","tags":["운영체제"]}},{"excerpt":"상호배제(Mutual Exclusion) 상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다. 일상생활에서 비유하면, 화장실 사용과 같습니다.\n한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다.\n컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 …","fields":{"slug":"/jc18/"},"frontmatter":{"date":"September 21, 2025","update":"Sep 21, 2025","title":"상호배제와 동기화 기법","tags":["운영체제"]}},{"excerpt":"교착상태란?(Dead Lock) 교착상태란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다. 교착상태를 설명하는 대표적인 예시로 식사하는 철학자 문제라는게 있습니다. 식사하는 철학자 식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습…","fields":{"slug":"/jc19/"},"frontmatter":{"date":"September 22, 2025","update":"Sep 22, 2025","title":"교착상태와 해결 방법","tags":["운영체제"]}}]}},"pageContext":{"series":"프로세스 동기화"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git "a/public/page-data/series/\355\224\204\353\241\234\354\204\270\354\212\244\354\231\200-\354\223\260\353\240\210\353\223\234\354\227\220-\353\214\200\355\225\264\354\204\234-\354\225\214\354\225\204\353\263\264\352\270\260/page-data.json" "b/public/page-data/series/\355\224\204\353\241\234\354\204\270\354\212\244\354\231\200-\354\223\260\353\240\210\353\223\234\354\227\220-\353\214\200\355\225\264\354\204\234-\354\225\214\354\225\204\353\263\264\352\270\260/page-data.json" index 9b4c05d..cc2c752 100644 --- "a/public/page-data/series/\355\224\204\353\241\234\354\204\270\354\212\244\354\231\200-\354\223\260\353\240\210\353\223\234\354\227\220-\353\214\200\355\225\264\354\204\234-\354\225\214\354\225\204\353\263\264\352\270\260/page-data.json" +++ "b/public/page-data/series/\355\224\204\353\241\234\354\204\270\354\212\244\354\231\200-\354\223\260\353\240\210\353\223\234\354\227\220-\353\214\200\355\225\264\354\204\234-\354\225\214\354\225\204\353\263\264\352\270\260/page-data.json" @@ -1 +1 @@ -{"componentChunkName":"component---src-templates-series-jsx","path":"/series/프로세스와-쓰레드에-대해서-알아보기/","result":{"data":{"posts":{"nodes":[{"excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. ![img.png](실행중인 프로세스.png) 백그라운드…","fields":{"slug":"/7/"},"frontmatter":{"date":"September 10, 2025","update":"Sep 10, 2025","title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","tags":["운영체제"]}},{"excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","fields":{"slug":"/8/"},"frontmatter":{"date":"September 11, 2025","update":"Sep 11, 2025","title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","tags":["운영체제"]}},{"excerpt":"스레드란? img.png 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이…","fields":{"slug":"/9/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB","tags":["운영체제"]}},{"excerpt":"img.png 멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술이다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것이다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세…","fields":{"slug":"/10/"},"frontmatter":{"date":"September 13, 2025","update":"Sep 13, 2025","title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","tags":["운영체제"]}},{"excerpt":"동시성 이슈란? img.png 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면…","fields":{"slug":"/11/"},"frontmatter":{"date":"September 14, 2025","update":"Sep 14, 2025","title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","tags":["운영체제"]}}]}},"pageContext":{"series":"프로세스와 쓰레드에 대해서 알아보기"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file +{"componentChunkName":"component---src-templates-series-jsx","path":"/series/프로세스와-쓰레드에-대해서-알아보기/","result":{"data":{"posts":{"nodes":[{"excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. 백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는…","fields":{"slug":"/jc7/"},"frontmatter":{"date":"September 10, 2025","update":"Sep 10, 2025","title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","tags":["운영체제"]}},{"excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","fields":{"slug":"/jc8/"},"frontmatter":{"date":"September 11, 2025","update":"Sep 11, 2025","title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","tags":["운영체제"]}},{"excerpt":"스레드란? 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이 여러 기능을…","fields":{"slug":"/jc9/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"쓰레드의 개념, 메모리 공유 구조 및 TCB","tags":["운영체제"]}},{"excerpt":"멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술입니다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것입니다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부…","fields":{"slug":"/jc10/"},"frontmatter":{"date":"September 13, 2025","update":"Sep 13, 2025","title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","tags":["운영체제"]}},{"excerpt":"동시성 이슈란? 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면 11가 됩니…","fields":{"slug":"/jc11/"},"frontmatter":{"date":"September 14, 2025","update":"Sep 14, 2025","title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","tags":["운영체제"]}}]}},"pageContext":{"series":"프로세스와 쓰레드에 대해서 알아보기"}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/page-data/sq/d/1132682437.json b/public/page-data/sq/d/1132682437.json old mode 100644 new mode 100755 diff --git a/public/page-data/tags/page-data.json b/public/page-data/tags/page-data.json index a3cbf38..0f24b13 100644 --- a/public/page-data/tags/page-data.json +++ b/public/page-data/tags/page-data.json @@ -1 +1 @@ -{"componentChunkName":"component---src-pages-tags-jsx","path":"/tags/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"allMarkdownRemark":{"group":[{"fieldValue":"운영체제","totalCount":11}],"nodes":[{"excerpt":"동시성 이슈란? img.png 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면…","fields":{"slug":"/11/"},"frontmatter":{"date":"September 14, 2025","update":"Sep 14, 2025","title":"11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","tags":["운영체제"]}},{"excerpt":"img.png 멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술이다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것이다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세…","fields":{"slug":"/10/"},"frontmatter":{"date":"September 13, 2025","update":"Sep 13, 2025","title":"10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","tags":["운영체제"]}},{"excerpt":"스레드란? img.png 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이…","fields":{"slug":"/9/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"9. 쓰레드의 개념, 메모리 공유 구조 및 TCB","tags":["운영체제"]}},{"excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","fields":{"slug":"/8/"},"frontmatter":{"date":"September 11, 2025","update":"Sep 11, 2025","title":"8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","tags":["운영체제"]}},{"excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. ![img.png](실행중인 프로세스.png) 백그라운드…","fields":{"slug":"/7/"},"frontmatter":{"date":"September 10, 2025","update":"Sep 10, 2025","title":"7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","tags":["운영체제"]}},{"excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","fields":{"slug":"/6/"},"frontmatter":{"date":"September 09, 2025","update":"Sep 09, 2025","title":"6. 동기식/비동기식 I/O의 차이와 활용 사례","tags":["운영체제"]}},{"excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","fields":{"slug":"/5/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"5. 인터럽트와 DMA를 통한 효율적 입출력 처리","tags":["운영체제"]}},{"excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. img.png 멀티 프로그래밍 img.png 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하…","fields":{"slug":"/4/"},"frontmatter":{"date":"September 07, 2025","update":"Sep 07, 2025","title":"4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","tags":["운영체제"]}},{"excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. img.png 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비…","fields":{"slug":"/3/"},"frontmatter":{"date":"September 06, 2025","update":"Sep 06, 2025","title":"3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리","tags":["운영체제"]}},{"excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","fields":{"slug":"/2/"},"frontmatter":{"date":"September 05, 2025","update":"Sep 05, 2025","title":"2. CPU 스케줄링, 시스템 자원 관리","tags":["운영체제"]}},{"excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","fields":{"slug":"/1/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"1. 운영체제의 역할과 커널의 기능","tags":["운영체제"]}}]}},"pageContext":{}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file +{"componentChunkName":"component---src-pages-tags-jsx","path":"/tags/","result":{"data":{"site":{"siteMetadata":{"title":"CATCH NPE"}},"allMarkdownRemark":{"group":[{"fieldValue":"운영체제","totalCount":28}],"nodes":[{"excerpt":"서론 지금까지 가상 메모리를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다.\n이러한 행위는 한정된 메모리를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다. 그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다. 불필요한 페이지를 선별 후 스왑 아웃 한다. 프로세스에게 적절한 프레임을 할당한다…","fields":{"slug":"/jc23/"},"frontmatter":{"date":"September 26, 2025","update":"Sep 26, 2025","title":"요구페이징을 잘 수행하기 위해서 필요한 것들","tags":["운영체제"]}},{"excerpt":"연속 할당의 문제점 연속적 할당의 대표적인 문제점은 외부 단편화가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해\n필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다. 이러한 문제를 해결하기 위해서는 불연속 할당 방식 중 대표적인 페이징기법을 사용할 수 있습니다. 페이징이란? 페이징 기법은 프로세스를 일정한 단위로 자릅니다. …","fields":{"slug":"/jc22/"},"frontmatter":{"date":"September 25, 2025","update":"Sep 25, 2025","title":"페이징","tags":["운영체제"]}},{"excerpt":"연속 메모리 할당 연속 메모리 할당이란 메모리에 프로세스가 그림처럼 연속적으로 배치되는 상황을 가정합니다. 프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다. 이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 스와핑과 관련이 있습니다. 스와핑이란? 메모리는 실행시킬 프로세스를 적재하게 됩니다. 하…","fields":{"slug":"/jc21/"},"frontmatter":{"date":"September 24, 2025","update":"Sep 24, 2025","title":"메모리 배치기법 그리고 단편화에 대해","tags":["운영체제"]}},{"excerpt":"물리주소와 논리주소 메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다.\n이 저장된 메모리의 데이터를 CPU 혹은 실행중인 프로그램이 읽어 실행하게 됩니다. 해당 그림은 두가지 관점으로 주소를 나누고 사용하는 방식을 그림으로 나타낸 것입니다. 왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요? 이유는 메모리에 저장되어 있는 정보는 변…","fields":{"slug":"/jc20/"},"frontmatter":{"date":"September 23, 2025","update":"Sep 23, 2025","title":"물리주소, 논리주소 그리고 메모리 분할 방식","tags":["운영체제"]}},{"excerpt":"교착상태란?(Dead Lock) 교착상태란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다. 교착상태를 설명하는 대표적인 예시로 식사하는 철학자 문제라는게 있습니다. 식사하는 철학자 식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습…","fields":{"slug":"/jc19/"},"frontmatter":{"date":"September 22, 2025","update":"Sep 22, 2025","title":"교착상태와 해결 방법","tags":["운영체제"]}},{"excerpt":"상호배제(Mutual Exclusion) 상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다. 일상생활에서 비유하면, 화장실 사용과 같습니다.\n한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다.\n컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 …","fields":{"slug":"/jc18/"},"frontmatter":{"date":"September 21, 2025","update":"Sep 21, 2025","title":"상호배제와 동기화 기법","tags":["운영체제"]}},{"excerpt":"공유자원 동시에 실행되는 프로세스에서 공통으로 사용하는 자원을 우리는 공유자원이라고 부릅니다. 임계구역(Critical Section) 공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 임계 구역이라고 부릅니다. 두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한…","fields":{"slug":"/jc17/"},"frontmatter":{"date":"September 20, 2025","update":"Sep 20, 2025","title":"임계구역과 경쟁상태","tags":["운영체제"]}},{"excerpt":"병행성(Concurrency) 병행성은 다른 말로 동시성이라고 부르는 용어입니다.\n이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 컨텍스트 스위칭을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다.\n이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실…","fields":{"slug":"/jc16/"},"frontmatter":{"date":"September 19, 2025","update":"Sep 19, 2025","title":"병행성과 병렬성의 차이 및 프로세스 동기화의 필요성","tags":["운영체제"]}},{"excerpt":"다단계 큐 스케쥴링(Multilevel queue scheduling) 멀티 레벨 스케줄링은 우선순위 스케줄링의 발전된 형태입니다.\n아래 그림을 통해 설명 하면, 이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데,\n멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다. 가장 높은 우선순위에 있는 큐들을 처리하고,…","fields":{"slug":"/jc15/"},"frontmatter":{"date":"September 18, 2025","update":"Sep 18, 2025","title":"멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링","tags":["운영체제"]}},{"excerpt":"스케줄링 알고리즘 개요 스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다. 비선점 스케줄링 선입 선처리 스케줄링 (FCFS) 최단 작업 우선 스케줄링 (SJF) 선점 스케줄링 라운드 로빈 스케줄링 최소 잔여 시간 우성 스케줄링 (SRT) 우선순위 스케줄링 비 선점 스케줄링 선입 선처리 스케줄(FCFS) FCFS는 준비 큐에 들…","fields":{"slug":"/jc14/"},"frontmatter":{"date":"September 17, 2025","update":"Sep 17, 2025","title":"CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)","tags":["운영체제"]}},{"excerpt":"선점형? 비선점형? 개요 CPU 스케줄링은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다. 여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다. 선점형 스케줄링 선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다. …","fields":{"slug":"/jc13/"},"frontmatter":{"date":"September 16, 2025","update":"Sep 16, 2025","title":"선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법","tags":["운영체제"]}},{"excerpt":"CPU 할당? 지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용\n하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등\nCPU사용에 …","fields":{"slug":"/jc12/"},"frontmatter":{"date":"September 15, 2025","update":"Sep 15, 2025","title":"CPU 스케줄링의 목적과 스케줄러의 종류","tags":["운영체제"]}},{"excerpt":"동시성 이슈란? 동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다. 예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다.\n스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때\n스레드 a가 좋아요 카운트를 늘리면 11가 됩니…","fields":{"slug":"/jc11/"},"frontmatter":{"date":"September 14, 2025","update":"Sep 14, 2025","title":"멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법","tags":["운영체제"]}},{"excerpt":"멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술입니다.\n보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해\n여러개의 프로세스를 생성하는 것입니다. 어떻게 멀티 프로세스를 생성할까? 멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부…","fields":{"slug":"/jc10/"},"frontmatter":{"date":"September 13, 2025","update":"Sep 13, 2025","title":"멀티 프로세스와 멀티 쓰레드의 차이 및 장단점","tags":["운영체제"]}},{"excerpt":"기아 상태와 CPU 스케줄링 프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다.\n그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나,\n너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고\n이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다.\n이를 컴퓨팅에서…","fields":{"slug":"/hs5/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"5. CPU 스케줄링","tags":["운영체제"]}},{"excerpt":"스레드란? 스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다. 또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면\n하나의 프로세스에서 여러 부분을 동시에 실행할 수 있습니다. 마치 화상 회의를 진행중에 회의 어플리케이션이란 프로세스 속 채팅과 화상통화의 기능이 독립적으로 돌아가는것과\n같이 여러 기능을…","fields":{"slug":"/jc9/"},"frontmatter":{"date":"September 12, 2025","update":"Sep 12, 2025","title":"쓰레드의 개념, 메모리 공유 구조 및 TCB","tags":["운영체제"]}},{"excerpt":"문맥교환(Context Switching) 하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요? 프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를\n저장하여야 합니다. 이곳에서는 이전에 보았던 PCB의 값인 레지스터 값, 메모리 정보등 중간 정보를 저장하여야\n이후 자신의 차례가 왔…","fields":{"slug":"/jc8/"},"frontmatter":{"date":"September 11, 2025","update":"Sep 11, 2025","title":"문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기","tags":["운영체제"]}},{"excerpt":"프로세스란 무엇일까? 우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다. 여기서 실행된 프로그램을 프로세스라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다. 백그라운드 프로세스라고 해서 사용자와 상호작용하지 않는…","fields":{"slug":"/jc7/"},"frontmatter":{"date":"September 10, 2025","update":"Sep 10, 2025","title":"프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기","tags":["운영체제"]}},{"excerpt":"IO란 개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를\n주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다. 예시를 들어서 파일 읽기/쓰기 (문서를 열거나 저장하는 행위) 네트워크 통신(웹사이트 접속, 이메일 전송) 데이터베이스 조회(회원 정보 검색) 이런 일련의 행위는 공통적…","fields":{"slug":"/jc6/"},"frontmatter":{"date":"September 09, 2025","update":"Sep 09, 2025","title":"동기식/비동기식 I/O의 차이와 활용 사례","tags":["운영체제"]}},{"excerpt":"쓰레드란? 쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다. 그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다.\n이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다. 사용자 수준 쓰레드와 커널 수준 쓰레드의 차이 사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다.\n쓰레드와 관련된 모든 행위를 사용자 영…","fields":{"slug":"/hs4/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"4. 쓰레드 ","tags":["운영체제"]}},{"excerpt":"프로세스란? 컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 인스턴스를 의미합니다.\n여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다. 프로세스의 메모리 공간 프로세스는 다음 4개의 메모리 영역으로 구성되고 가상 메모리 공간에 독립적으로 형성됩니다. 코드 영역(Cod…","fields":{"slug":"/hs3/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"3. 프로세스","tags":["운영체제"]}},{"excerpt":"인터럽트 기반 입출력 인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한\n방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다. 인터럽트는 크게 두가지로 나뉘게 되며, 소프트웨어 혹은 하드웨어 인터럽트로 나누어지며 이는 인터럽트…","fields":{"slug":"/jc5/"},"frontmatter":{"date":"September 08, 2025","update":"Sep 08, 2025","title":"인터럽트와 DMA를 통한 효율적 입출력 처리","tags":["운영체제"]}},{"excerpt":"단일 프로세스 초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다.\n이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나,\n끝날때 까지 기다려야 합니다. 멀티 프로그래밍 이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다.…","fields":{"slug":"/jc4/"},"frontmatter":{"date":"September 07, 2025","update":"Sep 07, 2025","title":"멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념","tags":["운영체제"]}},{"excerpt":"이중모드 운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다. 그럼 일반 응용프로그램은 어떻게 자원에 접근 할 수 있을까요? 이에 대한 답은 이중 모드 입니다. 위 사진 처럼 CPU가 명령을 실행하는 방식을 사용자 모드 와 커널 모드로 나누어 사용하게 됩니다. 사용자 모드 사용자 모드는 운영체제 서비스를 제공받을…","fields":{"slug":"/jc3/"},"frontmatter":{"date":"September 06, 2025","update":"Sep 06, 2025","title":"유저모드와 커널모드 전환, 시스템 콜의 동작 원리","tags":["운영체제"]}},{"excerpt":"CPU 스케줄링 CPU 스케줄링은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며,\n모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다. CPU 스케줄링이란 프로세스의 작업을 수행하기 위해 언제, 어떤 프로세스에 CPU를 할당할지 결정하는 작업을 말합니다.\n CPU 스케줄링 원칙 CPU는 스케줄링을 하…","fields":{"slug":"/jc2/"},"frontmatter":{"date":"September 05, 2025","update":"Sep 05, 2025","title":"CPU 스케줄링, 시스템 자원 관리","tags":["운영체제"]}},{"excerpt":"앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다.\n이제 커널이 어떻게 작동하는지 제대로 알아보자. 먼저 인터럽트(Interrupt)에 대해 알아야 한다. 컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데\n이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다.\n이중 하나가 인터럽트이다. \n인터럽트는 중단시키다라…","fields":{"slug":"/hs2/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"2. 커널의 작동 방식","tags":["운영체제"]}},{"excerpt":"운영체제란 무엇일까? 운영체제는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 자원을 관리하고,\n 프로세스를 관리하는 등 여러가지 일을 수행합니다. 이러한 운영체제는 프로그램을 위한 프로그램으로서 작동하게 되며, 여러 프로그램을 충돌없이 효율적으로 사용하는 기능을 제공합니다. 운영체제의 역할 …","fields":{"slug":"/jc1/"},"frontmatter":{"date":"September 04, 2025","update":"Sep 04, 2025","title":"운영체제의 역할과 커널의 기능","tags":["운영체제"]}},{"excerpt":"운영체제(OS, Operating System) 운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다. 운영체제가 없으면 어떻게 될까? 꼭 필요할까? A computer is a machine that can be programmed to automatically carry ou…","fields":{"slug":"/hs1/"},"frontmatter":{"date":"September 03, 2025","update":"Sep 03, 2025","title":"1. 운영체제의 개념과 구조","tags":["운영체제"]}}]}},"pageContext":{}},"staticQueryHashes":[],"slicesMap":{}} \ No newline at end of file diff --git a/public/profile.png b/public/profile.png old mode 100644 new mode 100755 diff --git a/public/robots.txt b/public/robots.txt old mode 100644 new mode 100755 diff --git a/public/rss.xml b/public/rss.xml index 360a2a9..9c5c34f 100644 --- a/public/rss.xml +++ b/public/rss.xml @@ -1,21 +1,1573 @@ -<![CDATA[RSS Feed of CATCH NPE]]>https://catch-npe.netlify.appGatsbyJSThu, 11 Sep 2025 10:23:40 GMT<![CDATA[11. 멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법]]>https://catch-npe.netlify.app/11/https://catch-npe.netlify.app/11/Sun, 14 Sep 2025 00:00:00 GMT<h2 id="동시성-이슈란" style="position:relative;"><a href="#%EB%8F%99%EC%8B%9C%EC%84%B1-%EC%9D%B4%EC%8A%88%EB%9E%80" aria-label="동시성 이슈란 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>동시성 이슈란?</h2> +<![CDATA[RSS Feed of CATCH NPE]]>https://catch-npe.netlify.appGatsbyJSFri, 26 Sep 2025 02:07:45 GMT<![CDATA[요구페이징을 잘 수행하기 위해서 필요한 것들]]>https://catch-npe.netlify.app/jc23/https://catch-npe.netlify.app/jc23/Fri, 26 Sep 2025 00:00:00 GMT<h2 id="서론" style="position:relative;"><a href="#%EC%84%9C%EB%A1%A0" aria-label="서론 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>서론</h2> +<hr> +<p>지금까지 <strong>가상 메모리</strong>를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다. +이러한 행위는 한정된 <strong>메모리</strong>를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다.</p> +<p>그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다.</p> +<ol> +<li>불필요한 페이지를 <strong>선별</strong> 후 <strong>스왑 아웃</strong> 한다.</li> +<li>프로세스에게 적절한 <strong>프레임</strong>을 할당한다.</li> +</ol> +<p>각각 <strong>페이지 교체 알고리즘</strong>, <strong>프레임 할당</strong>이라고 부릅니다.</p> +<p>또한, 이러한 작업은 <strong>요구 페이징(demand paging)</strong> 이라는 작업을 더 효율적으로 할 수 있게 돕습니다.</p> +<p>이 글은 요구 페이징에 대해서 알아보고, 요구 페이징이 안정적으로 작동하기 위해 필연적인 페이지 교체 알고리즘과, 프레임 할당을 설명합니다.</p> +<br> +<br> +<h2 id="요구-페이징demand-paging" style="position:relative;"><a href="#%EC%9A%94%EA%B5%AC-%ED%8E%98%EC%9D%B4%EC%A7%95demand-paging" aria-label="요구 페이징demand paging permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>요구 페이징(demand paging)</h2> +<hr> +<p>프로세스를 메모리에 적재할 떄 처음부터 모든 페이지를 적재하지 않고 필요한 페이지만을 메모리에 적재하는 방식을 +<strong>요구 페이징</strong>이라고 부릅니다.</p> +<p>요구 페이징은 다음과 같은 플로우로 진행됩니다.</p> +<ol> +<li>CPU가 특정 페이지에 접근하는 명령어를 내린다.</li> +<li>페이지가 메모리에 존재하면 <strong>유효비트 1</strong>을 나타내며 해당 프레임에 접근한다.</li> +<li>존재 하지 않는다면 <strong>유효비트 0</strong>을 나타내며 <strong>페이지 폴트</strong>가 발생한다.</li> +<li><strong>페이지 폴트</strong>가 발생하면 해당 페이지를 메모리로 적재하고 유효비트를 1로 설정한다.</li> +<li>1번을 다시 시행한다.</li> +</ol> +<p>이러한 <strong>요구 페이징</strong>은 필요한 페이지만 그때그때 불러서 적재 후 사용한다는 의미를 나타냅니다.</p> +<p><strong>요구 페이징</strong>을 안정적으로 수행하기 위해서는 크게 두가지를 고려해야 합니다. +첫번째는, <strong>요구 페이징</strong>은 메모리 기준 <strong>Input</strong>작업 입니다. +그렇다면 반대로 <strong>Output</strong>작업도 필요하게 됩니다.</p> +<p>왜냐하면 메모리는 한정되고 상대적으로 덜 필요한 페이지를 <strong>스왑아웃</strong>하는 작업도 필요하기 때문입니다.</p> +<p>이러한 방식을 <strong>페이지 교체</strong> 라고 부르며, 그중 여러가지 방식이 있기 때문에 <strong>페이지 교체 알고리즘</strong>으로 분류하고 명명합니다.</p> +<p>두번째는, 한정된 프레임을 잘 배분하는 것으로 <strong>스왑 아웃</strong>자체를 줄일 수 있기 때문에 <strong>프레임 할당</strong> 또한 +<strong>요구 페이징</strong>을 수행하기 위해 중요합니다.</p> +<br> +<br> +<h1 id="페이지-교체-알고리즘" style="position:relative;"><a href="#%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B5%90%EC%B2%B4-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98" aria-label="페이지 교체 알고리즘 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>페이지 교체 알고리즘</h1> +<hr> +<p>페이지 교체 알고리즘은 <strong>스왑 아웃</strong>할 페이지를 <strong>선별</strong>하는 알고리즘입니다. +그렇기 때문에 어떤 <strong>선별 기준</strong>에 따라 알고리즘을 나누게 됩니다.</p> +<p>일반적으로 <strong>기준</strong>은 <strong>페이지 폴트</strong> 발생 비율입니다. <strong>페이지 폴트</strong>는 보조기억장치로 부터 +정보를 가져와서 메모리로 할당하여 그 정보를 불러와야 하는 비효율적인 시퀀스를 가지고 있습니다. +이러한 <strong>페이지 폴트</strong> 발생 비율이 적은 교체 알고리즘을 좋다고 평가합니다.</p> +<p>그리고 <strong>페이지 폴트 횟수</strong>는 <strong>페이지 참조열</strong>을 통해서 진행합니다.</p> +<p>가령,</p> +<blockquote> +<p>2 2 2 3 5 5 5 3 3 7</p> +</blockquote> +<p>이라는 페이지 참조가 발생한다면 <strong>페이지 참조열</strong>은 여기서 연속된 중복을 제거한 순서입니다.</p> +<blockquote> +<p>2 3 5 3 7</p> +</blockquote> +<p>이 해당 순서에 <strong>페이지 참조열</strong>이 됩니다. 이렇게 중복을 제거하는 이유는 연속된 참조는 <strong>페이지 폴트</strong>대상이 +아니기 때문입니다.</p> +<br> +<br> +<h2 id="FIFO-페이지-교체-알고리즘" style="position:relative;"><a href="#FIFO-%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B5%90%EC%B2%B4-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98" aria-label="FIFO 페이지 교체 알고리즘 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>FIFO 페이지 교체 알고리즘</h2> +<p>FIFO 페이지 교체 알고리즘은 이름 그대로 먼저 들어온 페이지를 먼저 내보내는 방식입니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/29ef14f38fb55bcc0e52a63993968d2d/e4e90/fifo.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 45.294117647058826%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABI0lEQVR42o1R7ZKEIAzz/Z9TzxVE5UNFUXsJOzh37v04Z0IR2jQpVUpJlmWReZ5lXde837ZNeP4fHMdx4zxPqfZ9F2utTNMkIQRxzkmM8V2ApISkOxIPQtYXZEIu13VllI45EYjBS0Sj6KxES0yysxlySEAnrC8gR8ViqiKo1Huf7TtEZ4x4rcR1nQTT5+iQE3DPPI6niCnICjk72qTtvu9lGIZ3HMe8zxEw2DNHay0j/unmg5BLeQgqVErlgg5qGAkDckLhjI3ats2RNfx+EbIL7dLmT0IDu0Rd19I0zY329ZIe91TOOX4Qlseg9fIgjBFj0FBiocSheMQs1VeDvZEZj5NA9rR7Ez7BL8HOBIUBs9JQ5cdBAuY3qE4MyK/z+JPwG8PVumA0KKw1AAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/29ef14f38fb55bcc0e52a63993968d2d/ca1dc/fifo.png' srcset='/static/29ef14f38fb55bcc0e52a63993968d2d/e7570/fifo.png 170w, +/static/29ef14f38fb55bcc0e52a63993968d2d/f46e7/fifo.png 340w, +/static/29ef14f38fb55bcc0e52a63993968d2d/ca1dc/fifo.png 680w, +/static/29ef14f38fb55bcc0e52a63993968d2d/e4e90/fifo.png 769w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>해당 그림을 통해 설명하면 2,3,1 번의 순서대로 프레임에 쌓이게 되며 마지막 1번 페이지가 적재 된 이후에는 +프레임이 가득차게 됩니다. 이후 3번은 이미 적재된 페이지이기 때문에 넘어갑니다.</p> +<p>5번 페이지가 적재 되는 시점에 프레임은 가득 차있고, 5번페이지는 적재 되어있지 않기 때문에 <strong>선별</strong>후 <strong>교체</strong>하는 +작업이 필요합니다.</p> +<p>여기서 <strong>FIFO</strong>방식은 가장 먼저들어온 페이지를 내보낸다라고 설명드린것처럼 처음들어온 <strong>2페이지</strong> <strong>스왑아웃</strong> 시키게 됩니다. +빈 공간에 필요한 <strong>5페이지</strong>를 넣게 됩니다.</p> +<p>이렇게 먼저 들어온 페이지를 먼저 내보내는것을 <strong>FIFO 교체 알고리즘</strong>이라고 명명합니다.</p> +<p>하지만 이러한 방식에는 큰 단점이 있는데, 먼저 들어온 페이지가 실행 내내 사용 될 수도 있습니다. +즉, 먼저 들어왔다고 해서 교체에 대상이 되기는 합당한 이유가 아니기 때문입니다.</p> +<br> +<br> +<h2 id="2차-기회-페이지-교체-알고리즘" style="position:relative;"><a href="#2%EC%B0%A8-%EA%B8%B0%ED%9A%8C-%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B5%90%EC%B2%B4-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98" aria-label="2차 기회 페이지 교체 알고리즘 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>2차 기회 페이지 교체 알고리즘</h2> +<hr> +<p>해당 알고리즘은 <strong>FIFO</strong>방식을 개선한 알고리즘 입니다. 이름 처럼 한번의 기회를 더 주는 방식입니다. +두가지 케이스가 있습니다. 기본적으로 가장 오래된 페이지를 <strong>스왑 아웃</strong>한다는 방식은 같습니다. +만약 <strong>스왑 아웃</strong> 시점이 오게 되면, 해당 <strong>참조 비트</strong>를 확인합니다.</p> +<p>CPU에 의해서 <strong>참조</strong> 된적이 있다면, 해당 <strong>참조 비트</strong>를 0으로 바꾸고 적재 시간을 현재로 변경하며, +<strong>참조 비트</strong>가 0이라면 오래되면서 참조된적도 없기 떄문에 바로 <strong>스왑 아웃</strong> 시켜버립니다.</p> +<br> +<br> +<h2 id="최적-페이지-교체-알고리즘" style="position:relative;"><a href="#%EC%B5%9C%EC%A0%81-%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B5%90%EC%B2%B4-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98" aria-label="최적 페이지 교체 알고리즘 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>최적 페이지 교체 알고리즘</h2> +<hr> +<p><strong>최적 페이지 교체</strong> 방식은 이름그대로 최적의 방안을 찾는 알고리즘입니다. +미래를 통해 오랫동안 사용되지 않을 페이지를 <strong>스왑아웃</strong> 시키면서 문제를 해결합니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 675px; '> + <a class='gatsby-resp-image-link' href='/static/301d9be2aae117d26c7046bbc86abec7/a0bb6/optimal_page_replace.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 49.411764705882355%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABR0lEQVR42pVSa5ODIAzs//+R7fX6wHdVRETRvSxtnN5cvxwzSyDAZhNyWNcV3nsMw4BxHOGcwzRNWJbl39i2DQcSkqzrOlhr0fd9CrBfnGcECTCLfUcI4dc6xvgk5ERwkJzqSEhQ7SCq7fcZTgLSN4UZriphzR2TkPE+QTEkT4RUV9d1soymCnXtWQaSvR770QlGIQ9prwopKBHqYx62bYumafB4PJJ9x+77cEZ1KWWmyg1rR1Ie5nmOoiiQZVlCLijEp/vMmH1vZE0wE46kUGtAJ1MvyxJVVaFUlFV6TD8D0ZKEgdX3h5AK1bKWyUr6naTXiur75YL+5bcCc72iEaKe5wJmCf1lHbpWG6UE5nLF+XRClWdY5/C8KB9Qi+Kv4xHmdoOXttN3e9t8wrpEuL7DIIrmyWONz+bd2F7y85atJDa+PoSEP3U2BZX7WGPBAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/301d9be2aae117d26c7046bbc86abec7/a0bb6/optimal_page_replace.png' srcset='/static/301d9be2aae117d26c7046bbc86abec7/e7570/optimal_page_replace.png 170w, +/static/301d9be2aae117d26c7046bbc86abec7/f46e7/optimal_page_replace.png 340w, +/static/301d9be2aae117d26c7046bbc86abec7/a0bb6/optimal_page_replace.png 675w' sizes='(max-width: 675px) 100vw, 675px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>해당 그림을 통해 설명하면 5번 페이지를 요청할때 페이지 폴트가 발생하고 그 과정에서 이후 미래를 고려해서 +1번이 사용되지 않는다고 판단해 1번을 <strong>스왑 아웃</strong>하는 방식입니다.</p> +<p>해당 알고리즘은 <strong>페이지 폴트</strong>가 가장 낮습니다. +그렇지만, 현실적인 구현이 어렵습니다. 미래를 예측하는건 어려운 작업입니다. 그렇기 떄문에 현실적으로 가능한 +알고리즘으로 여기기 보단, <strong>페이지 폴트</strong>가 가장 낮다는 점을 고려하여 상대적인 <strong>성능 평가</strong>를 목적으로 사용합니다.</p> +<p>다른 <strong>교체 알고리즘</strong>의 하한선으로 잡고 비교대상으로 쓰여집니다.</p> +<br> +<br> +<h2 id="LRU-페이지-교체-알고리즘-Least-Recently-Used-Page-Algorithm" style="position:relative;"><a href="#LRU-%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B5%90%EC%B2%B4-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Least-Recently-Used-Page-Algorithm" aria-label="LRU 페이지 교체 알고리즘 Least Recently Used Page Algorithm permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>LRU 페이지 교체 알고리즘 (Least Recently Used Page Algorithm)</h2> +<hr> +<p>해당 알고리즘은 <strong>최적 페이지 교체 알고리즘</strong>을 변형해 <strong>미래</strong>를 예측하는것이 아닌, <strong>과거</strong>를 통해 +사용되지 않은 페이지를 <strong>스왑아웃</strong>하는 방식을 차용합니다.</p> +<p>'최근에 사용되지 않은 페이지는 앞으로도 사용되지 않을 것이다' 라는 점을 토대로 구성됩니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 602px; '> + <a class='gatsby-resp-image-link' href='/static/30d962ff19a1f7bd3cf761b3491c6861/d1b94/lru.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 40.588235294117645%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABMElEQVR42n2R63aDIBCE+/4vmaRqAoiK4v2S6QyJaX+Vc8Ydl/XbBb+ezyfOdRwH1nVN2qhFGkdMdZU0x4idNbN8T7/v2LYtaVkWiPUlSGRh13Xo+x4jAcMwYJ5n9IyxbdE7i2gNRvqJTQb6gfUTa6ZpetXyW7ESUIkz2fIjwc8myTMvdV1M++HdPISQ3uW10oQy6iKAYlmWSdbajxylnOOkzjnciwKe7wXjuS9YAuqh8wsmee9RVVWKSfQloySIcsa+wPbdqGJOJ/3coY6l0QVUoYBnYahrPPIcWZYhp5QX+Hq5wBNYs7by5S/wHPWvtDbC7b1Afr3CFTmGpoY3Dxges2OTltBH9o38dkOjCfnH/wWuuk9jUHLi0DSInMQQbDhtIKxnzvJOtd/RH/uWgD9AdmYhicbexgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/30d962ff19a1f7bd3cf761b3491c6861/d1b94/lru.png' srcset='/static/30d962ff19a1f7bd3cf761b3491c6861/e7570/lru.png 170w, +/static/30d962ff19a1f7bd3cf761b3491c6861/f46e7/lru.png 340w, +/static/30d962ff19a1f7bd3cf761b3491c6861/d1b94/lru.png 602w' sizes='(max-width: 602px) 100vw, 602px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>페이지마다 마지막으로 사용한 시간을 토대로 최근에 가장 사용이 적었던 페이지를 교체합니다. +해당 그림에서는 5번 페이지가 적재될 시기에 가장 오래 사용되지 않는 <strong>2</strong>를 <strong>스왑아웃</strong> 시키는것을 +알 수 있습니다.</p> +<br> +<br> +<h2 id="스래싱과-프레임-할당" style="position:relative;"><a href="#%EC%8A%A4%EB%9E%98%EC%8B%B1%EA%B3%BC-%ED%94%84%EB%A0%88%EC%9E%84-%ED%95%A0%EB%8B%B9" aria-label="스래싱과 프레임 할당 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>스래싱과 프레임 할당</h2> +<hr> +<p>요구 페이징을 잘 수행하기 위해 <strong>페이지 폴트</strong>를 줄이는 방식을 이야기 했습니다. +이러한 <strong>페이지 폴트</strong>를 줄이기 위해 <strong>교체 알고리즘</strong>을 적절하게 선택하는것이 중요하단것을 알게 되었습니다.</p> +<p>하지만, <strong>페이지 폴트</strong>를 발생시키는 이유에는 <strong>프레임 수의 한정</strong>이라는 문제가 있습니다. +프레임이 무지막지 하게 많다면 모든 프로세스를 할당할 수 있을것이고, 그렇게 되면 <strong>스왑 아웃</strong>이 발생할 이유도 없을것입니다.</p> +<p>그렇기 때문에 <strong>페이지 폴트</strong>의 발생을 줄이기 위해 적절하게 <strong>프레임을 할당</strong>하는 것또한, 중요합니다.</p> +<p>역으로 자원을 효율적으로 사용하고, 가상메모리와 같은 기법을 사용하면서 <strong>페이징에 프로세스 실제 실행시간보다 +더큰 리소스를 사용</strong>하는 문제가 생길 수도 있습니다.</p> +<p>이렇게 배보다 배꼽이 큰 상황, 플어서 이야기하면</p> +<blockquote> +<p>페이징 시간이 프로세스 실제 실행보다 더 길어지는 상황</p> +</blockquote> +<p>을 <strong>스레싱</strong>이라고 부르게 됩니다.</p> +<br> +<h3 id="멀티-프로그래밍-정도" style="position:relative;"><a href="#%EB%A9%80%ED%8B%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%A0%95%EB%8F%84" aria-label="멀티 프로그래밍 정도 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>멀티 프로그래밍 정도</h3> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 421px; '> + <a class='gatsby-resp-image-link' href='/static/f59eafb1bc2ccf73f4950479b865984a/edfbf/degree_of_multiprogramming.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 58.235294117647065%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABcklEQVR42qVTa3OCMBDk//88x2k/aJEEBRMCKg74GrnuRpKWavulzCy5ZPYue48k9/tdiP98wzBEJAzWNI1cLhc5n88Rp9PJI9ivzoI9CcifUkrW67VsNhvJ81y01n7l/ieKovAIe/pOAlIyCc6531HX4pCFtdZfXJZlBPff004Oh4NXRMeqqh6Ao195BthtKRWczXYrCtzZbCbz+dxnQTGTgMYYSdN0GhCKLM5NrsWuVmLhaKHEaiXOmofqkUv/Scr7/V6yLAMpqANJZWIyBCqLh1pexkuwt1BYudpzWYKngNfr1afsUzMgQK13CimPjtUIqg0l4Tnx1OUC9XGoj0NKNYj1bic1GzE2Jdh+RWdrbzf+jAonNeQmWy4le39DkTEuqJVCCag6jEccKaw6/ZAcfD2O12KxkNvtFoMmA4zueJS2baXliq7TZrAlHDlnKzSGYHpHcpBB4LMHLNtXwGF4+Zx4a9d18VX0fR+V/PX0PgEOupHcEV995QAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/f59eafb1bc2ccf73f4950479b865984a/edfbf/degree_of_multiprogramming.png' srcset='/static/f59eafb1bc2ccf73f4950479b865984a/e7570/degree_of_multiprogramming.png 170w, +/static/f59eafb1bc2ccf73f4950479b865984a/f46e7/degree_of_multiprogramming.png 340w, +/static/f59eafb1bc2ccf73f4950479b865984a/edfbf/degree_of_multiprogramming.png 421w' sizes='(max-width: 421px) 100vw, 421px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>해당 그래프는 세로축 <strong>CPU 이용률</strong>, 가로축 <strong>메모리에 올라와 있는 프로세스 수</strong>를 나타냅니다. +그래프에서 알 수 있듯이 프로세스수가 증가하면, CPU이용률 또한 증가합니다 하지만 일정 가로축을 넘어가면 +<strong>CPU</strong>이용률이 줄어드는 것을 알게 됩니다.</p> +<p>즉, 프로세스가 너무 많이 발생하면 각 프로세스에 할당된 <strong>프레임</strong>이 부족하고 그런 문제로 인해 <strong>페이지 폴트</strong>가 +자주 발생하게 됩니다.</p> +<p>CPU를 아무리 좋은것을 사용해도 메모리 공간이 부족하면 컴퓨터 성능이 안좋아지는 이유가 이런이유입니다.</p> +<br> +<br> +<h1 id="프레임-할당" style="position:relative;"><a href="#%ED%94%84%EB%A0%88%EC%9E%84-%ED%95%A0%EB%8B%B9" aria-label="프레임 할당 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프레임 할당</h1> +<hr> +<p>스래싱의 근본적 이유는 각 프로세스가 필요로 하는 <strong>프레임</strong>이 부족하기 때문입니다. 그렇기 떄문에 +운영체제는 <strong>프레임</strong>을 적절하게 할당할 수 있어야 합니다.</p> +<p>이러한 <strong>프레임 할당</strong>을 크게 두가지로 나눌수 있습니다.</p> +<ol> +<li>정적 할당 방식</li> +<li>동적 할당 방식</li> +</ol> +<br> +<br> +<h2 id="정적-할당-방식" style="position:relative;"><a href="#%EC%A0%95%EC%A0%81-%ED%95%A0%EB%8B%B9-%EB%B0%A9%EC%8B%9D" aria-label="정적 할당 방식 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>정적 할당 방식</h2> +<hr> +<p>정적할당방식은 두가지로 나누어집니다.</p> +<ol> +<li><strong>균등할당</strong></li> +<li><strong>비례할당</strong></li> +</ol> +<br> +<h3 id="균등할당" style="position:relative;"><a href="#%EA%B7%A0%EB%93%B1%ED%95%A0%EB%8B%B9" aria-label="균등할당 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>균등할당</h3> +<p>균등할당은 이름에서 알 수 있듯이 모든 프로세스에 프레임을 균등하게 할당하는 방식입니다. +프로세스가 3개가 있고, 프레임이 300개가 있다면 각 프로세스는 100개의 프레임을 할당받게 됩니다.</p> +<p>이러한 방식은 프로세스 크기도 각자 다른 상황에서 합리적이지 못한 선택입니다.</p> +<br> +<h3 id="비례할당" style="position:relative;"><a href="#%EB%B9%84%EB%A1%80%ED%95%A0%EB%8B%B9" aria-label="비례할당 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>비례할당</h3> +<p>크기가 큰 프로세스에 더 많은 프레임을 할당하는 방식을 비례할당이라고 부릅니다. +하지만 이러한 방식은 <strong>정적</strong>이라는 한계점을 가지고 있습니다.</p> +<p>실제 프로세스를 실행해보면 크기와 상관없이 더 많은 프레임을 필요로 하거나 그렇지 않은 프로세스들이 존재합니다. +이러한 문제 떄문에 비례할당도 합리적이라고 할 수 없습니다.</p> +<br> +<h2 id="동적-할당-방식" style="position:relative;"><a href="#%EB%8F%99%EC%A0%81-%ED%95%A0%EB%8B%B9-%EB%B0%A9%EC%8B%9D" aria-label="동적 할당 방식 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>동적 할당 방식</h2> +<hr> +<p>동적할당방식에는 크게 두가지로 나누어집니다.</p> +<ol> +<li>작업 직합 모델(working set model)</li> +<li>페이지 폴트 빈도(PFF: page fault frequency)</li> +</ol> +<br> +<h3 id="작업-집합-모델" style="position:relative;"><a href="#%EC%9E%91%EC%97%85-%EC%A7%91%ED%95%A9-%EB%AA%A8%EB%8D%B8" aria-label="작업 집합 모델 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>작업 집합 모델</h3> +<p>작업 집합 모델에서는 '프로세스가 일정 기간 동안 참조한 페이지 집합'을 기억하며 빈번한 페이지 교체를 방지합니다. +예를 들어 프로세스가 3초동안 20개의 페이지를 집중적으로 참조했다면 20개의 프레임을 할당하면 효율적일 것입니다.</p> +<p>이렇게 실행 중인 프로세스가 일정 시간 동안 참조한 페이지의 집합을 <strong>작업 집합</strong>이라고 합니다.</p> +<br> +<br> +<h3 id="페이지-폴트-빈도" style="position:relative;"><a href="#%ED%8E%98%EC%9D%B4%EC%A7%80-%ED%8F%B4%ED%8A%B8-%EB%B9%88%EB%8F%84" aria-label="페이지 폴트 빈도 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>페이지 폴트 빈도</h3> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/9243f5b6a6547b47c32fda8835dcb7b0/a6c2c/page_fault.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 37.64705882352941%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABF0lEQVR42nVRV67DMAzr/Y+Z9xFkOXbqEU89ShlIC9QAYYm2qPVqrdET+74LYow32L/ea62Cy/6Of+WcqZQijnOOxnGkZVloXVdSSok9TxPxuQT4PO8PQe89OfsmrVdi8V+HxbTWgnmeJeEwDHfMLTiCLGjLrooqHmtK8HfhCtspHhxgIOKR/IClzWgq3GEIlMCJ4F/XQZ4ogbRaiVDDJ0YtQE6SiAMXtK4Avu22EReTkUgSnnN+TdNIGKKAg/f3BhjKwYvfIHq8ZanQQcigG6kQ7edTLMEXQQuDN5kQEGOijGD2AxZkIc7zDd4Jp80mM+RFGWNoQqU8w/acIRMBiwlomdH3PXUYA9/+5CMqCD58LOA631v+B44qcERcXaXOAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/9243f5b6a6547b47c32fda8835dcb7b0/ca1dc/page_fault.png' srcset='/static/9243f5b6a6547b47c32fda8835dcb7b0/e7570/page_fault.png 170w, +/static/9243f5b6a6547b47c32fda8835dcb7b0/f46e7/page_fault.png 340w, +/static/9243f5b6a6547b47c32fda8835dcb7b0/ca1dc/page_fault.png 680w, +/static/9243f5b6a6547b47c32fda8835dcb7b0/a6c2c/page_fault.png 822w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>페이지 폴트 빈도 방식은 해당 그래프를 통해 이루어 집니다. +가로축은 할당된 프레임을 나타내며 세로축은 페이지 폴트율을 나타냅니다. +할당된 프레임은 적으면 페이지 폴트가 많이 발생하는 형상이 됩니다.</p> +<p>이러한 그래프에서 상한과 하한을 정한다음 해당 적정 구간에 들어올 수 있도록 프레임을 할당해주는 +방식을 <strong>페이지 폴트 빈도</strong>방식이라고 합니다.</p> +<h2 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h2> +<hr> +<p><a href="https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard">이미지 출처</a></p><![CDATA[페이징]]>https://catch-npe.netlify.app/jc22/https://catch-npe.netlify.app/jc22/Thu, 25 Sep 2025 00:00:00 GMT<h3 id="연속-할당의-문제점" style="position:relative;"><a href="#%EC%97%B0%EC%86%8D-%ED%95%A0%EB%8B%B9%EC%9D%98-%EB%AC%B8%EC%A0%9C%EC%A0%90" aria-label="연속 할당의 문제점 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>연속 할당의 문제점</h3> +<hr> +<p>연속적 할당의 대표적인 문제점은 <strong>외부 단편화</strong>가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해 +필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다.</p> +<p>이러한 문제를 해결하기 위해서는 <strong>불연속 할당</strong> 방식 중 대표적인 <strong>페이징</strong>기법을 사용할 수 있습니다.</p> +<br> +<br> +<h2 id="페이징이란" style="position:relative;"><a href="#%ED%8E%98%EC%9D%B4%EC%A7%95%EC%9D%B4%EB%9E%80" aria-label="페이징이란 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>페이징이란?</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 179px; '> + <a class='gatsby-resp-image-link' href='/static/3303d08d2825cfb6aa4e32e001ed03d3/a0b6e/paging.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 222.3529411764706%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,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'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/3303d08d2825cfb6aa4e32e001ed03d3/a0b6e/paging.png' srcset='/static/3303d08d2825cfb6aa4e32e001ed03d3/e7570/paging.png 170w, +/static/3303d08d2825cfb6aa4e32e001ed03d3/a0b6e/paging.png 179w' sizes='(max-width: 179px) 100vw, 179px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>페이징 기법은 프로세스를 일정한 단위로 자릅니다. 또한 프로세스가 들어갈 메모리 공간 또한 일정한 단위로 자릅니다.</p> +<p>여기서 프로세스를 일정한 단위로 자르면 일정한 <strong>논리 주소 공간</strong>이 생기는데 이것을 <strong>페이지</strong>라고 부르며, +일정한 단위로 잘린 메모리 <strong>물리 주소 공간</strong>은 <strong>프레임</strong>이라고 부르게 됩니다.</p> +<p>여기서 <strong>프레임</strong>, <strong>페이지</strong>의 일정한 단위는 동일한 크기로 자르게 됩니다.</p> +<p>이렇게 만들어진 <strong>페이지</strong>를 <strong>프레임</strong>에 할당하는 가상 메모리 관리 기법을 <strong>페이징</strong>기법이라고 부르게 됩니다.</p> +<p>이렇게 일정한 크기를 정하고 불연속 할당을 수행하면 외부 단편화 문제를 줄일 수 있습니다.</p> +<br> +<h3 id="페이징에서-스와핑" style="position:relative;"><a href="#%ED%8E%98%EC%9D%B4%EC%A7%95%EC%97%90%EC%84%9C-%EC%8A%A4%EC%99%80%ED%95%91" aria-label="페이징에서 스와핑 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>페이징에서 스와핑</h3> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 632px; '> + <a class='gatsby-resp-image-link' href='/static/5c44828843de79269526a85c37191d0c/afa26/paging_swaping.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 43.529411764705884%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABjklEQVR42nVSa2+CQBD0//+Wfqs1rbFN2tT4FijyqK/atFZ8IAJ6KgjT3ROM/dBJJncsMDuzd4UkTXE8HrHf75EkKTFBejoh5ZXeMa9rOfL6NbhWELsd1q6L5WKBbRggimP58kQfR8Q4OYsyWGC73crmh8MBQgi5hmEo64zC0urhu1WHo7SxMN7gD9/hN6v4fFPRb9YxVrpwdBVBqwrhrhDQjyzE3JGZXMzzvLNDvdXCU/EWr+V7dBt1uD0V/vMDlraBBTVziHNqtn4sQSzniDh6mvxxzXt2LQWHoxE0XYdp2zAtG3uKkEeOibzybBkxjYOdMTabDWaz2eWZ3UrB4GOIudbB2qS4Axv+ZAxPbWPATShu3+hh0tPhc+S1Kx0mRN/3EQSBFGZcHNrdDl5KRdQqZWhZ5FXlDiMSkTQNfGkKvOINhPMDQTeCXTmOg+l0CpcONIoiOUcpaFgWao0m2oqCjqpCUKf8CmQbyTSrsROOx4fAvD51KZjICDFORJ6RHDLPLbuDklnt0uQfsOAvZLeqvuikWrsAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/5c44828843de79269526a85c37191d0c/afa26/paging_swaping.png' srcset='/static/5c44828843de79269526a85c37191d0c/e7570/paging_swaping.png 170w, +/static/5c44828843de79269526a85c37191d0c/f46e7/paging_swaping.png 340w, +/static/5c44828843de79269526a85c37191d0c/afa26/paging_swaping.png 632w' sizes='(max-width: 632px) 100vw, 632px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>페이징에서도 이전과 마찬가지로 <strong>스와핑</strong>이 사용됩니다. 차이가 있다면 기존 연속 할당 방식 스와핑은 +프로세스 전체가 스왑영역으로 넘어가지만, <strong>페이징 스와핑</strong>은 사용하지 않는 특정 <strong>페이지</strong>만 스왑아웃 +시킬 수 있습니다.</p> +<p>이러한 방식은 이후 <strong>가상메모리</strong> 방식을 사용하는데 핵심이 됩니다.</p> +<br> +<h2 id="페이지-테이블" style="position:relative;"><a href="#%ED%8E%98%EC%9D%B4%EC%A7%80-%ED%85%8C%EC%9D%B4%EB%B8%94" aria-label="페이지 테이블 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>페이지 테이블</h2> +<hr> +<p>불연속 할당 방식에는 실행순서에 대한 문제가 하나 있습니다. +연속적 할당 방식에서는 실행순서를 CPU에게 알려줄 필요가 없습니다. 왜냐하면 실제로 물리 메모리에 연속적으로 +프로세스에 대한 정보가 있기 때문에 순서대로 실행시키면 되기 때문입니다.</p> +<p>하지만, <strong>불연속 할당</strong>은 상황이 다릅니다. 메모리상 프로세스에 대한 정보가 연속적이지 않기 떄문에 +이를 실행시키는 <strong>CPU</strong>입장에서는 어떤 프로세스를 실행시켜야 할지 알기 어렵습니다.</p> +<br> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 435px; '> + <a class='gatsby-resp-image-link' href='/static/cd81bdcfe0a54668cfce7274055adb2a/faa12/page_table.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 68.23529411764706%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAABw0lEQVR42o2UDW/aMBCG+f9/q9JE0TqtVCQbyggJHyVAPmzyASTh3b1enQZopyKdzr74Hr93thlcLhfQ2raFHX9k/N5fczu3NrAD+/sM5vs+PM/DZDIxxnEYhnc5A5uw3W6x2+1wPp/vgE3TwHEcAxoOhxiNRnBd10DvgAzkeY4gCLBcLg34dhGBWmvjW5oIsLH9fo/FYoE0TU3ewAZWqxVms5kpY71eo67rDszkNFMoqwpFWRpfHY9QSouYA6IowuFw+AekIgYIYglUSbUsvQOKokw2rpRAs0x8hqNWUHFsVJJBb4BFUchOCpkspFpKp10rFODURTr+geDbA16/P6JwXxAzJrmbzeYaWEkJlJwkiflA+Ol0ulKoJTkbP2ExfEBEoPOMhLFbhTwQAqiKp0woPTexQB6CnvvIfjt4FZV75wXlnyli34MSIVzf9ZBKqJJg+lKazt1Ycv8eavl+PNeo20asxUl6nLA9IoAls20G2L/1fbu6NjJX8xlyURVNxoh/OSjnHtLAh3oruVP4v+fWV1iEPvKpg5X0b/PzCYX0T4fzDtj18CtAA2U/xdgiU4VM2vcXe/+Wv2rN20u5/ZOwsb96sTdnQ5UbwgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/cd81bdcfe0a54668cfce7274055adb2a/faa12/page_table.png' srcset='/static/cd81bdcfe0a54668cfce7274055adb2a/e7570/page_table.png 170w, +/static/cd81bdcfe0a54668cfce7274055adb2a/f46e7/page_table.png 340w, +/static/cd81bdcfe0a54668cfce7274055adb2a/faa12/page_table.png 435w' sizes='(max-width: 435px) 100vw, 435px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>이를 해결하기 위해서 <strong>페이지 테이블</strong>이란것을 사용합니다.</p> +<p><strong>페이지 테이블</strong>은 <strong>페이지 번호</strong>, <strong>프레임 번호</strong>를 짝지어 줍니다. 그렇게 되면 <strong>CPU</strong>입장에서는 +<strong>페이지 번호</strong>만 알고있다면 <strong>페이지 테이블</strong>을 통해 <strong>프레임</strong>으로 접근이 가능하기 때문입니다.</p> +<p>페이지 테이블은 프로세스마다 각자의 페이지 테이블을 가지게 됩니다.</p> +<br> +<br> +<h2 id="페이지-테이블-베이스-레지스터PTBR" style="position:relative;"><a href="#%ED%8E%98%EC%9D%B4%EC%A7%80-%ED%85%8C%EC%9D%B4%EB%B8%94-%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EB%A0%88%EC%A7%80%EC%8A%A4%ED%84%B0PTBR" aria-label="페이지 테이블 베이스 레지스터PTBR permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>페이지 테이블 베이스 레지스터(PTBR)</h2> +<hr> +<p>페이지 테이블은 프로세스마다 가지고 있고, 이는 <strong>메모리</strong>에 저장됩니다.</p> +<p>하지만, CPU 입장에서는 결국 <strong>페이지 테이블</strong>의 위치를 알아야 합니다. 이러한 기능을 수행하는게 +<strong>CPU</strong>내의 존재하는 <strong>PTBR</strong>입니다.</p> +<p><strong>PTBR</strong>은 <strong>CPU</strong>내에 존재하고 <strong>페이지 테이블</strong>의 위치를 기록합니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 273px; '> + <a class='gatsby-resp-image-link' href='/static/f28f87d93e2e40169da53297b8de9467/d00c8/ptbr.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 81.17647058823529%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB0ElEQVR42o1UaWvCQBD1//8L+0UoPagpaKFIqdDPVWk1MRoFifeZxHi/ztt2QwxqXRjdXXfeMTtu6nA44JrY7/dHa45T51LXAmoQjvV6jel0ijAMo72zgEklXHMsl0t4nodwtcJwPEatZqLX7yP42w+C4BiQiTo5Dqz3JgIykwgWCyy9BdYCFPo+fFlzbzgYqLOppB0y0ZIeK1E0nc1QK5XwmTPwXXiB81HE12sejeIb7PcCyrksunVLnVeAu90OC2HxhbHT6WA0GimLrBHtkMBpNpG5SePx7hb5ZwPGwz1y2SfkjSwy6TS+K5VfQH7EE7vdLvpSGwIOxAaJqHIkdk3LQkOAm46jvp1WC612G1bdhit5ESCTZ2Kr1+uhXC7DkQSCUa1WTtLtdotTgy4pSNVQtwGVmaYJS1RUq1UFatu2IqFCxmazObpAHSQai4MIkAfZV1Q1mUzgui5aYodg+papkLU+1/TMiwDJzgT+SDbdMiQgmQbUli8C6g0msFa6SfU83thxwDgwz9DhyT5MFjsOyFrTNoHjQRdRDS/9d5ms7ROMihm8+fl8ruZ0wjXnFx8HArWlx3jzvCReEOdUcs7Nv68NFeqgLapMPh7J5+sHK2vUioZUflIAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/f28f87d93e2e40169da53297b8de9467/d00c8/ptbr.png' srcset='/static/f28f87d93e2e40169da53297b8de9467/e7570/ptbr.png 170w, +/static/f28f87d93e2e40169da53297b8de9467/d00c8/ptbr.png 273w' sizes='(max-width: 273px) 100vw, 273px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>해당 그림처럼 특정 프로세스 작업을 수행하기 위해서 <strong>CPU</strong>는 해당 <strong>PTBR</strong>내부 프로세스의 페이지 테이블을 +조회합니다. 이후 메모리내부 해당 페이지 테이블 주소로 넘어가서 특정 프로세스의 페이지 까지 접근하게 됩니다.</p> +<br> +<br> +<h3 id="비효율적인-접근" style="position:relative;"><a href="#%EB%B9%84%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9D%B8-%EC%A0%91%EA%B7%BC" aria-label="비효율적인 접근 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>비효율적인 접근</h3> +<hr> +<p>이전 <strong>페이지 테이블</strong>을 참조하는데 한가지 문제가 있습니다.</p> +<p><strong>CPU</strong>는 <strong>페이지 테이블</strong>로 접근하고, 해당 값들을 통해 실제 <strong>페이지</strong>로 접근합니다.</p> +<p>즉, 하나의 조회에 대해 두가지 접근을 수행하게 됩니다. 이러한 방식은 비효율적입니다. +그렇기 때문에 <strong>캐싱</strong>기능을 통해 이를 해결하고 이러한 기능을 수행하는게 <strong>TLB</strong>입니다.</p> +<br> +<h2 id="TLBTranslation-Lookaside-Buffer" style="position:relative;"><a href="#TLBTranslation-Lookaside-Buffer" aria-label="TLBTranslation Lookaside Buffer permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>TLB(Translation Lookaside Buffer)</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 170px; '> + <a class='gatsby-resp-image-link' href='/static/9420bb58a1fe627be70a707949f07993/e7570/tlb.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 95.29411764705883%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAAByklEQVR42oWU2QoCMQxF/f9f0idRQVHBB9FxX3Af9xW3yAmkjGPVQOiS9vbepG3i+XzKL8f+rYl6wjqPx8Prx+NRLpeL3G43b/wroLGJ23A4lEKhIKPRyLGNmhcQ2+12EoahLJdL9e12q75arWQwGMh8Ppf1ei2bzUbnaFmHAszYOsBeryez2UwWi4UCs4k+881mU8cA0E6nUxfD3wDpYI1GQ5LJpNRqNalUKtLv9yWbzUo+n9dYOp2WVColxWJRqtWqzpfLZSXxwRAnV8g4HA5OLjLH47G0222XEuTDjhhgk8nELxkWSDEQDgAAuZlMRkEAxikQa4hZsd4AGbAhWkHr7/d7BfdV+Hw++xkaYPxeYaQANtFNFgMQVV7JnU5HmSCBynW7XQWiSLlcTueDIJB6va5xikYsfpgrCvniNdzvd21x5imGbbper24NAKTDm0OcS+t7LVxckxWPE/u4h7YICVwDqkyiOZm8kopSqeQuMmMYc0ir1dKxFxAAJFAEWqSeTic9gE30uac4MdYB6mX4S7KBfpOMMi8g7xRmvBD7ADgEFlQcRsbQPglUeQEx/jyTaqC20dyeJH1uBczZF/3G/v6H/yz+H74AzCW1kTlZCdEAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/9420bb58a1fe627be70a707949f07993/e7570/tlb.png' srcset='/static/9420bb58a1fe627be70a707949f07993/e7570/tlb.png 170w' sizes='(max-width: 170px) 100vw, 170px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p><strong>TLB</strong>는 CPU 곁에 존재하며 이는 페이지 테이블에 대한 <strong>캐시 메모리</strong>입니다. +참조 지역성에 근거해 주로 최근에 사용된 페이지 위주로 가져와서 저장합니다.</p> +<p>여타한 캐싱 기능과동일하게 리소스가 <strong>TLB</strong>를 통해서 나오게 되면, <strong>히트</strong>했다. 그것이 아니라면 +<strong>미스</strong>했다 라고 표현합니다.</p> +<br> +<br> +<h2 id="페이징에서의-주소-변환" style="position:relative;"><a href="#%ED%8E%98%EC%9D%B4%EC%A7%95%EC%97%90%EC%84%9C%EC%9D%98-%EC%A3%BC%EC%86%8C-%EB%B3%80%ED%99%98" aria-label="페이징에서의 주소 변환 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>페이징에서의 주소 변환</h2> +<hr> +<p><strong>특정 주소</strong>에 접근하기 위해서는 두가지 관점의 정보가 필요하게 됩니다.</p> +<ol> +<li>어떤 페이지 혹은 프레임에 접근하고 싶은지</li> +<li>접근하려는 주소가 그 페이지 혹은 프레임으로부터 얼마나 떨어져 있을지</li> +</ol> +<br> +<p>이중에서 1번은 기존 <strong>페이지 번호</strong>를 통해서 해결할 수 있습니다. +하지만, 2번의 말은 조금 애매하게 들리는데 이를 풀어서 설명하면, +하나의 <strong>주소</strong>내에서도 <strong>논리</strong> 혹은 <strong>물리</strong>주소에 따른 순차적인 주소가 있습니다.</p> +<p>n번지, n+1번지, n+2번지.... 처럼 세부적인 <strong>지점</strong>을 의미합니다.</p> +<p>1번 주소를 통해서 <strong>페이지</strong>혹은 <strong>프레임</strong>에 접근한다면 그 중 명확한 지점을 식별해야 하기 때문에</p> +<p>페이징 시스템에서는 <strong>페이지번호</strong>, <strong>변위</strong>를 이용합니다.</p> +<p>자세한 예시는 아래 그림을 통해서 하겠습니다.</p> +<br> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 560px; '> + <a class='gatsby-resp-image-link' href='/static/43ca59962cdfc65f5059944fb0b8f5f4/6d7b8/paging_address_trans.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 65.88235294117646%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAABYklEQVR42p3T6W7CQAwEYN7/HRHhvgn3DVt9lpxCW/400mo39ng8nk1az+ezeG63W7ler7GLZVzscrnE/hq/3+9N/LWm5eVwOJTlcll6vV4ZDAbx7jmdTmU0GkXc2u12UXQ8HstqtSqTyaTMZrNS13V5PB7fhJJIxuNx2Ww2Zb/fh4LFYhGxbrdbOp1ONFO03W6DXC2V5/O5ERGEChEpcAZGCGRpaMFQgtBE1Gvm3TRByAPJ9Xodyfl83ihEjIhKxXAIjZgjV1UVuF+EQMZCqCPliOWm02l4Rb1GmiM0UbvdflfIg5+ERkPIfGd5BHbxVDgcDkMhwsZDhkrq+hehuFiSJKFF4UdCAB7mBaWHRjUyD53FYWF4m59TQ2hkKnQxgrOkQr6kX8aFyVvOZmrgGw/zLwFwa7obNT9UuylgnPOWNUoPXR5MEOYvA5hFGfu0Uj1v+/1+iPG1vBH+Z2mO/DX2BRb66RT6aiknAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/43ca59962cdfc65f5059944fb0b8f5f4/6d7b8/paging_address_trans.png' srcset='/static/43ca59962cdfc65f5059944fb0b8f5f4/e7570/paging_address_trans.png 170w, +/static/43ca59962cdfc65f5059944fb0b8f5f4/f46e7/paging_address_trans.png 340w, +/static/43ca59962cdfc65f5059944fb0b8f5f4/6d7b8/paging_address_trans.png 560w' sizes='(max-width: 560px) 100vw, 560px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>페이지, 페이지 테이블, 프레임을 나타내는 그림입니다. 이러한 그림은 특정 페이지에 접근하기 위해 +페이지 테이블을 참조하고 프레임 번호를 얻어 실제 메모리 프레임에 접근하는 시퀀스 입니다.</p> +<p>만약 <strong>CPU</strong>가 5번페이지에 변위가 2인 곳에 접근하려고 하면 10번지로 접근하게 될것입니다.</p> +<ol> +<li>5번 페이지는 1번 프레임에 있다.</li> +<li>1번 프레임의 시작 번지수는 8번지이다</li> +<li>8번지에 변위 2를 더해서 최종주소는 10이 된다.</li> +</ol> +<p>여기서 주의 할점은, 논리주소의 변위를 최종 물리 주소상 프레임 번지에 더하였다는 것입니다.</p> +<blockquote> +<p>이말은, 논리주소의 변위 == 물리주소의 변위 입니다.</p> +</blockquote> +<p>이것이 가능한 이유는 처음 페이징 방식을 사용할때 페이지와 프레임 변환과정에서 <strong>특정 크기</strong>로 나누게 되고, +그 간격이 같기 때문에 논리주소의 변위랑 물리주소의 변위는 같다는 결론이 나옵니다.</p> +<br> +<br> +<h2 id="페이지-테이블-엔트리" style="position:relative;"><a href="#%ED%8E%98%EC%9D%B4%EC%A7%80-%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%97%94%ED%8A%B8%EB%A6%AC" aria-label="페이지 테이블 엔트리 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>페이지 테이블 엔트리</h2> +<hr> +<p>페이지 테이블 엔트리는 페이지 테이블 <strong>row</strong>를 지칭하는 단위입니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 391px; '> + <a class='gatsby-resp-image-link' href='/static/d1c392afc24e5144387a7f4a07671dae/7e80f/pte.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 73.52941176470587%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAABz0lEQVR42pWUV2/DMAyE/f9/VtGXpkUzUThxGmfYcaaz97jqI6AgDx2pAEEULZ7uSMrB9XrVb/NyudjKwB4MBprNZppMJsqyTPP5XH5wLvgJyAMw9vu9ptOpFouF6vW62u22Wq2WwjBUHMfmz/Nc5/NZAUEYfj2dTrYCwnp2e8AKhYIajYbNarWqZrNpvnK5rGKxqFKppOPxqAD6HBoOh3YIu9frqVKpKElSRc9P6tZDTfKZyUMqZ2GGzVku7Ha7RiJYrVa2wZkkiUnp9/sGPBqNFL+/KW19au5kLZdLm5ztdDo3qWAQczgcFOCMokjj8djAyFHH5ahWqylzBYhfX9SLGsqdkoVjCEuvBjAuxQcZY7herw0dJxWE7QhJDhQm2YcDbsfGkLOwIU1Iha1nSKwx9BVlUAQO3bcBAxWwIpi8EYwq2NE6XEzljaHvNV/l3W6ne5/bGDMu4tt2u7ULAPU2QKjke/BXUzMAA4A8w4pgcghrpOOH8beA/mXcA242GwOFETas0jQ15tgAsX+YIUmHBYUjj9i0jc8nRaIv/wVIMGz8O0Yq4MjmIoryJ6CvMu2AVCYyAYAlNpNUsL+1zSN/HN4pAUyqer8y+c7f5gvSHXrEKyc9tAAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/d1c392afc24e5144387a7f4a07671dae/7e80f/pte.png' srcset='/static/d1c392afc24e5144387a7f4a07671dae/e7570/pte.png 170w, +/static/d1c392afc24e5144387a7f4a07671dae/f46e7/pte.png 340w, +/static/d1c392afc24e5144387a7f4a07671dae/7e80f/pte.png 391w' sizes='(max-width: 391px) 100vw, 391px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>지금까지는 이러한 페이지 테이블에는 페이지 번호, 프레임 번호만 존재 한다고 설명했습니다. +하지만, 다른 중요한 정보들도 있습니다.</p> +<ol> +<li>유효 비트</li> +<li>보호 비트</li> +<li>참조 비트</li> +<li>수정 비트</li> +</ol> +<br> +<h3 id="유효-비트" style="position:relative;"><a href="#%EC%9C%A0%ED%9A%A8-%EB%B9%84%ED%8A%B8" aria-label="유효 비트 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>유효 비트</h3> +<p>유효비트는 해당 페이지에 접근 가능한지 여부를 알려줍니다. 대표적으로 접근 불가능 한 경우는 +<strong>스와핑</strong>으로 인한 해당 <strong>페이지</strong>가 <strong>스왑영역</strong>으로 들어간 경우입니다.</p> +<p>이러한 경 <strong>페이지 폴트</strong>라는 예외가 발생하며, 하드웨어 인터럽트 처럼 처리 됩니다.</p> +<ol> +<li>CPU는 기존 작업 내역을 백업합니다.</li> +<li>페이지 폴트 처리 루틴을 실행합니다.</li> +<li>페이지 처리 루틴은 원하는 페이지를 메모리로 가져온 뒤 유효 비트를 1로 변경해줍니다.</li> +<li>페이지 폴트를 처리했다면 이제 CPU는 해당 페이지에 접근할 수 있게 됩니다.</li> +</ol> +<br> +<h3 id="보호-비트" style="position:relative;"><a href="#%EB%B3%B4%ED%98%B8-%EB%B9%84%ED%8A%B8" aria-label="보호 비트 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>보호 비트</h3> +<p>보호비트는 페이지 보호 기능을 위해 존재합니다. 리눅스의 읽기 쓰기 권한을 생각하면 됩니다. +해당 페이지가 읽기 전용 페이지라면 보호비트는 0을 나타내고, 읽고 쓰기가 가능하다면 1을 나타냅니다.</p> +<br> +<h3 id="참조-비트" style="position:relative;"><a href="#%EC%B0%B8%EC%A1%B0-%EB%B9%84%ED%8A%B8" aria-label="참조 비트 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>참조 비트</h3> +<p><strong>CPU</strong>가 접근한적 있는지 여부를 나타냅니다. 참조된 비트라면 1을 나타내며, 그렇기 않다면 0으로 유지됩니다.</p> +<br> +<h3 id="수정-비트" style="position:relative;"><a href="#%EC%88%98%EC%A0%95-%EB%B9%84%ED%8A%B8" aria-label="수정 비트 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>수정 비트</h3> +<p>해당 페이지에 데이터를 쓴 적이 있는 여부를 나타냅니다. 수정 여부를 확인해야 하는 이유는 <strong>스와핑</strong> 떄문입니다. +만약 <strong>CPU</strong>가 페이지에 대한 내용을 수정했다면, 스와핑 과정에서 보조 기억장치에 있는 데이터 또한 수정해야 하기 때문입니다.</p> +<h2 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h2> +<hr> +<p><a href="https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard">이미지 출처</a></p><![CDATA[메모리 배치기법 그리고 단편화에 대해]]>https://catch-npe.netlify.app/jc21/https://catch-npe.netlify.app/jc21/Wed, 24 Sep 2025 00:00:00 GMT<h2 id="연속-메모리-할당" style="position:relative;"><a href="#%EC%97%B0%EC%86%8D-%EB%A9%94%EB%AA%A8%EB%A6%AC-%ED%95%A0%EB%8B%B9" aria-label="연속 메모리 할당 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>연속 메모리 할당</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 278px; '> + <a class='gatsby-resp-image-link' href='/static/a20e2cda3788d5213a275023d36effd1/75062/sequencial_memory.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 110.58823529411765%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAWCAYAAADAQbwGAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC+UlEQVR42oVVCVPaUBDu//8znQ7a1hFbq+IggYSc5CAHpwoSQiDI/XX3ATq1Am9mZzd5b7/st8fLl81mg9lshul0+o9kWSZkb+/1crkE+xySL6ClaRpkWUa1WoWu67AsC6qqCm0YBhRFEWckSUKr1WIXrNfrw4AmOdm1Gnzfh0LAuVwOd7e3+H5+jnw+D891Ufc8WKaJdrt9GtCggyYBOuxk27gvPkCqVFB8KOGBorIJ0HY96HTu6fn5NKClyKiVivCUMuxyCZGuItAURAbrKr2vwFdloZtRhPl8LkA/BdzQRt+tYekZWAU2xqaCWJWQaGVkNRUz18DcM7EObaG7UYhRmh6MUgDGoYdN6ACdEMHdL8jn32Dmf8K7uUJXuscrAaEdYEkffG41CXB8GJA3nmwTE6uKqUvaMYSwne2eM5JXzxL6sdnEMEmOA7YoVwO1jKGhoFeVMCTaLCNLFZLs7MSsoh2GGMTxccrD4J1yWPgN9SIH8/IH6kS5VbzBa916o9zw60hGo/+Ksn8WgAPfwZKc1pGLia2jT1FyNCkVJbM1zP2a2JtRLkPXeQPkqVmtVkLztLEWlLsWgchFxFqFwEoCaEQ5TXc0Y70i9IAqH3ouoqiBx25XTI5NfRtRKxUKBXQ6nXfKC4pwFbrkKOOF2oadUwKd0fsFUV1RSrgwUd3Dy2CANUXGs809yZEtFotthAyYNoK3HDYoZ9rFGeyrC3h/rtBTSlgQZbR9LOlMSFPDgPucfczltm0cc9vM1pZerMtEWxO0ucJDQ8aYcsm2b9do/HrH26ZHkzIm54mjC1DWDMAFylx925dUEH4XUQ5Pts0o8reUuxH8wjWks69iUpzrSzEps33b0Jl2GFCVT4xeErhYUFTcOjzLQ6r2iGizPdnNM+/NKNIGFaXX7x+nnPaekTYjDKk4STMUOo4CDEIfsbD9nQToPXYxnkyORLir1MeV0ZXPDp+to78AYfCXdsL9RTvoE60F33sf91lOAn4i3LCHbuVjEf4Fe4N1AT6l4KYAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/a20e2cda3788d5213a275023d36effd1/75062/sequencial_memory.png' srcset='/static/a20e2cda3788d5213a275023d36effd1/e7570/sequencial_memory.png 170w, +/static/a20e2cda3788d5213a275023d36effd1/75062/sequencial_memory.png 278w' sizes='(max-width: 278px) 100vw, 278px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p><strong>연속 메모리 할당</strong>이란 메모리에 프로세스가 그림처럼 <strong>연속적</strong>으로 배치되는 상황을 가정합니다.</p> +<p>프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다.</p> +<p>이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 <strong>스와핑</strong>과 관련이 있습니다.</p> +<br> +<h2 id="스와핑이란" style="position:relative;"><a href="#%EC%8A%A4%EC%99%80%ED%95%91%EC%9D%B4%EB%9E%80" aria-label="스와핑이란 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>스와핑이란?</h2> +<hr> +<p>메모리는 실행시킬 프로세스를 적재하게 됩니다. 하지만, 이런 프로세스들 중에 현재 실행되지 않는 프로세스는 처리해줘야 합니다. +메모리 리소스가 한정적이기 때문입니다.</p> +<p>여기서 말하는 실행되지 않는 프로세스의 예시는 <strong>I/O</strong>작업, 오랫동안 사용되지 않는 프로세스가 이에 해당합니다.</p> +<br> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/1b05958638432d57c6897ebda0560736/5e9f9/swaping.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 40.588235294117645%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABSElEQVR42m1S20rEMBDt//+Igg8KIog+LL74CYIKq+613bTpNdm0afc4JzaLoIFhksnMyTkzSU6nE7i89+Celuc5lFLBZ1kW9ofDAdYY/LciBn0yDAOOx2Mo7roOzjl0Ulg3LYqiCGC0VmL9nMuc6GnEoJ+mCQkvIjsGrLEo9zuYqkTf9yjLEtZajNbANg201ujaFo3saSRB4+METlhEoEjbyGV2cwm9uA8sMpHK2P76AunzE7ykjUIg1tAHIvLoH0AaQSYp4KURmTxXdX2WyDgXz2RFH8/ECj38DUj6o5PLWQYl0+s0RbpZYxzHkOcEgNKd+wGMjwXAKJerqSrsbq+gHu/QSsFmu0UtMSWS94sHeP4IKVbLN5Qf79CrJfw8lDNgnFaYsDCbJDYIA8pgbwjMs59/gDXS568l1q8vUKtPtDIctofsvwHgp2iFEhRwsAAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/1b05958638432d57c6897ebda0560736/ca1dc/swaping.png' srcset='/static/1b05958638432d57c6897ebda0560736/e7570/swaping.png 170w, +/static/1b05958638432d57c6897ebda0560736/f46e7/swaping.png 340w, +/static/1b05958638432d57c6897ebda0560736/ca1dc/swaping.png 680w, +/static/1b05958638432d57c6897ebda0560736/5e9f9/swaping.png 711w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>그렇다면 이러한 프로세스를 메모리에서 처리하는 방법이 필요한데 그 방법이 <strong>스와핑</strong> 입니다.</p> +<p><strong>스와핑</strong>은, 두가지 행위를 통해서 수행할 수 있습니다.</p> +<blockquote> +<p>스왑 아웃: 현재 실행되지 않는 프로세스가 메모리에서 스왑 영역으로 옮겨지는 것 (메모리 -> 스왑 영역)</p> +</blockquote> +<blockquote> +<p>스왑 인: 스왑영역에 있던 프로세스가 다시 메모리로 옮겨지는 것 (스왑 영역 -> 메모리)</p> +</blockquote> +<p>또한 메모리에서 보조기억장치로 옮겨질때 <strong>스왑영역</strong>으로 프로세스를 옮겨두는데 그 영역을 <strong>스왑 영역</strong>이라고 합니다.</p> +<br> +<br> +<h2 id="메모리-할당-방식" style="position:relative;"><a href="#%EB%A9%94%EB%AA%A8%EB%A6%AC-%ED%95%A0%EB%8B%B9-%EB%B0%A9%EC%8B%9D" aria-label="메모리 할당 방식 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>메모리 할당 방식</h2> +<hr> +<p>프로세스는 메모리 속 비어있는 공간에 적재되어야 합니다. 비어 있는 메모리 공간에 프로세스를 연속적으로 할당하기 위해 +<strong>세가지</strong> 방법을 고려할 수 있습니다.</p> +<ol> +<li><strong>최초 적합(first fit)</strong></li> +<li><strong>최적 적합(best fit)</strong></li> +<li><strong>최악 적합(worst fit)</strong></li> +</ol> +<p>각방식을 아래 예시를 통해 들어보려 합니다.</p> +<p>프로세스 A,B,C는 이미 적재되어있고, 빈 공간 A,B,C가 있습니다. 앞으로 적재할 프로세스는 20MB크기를 가지고 있으며 +적재 방식에 따라 이를 어디에 적재할지 달라지게 됩니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 472px; '> + <a class='gatsby-resp-image-link' href='/static/f3a316d4df3edc645b29b25e6ceb80e2/85788/memory_stacking.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 73.52941176470587%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAACT0lEQVR42pVUS2/TQBjMj6/ErfSGQEVISFRcuMCJGxc4IAhNSdomxXk6Xjt+v98eZpckTSrEY6Xx2tLu7Mw3n7dXeC7i8QghEY2vkXCO9SXKukbbtui6bo+iLJB4DkJTQBsN4RtrZK6DNI7QAWpNLxz0sTw9we3ZI0yfnGL1+ATO+7fQTQu+5+3J5PCDALl2h/ruBo02RjOdIL8dwtZXilAK6FVJjIKnOIOv0N+9QbqxkPse6uZYIR8ISNjocyTXV9A/f0JKMklqrZYQpok8z9Hr2kadHo0GMF4+Rau+uiOrO4We5yP9MUY5GaGkSomcJdpQYbuz3Da/COOb7xCvzlFBaUe3wwGh4zjIwgApHYT2BjkVF2EIS6orCjTk2hMmlG9enKNWArsjsh2h67pqU16WcEgq56btYFkWbNtGQdJ7QircvH6BZitdWqi4YVdHFYrvI17MkGgTRAwnnU8RTe9grmhZ7pGh7C2zNmsmLEhq0Lpx8RzrZ2fIljNUXCwMA2uiXmgILr9g8fEDoqs+yvEQxnzGUKxtKNISCZuqQu7aKFmb0iH4Hs811GmiTpeLXcdF4tjIiJKWJRJ2hcl+xC6Uh3V6OI5T9pQteYBqfM41Hcr6lbKeMpSj9jhMV4ILDsORGyVhkiQQwkCapqhJLISAyaRVKA/77U+QoUjCw9FsFf7W8t8g/5SATSxurzG7uoTNpAOmbjDlgP1Y/q9C2YdFFMJczDH61ocreDkwGEPXle37lP8RWZYiowo/jCDYzGEUI81yXho+oihCVVX4Ce97ettXwW9hAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/f3a316d4df3edc645b29b25e6ceb80e2/85788/memory_stacking.png' srcset='/static/f3a316d4df3edc645b29b25e6ceb80e2/e7570/memory_stacking.png 170w, +/static/f3a316d4df3edc645b29b25e6ceb80e2/f46e7/memory_stacking.png 340w, +/static/f3a316d4df3edc645b29b25e6ceb80e2/85788/memory_stacking.png 472w' sizes='(max-width: 472px) 100vw, 472px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<h2 id="최초-적합" style="position:relative;"><a href="#%EC%B5%9C%EC%B4%88-%EC%A0%81%ED%95%A9" aria-label="최초 적합 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>최초 적합</h2> +<hr> +<p>최초 적합은 메모리 내의 빈 공간을 순서대로 검색하다가 적재할 수 있는 공간을 발견하면 그 공간에 프로세스를 배치하는 방식입니다. +이전 그림에서 운영체제가 빈공간 A,B,C 순서대로 검색을 하였다면 가장 먼저 검색된 A 빈공간에 적재되는 방식입니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 252px; '> + <a class='gatsby-resp-image-link' href='/static/20767aa0ea46e42ca3e0795e165a5be6/f6ed8/first_fit.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 143.52941176470588%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAYAAACqhkzFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEAUlEQVR42oVWaW8bVRTtD64QiEJRUSUKFRL8BD4UiRZBl1AZ2iCCUBcpIAtI4sT2eOxZPON9du/r+HDuODZuMnEsXb3MW86799xz78uN5XKJi7b9u2r+4trablycWCwWmEwmGI9GydhqtZDNZpHP5zEcDDAZj1fGNdm7GzCO4QcBmkoBUTEPr3AKL5+DkzuCc3qCoHiGUNaUPGpcD8IwORPTUgFlwfMDBJoKmBXAMoCaCdSrq9HSaVqy5nGP43kS9zvhX/IwiKIEMDbKmOkq+oUcerRB8RSTioK5UUnWfL2CdsdBv99HSE/n83kCnBJyiFArJ14MlTPkD15CfXWA6uFrOEfZ5JIlAbv03q7VYBhGwu+A/F4ClJAd14NfVrDkwZigy6q2MfkW75Z6Cd2qgQYTtrwuZM/3yU8ZMT2Y2ybmyWhsxgXnYo6hZaLjOIiZ6Z1JcQio72fQ+eEB3GcP4T79LjH/p+/h7z1C5+lDOI+/hUkaWq57SZPvAvK2NrPc/PEBoi8/gX7/NtTPbsG+/zGMe7eg09pf38XwqzsIDn6B1+slmhzT1pq8BOhGXTQefYPw3gdQ776P3O2b0Dgqd25C/fQ9WJ9/hMEXHyL6LQOr1Ua5VMLx8XGS7dSkeMyy+foAncxjuC/34Lx4loz+/nMEvz6Hx9H7+Qla2T/RIoepSYnP1S5uuxRr0xTSq/BJfFSz0K3XEDVqHO3ke9CsQ1eK1GEnncPtSVF/JJVCaczKBQTUXnj8N3q5fzGmuGOtBGgKHEqrTQ9F1A7H6XS6ClmKXNd1qKoKi16JtiJWAai7YSkP7c0f0N6+gnX4Bu7JP1gYIvoyPL0M07JhUtjFYhHD4XAFKCUTsCFELLkes9ZiGK5axLhMozdTCnxGQc9pU4KM6f2M83U2hzovvzZkl9rqcGOPyYkooYi67PLCbhigz/B6YYQRM1olz8L3OgepSRETwLUEdv1kn3AXX9e+ms1mArjd57ZblMzJt0NqBHB3pXBzo9HYdA7h17ZtJstCpcIeKP1vi5oau42sKYryf1J2Acq3JGttcmjN+RrQJ8dis9ksHVDekMF5yMstbrY7koTs09t6vb67fW2SQg9lW5rF55yF9LhDHq8FlH7o1Gz0WF6eXUWtrKJJ/XXYUEOWYK/ZwKjTRoOyaTSayesnOr4yZIcetop82c5OYGUPcZjZQ/ZFBse/78P46y280yP0WIL1Qh66wSbbbqPEjjPis3slh91uF3PeOOXtXYYm9RoEfnJoPp8lTcTjxW2CyZwkK/WRWutQAOXQmICmaSYmtS7ZlINiIiHpAZqmIZfLpT9SYiJq4WTlVbD5e/0toCIhSZ7U/k5hp/3/suu3XbZrwP8Ax+GRSxrG8N0AAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/20767aa0ea46e42ca3e0795e165a5be6/f6ed8/first_fit.png' srcset='/static/20767aa0ea46e42ca3e0795e165a5be6/e7570/first_fit.png 170w, +/static/20767aa0ea46e42ca3e0795e165a5be6/f6ed8/first_fit.png 252w' sizes='(max-width: 252px) 100vw, 252px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>적재후 모습은 그림과 같으며 해당 방식은 검색을 최소화 하며 <strong>빠른 할당</strong>을 가능하게 하는 장점이 있습니다. +하지만, 이후에 보게 될 <strong>외부 단편화</strong>가 생길 가능성이 높아지게 됩니다.</p> +<br> +<br> +<h2 id="최적-적합" style="position:relative;"><a href="#%EC%B5%9C%EC%A0%81-%EC%A0%81%ED%95%A9" aria-label="최적 적합 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>최적 적합</h2> +<hr> +<p>최적 적합은 운영체제가 빈공간을 <strong>모두</strong> 검색한 후 프로세스가 적재될 수 있는 공간 중 가장 <strong>작은 공간</strong>에 프로세스를 +배치하는 방식입니다. +이전 그림에서는 빈 공간 C가 가장 적합한 크기를 가진 공간이기 때문에 그곳에 적재 됩니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 237px; '> + <a class='gatsby-resp-image-link' href='/static/7934546df5ae17afd65659dc2af0ead3/2f5e9/best_fit.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 141.17647058823528%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAcCAYAAABh2p9gAAAACXBIWXMAAAsTAAALEwEAmpwYAAAD+UlEQVR42oVWWY8bRRDOH4bwEiRWRFFAQQKhvMALyhMgRSARJBASD0BCdpclLFjreNdjzz3jY+7L4xnf9kdVx+NYtnd3pFJP13R/XfXV0XNntVphW3af5XKJyXSKyWSy9313L8udXcVsNscgSxFHAZI4gqGpODl+if/OzxEFAVLSJVGELE0xn8/3gPcAPdoUawomWhOF0sRIa5FIGPOoSmI+obHfkhAnCaMJLw4D0oeATh+YOmArWHU0oG++kZ4h5ivSw5IRqDLCON5zf8fCJZ2abgDHahO9Vyfon58irJ8jb73G3JSxIokMFY7nIQxD9Ho9wTE/exaGWxaOlCsYp89hnv0Jt3aGpFHbAGYdA3a3iz6B6bqO0Wh0AJAs9PwAGZ0OW8WqS8CuDTiWcHvV08lt+mYpSG1DWHhzUJjDMELQamIqX6JsN1BIr1G2WBoYtS8xJqunJL7ahk/u8h6OdhWYPUDHdeF2OxhGIbLAwzAOUSYxxlkixjwMME4TdAyDvPFvTxvHcTAYDMRCPpmDFMUJfEqncs0TP1mWwaXDefQJ+HBQSPhjnufi42KxQEBArPOIr0rPDx9qkJW2bUOWZZRleRiQ0yCkwAxpw4BO57EcDjEqCjHmNOf3jm0JC29x+U1QYl1BKV+hoIqY6DKmJBO9LaqlZB2N1mVdFMEeIEeHXWNhzjhyOaUEqCo4sfXjP6CfPIfz7xliysOFpYi04Sh3KAd7lIuKorzNw9lsJhQXFxeCE6tDEbZ0sWlGNezX/kZQe4X0soZcqmNJSQ2zjVCTxdqYyo/5nVJH2nDI1q3WRc6p4FFzyBQJqSwh19oYGgoKkiFRkdG8NFVojbqI/I0cLolDjuiAojlfLDEl6yfTmRjZkym1thnRsqCDu+RutObw2m4jLCTzy7LYnLx+qXrKRuetG8PNFhJgh3ipCOa5sGzdsStqdgF5zcHSY2WXolYBMpBlWSJYqqoKkMoiTnjWS5IkAloUxX5i7wKyjlOpku17h8G5TG91mRdtANmNLcK3ATkgVaUwFde6zLwMqcQqq1i3kcXbVlXV960WBgQYWCYGtg6PcvHi5AUafx1Dqf0Dh/pkSklf9Ez0dQ2GaQoumceDHXtJpju0oH/8AtGzb+H++BSNr77A5ZMvYXzzBM73XyP+6TukpLdPX6Lv+ZhS9FO6UjnSBwF7QYj42VNED97D1dE7qH/wLuyH99D+8C5aR3fR/fh9lI/uIfntF3SpK3Eta5p2zZ2yXMCNYgQ//4D48wfQPruP5qMj6J/eR/uTI2g0dh9/hOzxQ3i//0qAPjK6m9ntgxZWfw4FFXzuORj6LoY8khT0zsK6gesgpzWz9Z/D9r38P3oKSQ6mOmgJAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/7934546df5ae17afd65659dc2af0ead3/2f5e9/best_fit.png' srcset='/static/7934546df5ae17afd65659dc2af0ead3/e7570/best_fit.png 170w, +/static/7934546df5ae17afd65659dc2af0ead3/2f5e9/best_fit.png 237w' sizes='(max-width: 237px) 100vw, 237px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>적재후 모습은 그림과 같으며 해당 방식은 적재할 프로세스 크기를 고려한 방식이기 때문에 <strong>외부 단편화</strong>를 +최소화 할 수 있다는 장점이 있지만, <strong>모든</strong>공간을 검색하는 행위가 <strong>오버헤드</strong>를 발생시키기 때문에 느려집니다.</p> +<br> +<br> +<h2 id="최악-적합" style="position:relative;"><a href="#%EC%B5%9C%EC%95%85-%EC%A0%81%ED%95%A9" aria-label="최악 적합 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>최악 적합</h2> +<hr> +<p>최악 적합은 운영체제가 빈 공간을 모두 검색한 후, 가장 큰 공간에 프로세스를 적재하는 방식입니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 267px; '> + <a class='gatsby-resp-image-link' href='/static/9fa2c46dbc40f654108d90d3082d3193/fed60/worst_fit.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 127.6470588235294%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAaCAYAAAC3g3x9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAD8ElEQVR42o1VXY/bVBDNTy6CIhCrCtEiVfQBJF5KEYhuiyoVhBAI8cBmgT60yaa7bNjsJrGT2PFH4iR2bMd2PpyPw7mXONBNttsrHV1n4jtz58yZcW61WmEXsjWbpRhFESaTCS6vXedylw2L5RIJHQTuACPPhd3WcFwsQL04x2joSfhuXwa41qFYozhGp9XEpH6Oca2CqXKBebOOmVrFmLaZegG3fIyOZWGxWF7vMB6P0TcNrHSVaGDVbgJGS+7ymYgZyOnYMpvLqW85TMYTDCxTOkwbNah/HEB9lkf7+TMEZ6cySMybOt0ODNNEtVpFGIby7JIBthxGcQJH17DSVCxaCpLaOVFBUq9gxgDCPlFrMuWI9CRJgvl8fvUNI77QbTHFRh1LcrfSFIBOxL5igBVtiUy5Izm8NuWIFTa0FgJDh29oEqFlILJNBKbO3UCvqcIwDJnitQ5HoxFsRhdrQZugIGQQnzyli8V/hev3ZbpBEFCrs43j7SqTF8dxNiQPBgMZwLJt6UAsocEObSaLoijK7qIsGF3sCaPbJDwcDhF4HgIKOQoDxDwkbGLvd7sw2u3Xp5wtIZsuu2MmxMzCpE2FqGPOggibqLxH+ViCw/W5VxwKQ5qmkgvf9+ENffTaOkC9peyOFjXY+DMP64XQ4YkUdlQ9g0Xxi8JUzs7kuU3K8lbkps0UxAuW3ZE3XLI7Ur2JEXUYU3exUsWEt12aGiI+G7ouiyE0mNG1O+XpDO2/2KtffY7+/hfwHj+A++gBht9+CZfPg/370L+5D1Oj+HdMnVeLwivHHFf2yyKie3sw77yL6q23YHz8HvSP3oFGBJ/swfvsDvq2JXtZpLnTYVaxkJIwis8xvvcBzNs3Udm7QWc3od66gdaHb8O/+z68T2/DMa8oypZD6lA/PcHgyddwnz6ERwy/e4Twh8fwv38In7+7T/fR5QDRyXulUpEF3dJh5lD82ev1JD9z2ifzBRLSEE+nSNfviJlpUqtC4AKiMFd2ilC96A7ZenzRoYhNptdqUi5sy0wVHTkcFm82HDyOfuFsvsaSB0UGwoF4Fo67DLTT4XJdqaxaYsZZnDYuRWyfFFH4+Ucc/fITTn/7FUbpBYYXZTjlEzQbKlzXRa1W23AoAuT+/wWTHIpedboYiw8SP0Yddo1Aj6IP+z1MQx8+/7fI4Zj8iemUcShWbsxhkGE6ZR9ztHeYziydy0FhWjYaLQ1qo8FgI2n3eSONndJQGyiX/2YRHXk2SWLk6hw/GRRVpQzOcfzyWKJ0VEKhUECxeEQUJUqlEoqFIo74X63GM4qKel3ZIJfP55HhQOyHh/8i/3ocHv6+eT5YnxX4B9nFmgPouDSzAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/9fa2c46dbc40f654108d90d3082d3193/fed60/worst_fit.png' srcset='/static/9fa2c46dbc40f654108d90d3082d3193/e7570/worst_fit.png 170w, +/static/9fa2c46dbc40f654108d90d3082d3193/fed60/worst_fit.png 267w' sizes='(max-width: 267px) 100vw, 267px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>적재 후 모습은 가장 빈공간의 크기가 큰 B에 적재되는 것을 확인할 수 있습니다. 이러한 방식은 +외부 단편화의 발생 빈도도 크며, 모든 공간을 검색한다는 비효율적인 측면도 가지고 있습니다.</p> +<br> +<p>지금까지 <strong>외부 단편화</strong>라는 용어가 단점으로 설명했습니다. +그렇다면, <strong>외부 단편화</strong>는 어떠한 문제일까요?</p> +<br> +<h2 id="단편화" style="position:relative;"><a href="#%EB%8B%A8%ED%8E%B8%ED%99%94" aria-label="단편화 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>단편화</h2> +<hr> +<p>단편화는 크게 두가지로 나눌 수 있습니다.</p> +<ol> +<li>내부 단편화</li> +<li>외부 단편화</li> +</ol> +<br> +<h3 id="내부-단편화" style="position:relative;"><a href="#%EB%82%B4%EB%B6%80-%EB%8B%A8%ED%8E%B8%ED%99%94" aria-label="내부 단편화 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>내부 단편화</h3> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 252px; '> + <a class='gatsby-resp-image-link' href='/static/20767aa0ea46e42ca3e0795e165a5be6/f6ed8/first_fit.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 143.52941176470588%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAYAAACqhkzFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEAUlEQVR42oVWaW8bVRTtD64QiEJRUSUKFRL8BD4UiRZBl1AZ2iCCUBcpIAtI4sT2eOxZPON9du/r+HDuODZuMnEsXb3MW86799xz78uN5XKJi7b9u2r+4trablycWCwWmEwmGI9GydhqtZDNZpHP5zEcDDAZj1fGNdm7GzCO4QcBmkoBUTEPr3AKL5+DkzuCc3qCoHiGUNaUPGpcD8IwORPTUgFlwfMDBJoKmBXAMoCaCdSrq9HSaVqy5nGP43kS9zvhX/IwiKIEMDbKmOkq+oUcerRB8RSTioK5UUnWfL2CdsdBv99HSE/n83kCnBJyiFArJ14MlTPkD15CfXWA6uFrOEfZ5JIlAbv03q7VYBhGwu+A/F4ClJAd14NfVrDkwZigy6q2MfkW75Z6Cd2qgQYTtrwuZM/3yU8ZMT2Y2ybmyWhsxgXnYo6hZaLjOIiZ6Z1JcQio72fQ+eEB3GcP4T79LjH/p+/h7z1C5+lDOI+/hUkaWq57SZPvAvK2NrPc/PEBoi8/gX7/NtTPbsG+/zGMe7eg09pf38XwqzsIDn6B1+slmhzT1pq8BOhGXTQefYPw3gdQ776P3O2b0Dgqd25C/fQ9WJ9/hMEXHyL6LQOr1Ua5VMLx8XGS7dSkeMyy+foAncxjuC/34Lx4loz+/nMEvz6Hx9H7+Qla2T/RIoepSYnP1S5uuxRr0xTSq/BJfFSz0K3XEDVqHO3ke9CsQ1eK1GEnncPtSVF/JJVCaczKBQTUXnj8N3q5fzGmuGOtBGgKHEqrTQ9F1A7H6XS6ClmKXNd1qKoKi16JtiJWAai7YSkP7c0f0N6+gnX4Bu7JP1gYIvoyPL0M07JhUtjFYhHD4XAFKCUTsCFELLkes9ZiGK5axLhMozdTCnxGQc9pU4KM6f2M83U2hzovvzZkl9rqcGOPyYkooYi67PLCbhigz/B6YYQRM1olz8L3OgepSRETwLUEdv1kn3AXX9e+ms1mArjd57ZblMzJt0NqBHB3pXBzo9HYdA7h17ZtJstCpcIeKP1vi5oau42sKYryf1J2Acq3JGttcmjN+RrQJ8dis9ksHVDekMF5yMstbrY7koTs09t6vb67fW2SQg9lW5rF55yF9LhDHq8FlH7o1Gz0WF6eXUWtrKJJ/XXYUEOWYK/ZwKjTRoOyaTSayesnOr4yZIcetop82c5OYGUPcZjZQ/ZFBse/78P46y280yP0WIL1Qh66wSbbbqPEjjPis3slh91uF3PeOOXtXYYm9RoEfnJoPp8lTcTjxW2CyZwkK/WRWutQAOXQmICmaSYmtS7ZlINiIiHpAZqmIZfLpT9SYiJq4WTlVbD5e/0toCIhSZ7U/k5hp/3/suu3XbZrwP8Ax+GRSxrG8N0AAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/20767aa0ea46e42ca3e0795e165a5be6/f6ed8/first_fit.png' srcset='/static/20767aa0ea46e42ca3e0795e165a5be6/e7570/first_fit.png 170w, +/static/20767aa0ea46e42ca3e0795e165a5be6/f6ed8/first_fit.png 252w' sizes='(max-width: 252px) 100vw, 252px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>내부 단편화 문제는 이전 <strong>최초 적합</strong> 사례에서 볼 수 있습니다. +빈공간A의 크기는 30MB인데 적재한 프로세스는 20MB입니다. 이런경우 10MB의 빈공간이 생기게 되고 이러한 비어있는 +공간을 <strong>내부 단편화</strong>가 발생했다고 표현합니다.</p> +<br> +<h3 id="외부-단편화" style="position:relative;"><a href="#%EC%99%B8%EB%B6%80-%EB%8B%A8%ED%8E%B8%ED%99%94" aria-label="외부 단편화 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>외부 단편화</h3> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 252px; '> + <a class='gatsby-resp-image-link' href='/static/20767aa0ea46e42ca3e0795e165a5be6/f6ed8/first_fit.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 143.52941176470588%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAYAAACqhkzFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEAUlEQVR42oVWaW8bVRTtD64QiEJRUSUKFRL8BD4UiRZBl1AZ2iCCUBcpIAtI4sT2eOxZPON9du/r+HDuODZuMnEsXb3MW86799xz78uN5XKJi7b9u2r+4trablycWCwWmEwmGI9GydhqtZDNZpHP5zEcDDAZj1fGNdm7GzCO4QcBmkoBUTEPr3AKL5+DkzuCc3qCoHiGUNaUPGpcD8IwORPTUgFlwfMDBJoKmBXAMoCaCdSrq9HSaVqy5nGP43kS9zvhX/IwiKIEMDbKmOkq+oUcerRB8RSTioK5UUnWfL2CdsdBv99HSE/n83kCnBJyiFArJ14MlTPkD15CfXWA6uFrOEfZ5JIlAbv03q7VYBhGwu+A/F4ClJAd14NfVrDkwZigy6q2MfkW75Z6Cd2qgQYTtrwuZM/3yU8ZMT2Y2ybmyWhsxgXnYo6hZaLjOIiZ6Z1JcQio72fQ+eEB3GcP4T79LjH/p+/h7z1C5+lDOI+/hUkaWq57SZPvAvK2NrPc/PEBoi8/gX7/NtTPbsG+/zGMe7eg09pf38XwqzsIDn6B1+slmhzT1pq8BOhGXTQefYPw3gdQ776P3O2b0Dgqd25C/fQ9WJ9/hMEXHyL6LQOr1Ua5VMLx8XGS7dSkeMyy+foAncxjuC/34Lx4loz+/nMEvz6Hx9H7+Qla2T/RIoepSYnP1S5uuxRr0xTSq/BJfFSz0K3XEDVqHO3ke9CsQ1eK1GEnncPtSVF/JJVCaczKBQTUXnj8N3q5fzGmuGOtBGgKHEqrTQ9F1A7H6XS6ClmKXNd1qKoKi16JtiJWAai7YSkP7c0f0N6+gnX4Bu7JP1gYIvoyPL0M07JhUtjFYhHD4XAFKCUTsCFELLkes9ZiGK5axLhMozdTCnxGQc9pU4KM6f2M83U2hzovvzZkl9rqcGOPyYkooYi67PLCbhigz/B6YYQRM1olz8L3OgepSRETwLUEdv1kn3AXX9e+ms1mArjd57ZblMzJt0NqBHB3pXBzo9HYdA7h17ZtJstCpcIeKP1vi5oau42sKYryf1J2Acq3JGttcmjN+RrQJ8dis9ksHVDekMF5yMstbrY7koTs09t6vb67fW2SQg9lW5rF55yF9LhDHq8FlH7o1Gz0WF6eXUWtrKJJ/XXYUEOWYK/ZwKjTRoOyaTSayesnOr4yZIcetop82c5OYGUPcZjZQ/ZFBse/78P46y280yP0WIL1Qh66wSbbbqPEjjPis3slh91uF3PeOOXtXYYm9RoEfnJoPp8lTcTjxW2CyZwkK/WRWutQAOXQmICmaSYmtS7ZlINiIiHpAZqmIZfLpT9SYiJq4WTlVbD5e/0toCIhSZ7U/k5hp/3/suu3XbZrwP8Ax+GRSxrG8N0AAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/20767aa0ea46e42ca3e0795e165a5be6/f6ed8/first_fit.png' srcset='/static/20767aa0ea46e42ca3e0795e165a5be6/e7570/first_fit.png 170w, +/static/20767aa0ea46e42ca3e0795e165a5be6/f6ed8/first_fit.png 252w' sizes='(max-width: 252px) 100vw, 252px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>외부 단편화 문제는 이전 <strong>최초 적합</strong> 사례를 이어서 설명하겠습니다. +현재 그림속 비어있는 공간은 <strong>80MB</strong>입니다. 하지만 해당 공간에 <strong>80MB</strong>크기의 프로세스를 적재할 수 없습니다. +이유는, 빈 공간이 연속적인것이 아닌 프로세스C에 의해 끊어져있기 때문입니다.</p> +<p>이처럼, 프로세스를 할당하기 어려울 만큼 작은 메모리 공간들로 인해 메모리가 낭비되는 현상을 지칭합니다.</p> +<p>이러한 외부 단편화를 해결할 수 있는 대표적인 방안은 메모리를 <strong>압축</strong>하는 방법이 있습니다.</p> +<br> +<h2 id="압축" style="position:relative;"><a href="#%EC%95%95%EC%B6%95" aria-label="압축 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>압축</h2> +<hr> +<p><strong>압축</strong>이란 흩어져 있는 빈 공간들을 하나로 모으는 방식으로 메모리 내에 저장된 프로세스를 재배치 시켜 빈 공간을 +하나의 큰 빈 공간으로 만드는 방법입니다.</p> +<p>이러한 방식은 단점이 있는데, 메모리의 빈공간을 모으는 작업은 시스템을 중지 시킨다는 문제가 있습니다. +또한, 메모리를 옮기는 작업이 큰 오버헤드를 만들고, 최적화 방법에 대한 정답을 고르기가 어렵습니다.</p> +<h2 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h2> +<hr> +<p><a href="https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard">이미지 출처</a></p><![CDATA[물리주소, 논리주소 그리고 메모리 분할 방식]]>https://catch-npe.netlify.app/jc20/https://catch-npe.netlify.app/jc20/Tue, 23 Sep 2025 00:00:00 GMT<h2 id="물리주소와-논리주소" style="position:relative;"><a href="#%EB%AC%BC%EB%A6%AC%EC%A3%BC%EC%86%8C%EC%99%80-%EB%85%BC%EB%A6%AC%EC%A3%BC%EC%86%8C" aria-label="물리주소와 논리주소 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>물리주소와 논리주소</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 643px; '> + <a class='gatsby-resp-image-link' href='/static/0ccc02275a05cd2929b1e53347f2b7d9/45cbc/memory_address.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 41.76470588235294%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABaUlEQVR42mVS2W7CMBDk9/kS3pHat4q+0AhVoAhaQgUBQRpygIGczj3ddUkqVEsjO97d8cxme03ToEVd12ovqgplVT/c50WBKI5RlCXyPEdFOYwwDJFlWVfb+yOqIbMcgXOAb8xwWs0QuhYRV6pA+B7CyxnRVSAMbijLCkmSqBjvUkrwUoS/i5TVDYLdEr72DE97wnUzB0eLPMN5MYaYjSD0V6SnI0oSEQQB0jTtiBVhTDYGgwE0TSMrhVIhLz4S4Sk1JVlM0wSWPsZ+8gLrfYSbY5GrRpGxfd47Qn6l3+9jOByqi6Pj4tNYEQx1rsmypOS1ucXH0lDwXRcNKWRlLeGD5YIazn3kgBACDhXYtq3O3HguOtkWnP0W9m5NLgS4U62yf4TtipMU3mELU5/ga/oG39qpn8LJ35slzPkU5mKKs2OjugtgQo53lh/GhZRK6mkSBYhuF0iy1I2OAhSy+9hwPhMx+JvH5gfHDmJ3+Y2k1AAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/0ccc02275a05cd2929b1e53347f2b7d9/45cbc/memory_address.png' srcset='/static/0ccc02275a05cd2929b1e53347f2b7d9/e7570/memory_address.png 170w, +/static/0ccc02275a05cd2929b1e53347f2b7d9/f46e7/memory_address.png 340w, +/static/0ccc02275a05cd2929b1e53347f2b7d9/45cbc/memory_address.png 643w' sizes='(max-width: 643px) 100vw, 643px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다. +이 저장된 메모리의 데이터를 <strong>CPU</strong> 혹은 <strong>실행중인 프로그램</strong>이 읽어 실행하게 됩니다.</p> +<p>해당 그림은 두가지 관점으로 <strong>주소</strong>를 나누고 사용하는 방식을 그림으로 나타낸 것입니다.</p> +<p>왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요?</p> +<blockquote> +<p>이유는 메모리에 저장되어 있는 정보는 변화가 빠르고 이를 시시각각 알기어렵기 때문에</p> +</blockquote> +<p>가령 프로그램이 새롭게 실행될때, 삭제 될때 혹은 같은 프로그램일지라도 실행될때마다 실행되는 주소가 다르기 때문입니다.</p> +<p>그렇기때문에 주소를 두가지 관점으로 나눠서 사용하게 됩니다.</p> +<blockquote> +<p><strong>물리주소</strong>란 실제로 정보가 저장된 하드웨어상 주소를 의미합니다.</p> +</blockquote> +<blockquote> +<p><strong>논리주소</strong>란 실행중인 프로그램에 부여된 0번지부터 시작되는 주소를 의미합니다.</p> +</blockquote> +<p>여기서 주의할점은 <strong>논리주소</strong>는 0번지 부터 시작하는 논리적 주소이기 때문에, <strong>고유성</strong>이 없습니다. 하지만 <strong>물리주소</strong>는 +하드웨어상 주소기 때문에 <strong>고유성</strong>이 있습니다.</p> +<br> +<br> +<h2 id="메모리-할당-방식" style="position:relative;"><a href="#%EB%A9%94%EB%AA%A8%EB%A6%AC-%ED%95%A0%EB%8B%B9-%EB%B0%A9%EC%8B%9D" aria-label="메모리 할당 방식 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>메모리 할당 방식</h2> +<hr> +<p><strong>메모리 할당</strong>이란 주기억 장치에 프로세스를 저장하는 과정입니다. +이러한 과정은 크게 <strong>두가지</strong>로 나누어집니다.</p> +<ol> +<li>연속 할당</li> +<li>불연속 할당</li> +</ol> +<br> +<h2 id="연속할당" style="position:relative;"><a href="#%EC%97%B0%EC%86%8D%ED%95%A0%EB%8B%B9" aria-label="연속할당 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>연속할당</h2> +<hr> +<p>연속 할당은 프로세스가 연속된 메모리 영역에 할당되는 방법을 말합니다. +각 프로세스는 연속적인 메모리 주소 범위 내에 위치하게 됩니다. 이렇게 연속할당을 하게 되면 +빈공간보다 프로세스 공간이 더 작은 경우가 있는데 이러한 현상을 <strong>단편화</strong>라고 합니다.</p> +<p>연속할당의 종류로는 <strong>고정 크기 파티셔닝</strong>, <strong>가변 크기 파티셔닝</strong>이 있습니다.</p> +<br> +<h3 id="고정-크기-파티셔닝" style="position:relative;"><a href="#%EA%B3%A0%EC%A0%95-%ED%81%AC%EA%B8%B0-%ED%8C%8C%ED%8B%B0%EC%85%94%EB%8B%9D" aria-label="고정 크기 파티셔닝 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>고정 크기 파티셔닝</h3> +<p>고정 크기 파티셔닝은 메모리를 고정된 크기의 파티션으로 나누어 각 파티션에 프로세스를 할당하는 방식입니다. +예를들어, 모든 파티션을 10MB로 설정하고 파티션마다 프로세스를 할당하는 방식을 사용할 수 있습니다.</p> +<p>이러한 방식은 모든 프로세스가 지정한 파티션 크기만큼 떨어지는것이 아니기 떄문에 효율적이지 못한 단점이 있습니다.</p> +<br> +<h3 id="가변-크기-파티셔닝" style="position:relative;"><a href="#%EA%B0%80%EB%B3%80-%ED%81%AC%EA%B8%B0-%ED%8C%8C%ED%8B%B0%EC%85%94%EB%8B%9D" aria-label="가변 크기 파티셔닝 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>가변 크기 파티셔닝</h3> +<p>가변 크기 파티셔닝은 파티션의 크기를 유동적으로 조절하는 메모리 할당 방식입니다. +이러한 방식은 <strong>고정 크기 파티셔닝</strong>보다는 효율적이지만, 메모리 공간에 어떤 프로세스를 저장해야 할지 결정하는게 +복잡합니다.</p> +<br> +<br> +<h2 id="불연속-할당" style="position:relative;"><a href="#%EB%B6%88%EC%97%B0%EC%86%8D-%ED%95%A0%EB%8B%B9" aria-label="불연속 할당 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>불연속 할당</h2> +<hr> +<p>불연속 할당은 한 프로세스를 메모리 여러 곳에 분산 저장하는 방법입니다. <strong>페이징</strong>, <strong>세그멘테이션</strong> 이 있습니다.</p> +<br> +<h3 id="페이징" style="position:relative;"><a href="#%ED%8E%98%EC%9D%B4%EC%A7%95" aria-label="페이징 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>페이징</h3> +<p>페이징은 프로세스의 주소 공간을 페이지라는 동일한 크기의 구획으로 나누고, 주기억 장치도 페이지와 동일한 크기의 +프레임이라는 구획으로 나눕니다. 이후 한 페이지를 한 프레임에 적재하는 방식입니다.</p> +<p>자세한 내용은 이후에 다루게 됩니다.</p> +<br> +<h3 id="세그멘테이션" style="position:relative;"><a href="#%EC%84%B8%EA%B7%B8%EB%A9%98%ED%85%8C%EC%9D%B4%EC%85%98" aria-label="세그멘테이션 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>세그멘테이션</h3> +<p>프로세스의 주소공간을 세그먼트라는 단위로 나누어 주기억 장치에 적재합니다. +프로세스는 코드, 데이터, 스택 등으로 구성되기 때문에 각각을 한 세그먼트로 나누어서 메모리에 적재합니다.</p> +<p>이 과정에서, base주소와, limit주소를 이용하여 프로세스가 자신에게 할당된 메모리 영역만 사용하게 합니다.</p> +<br> +<h2 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h2> +<hr> +<p><a href="https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard">이미지 출처</a></p><![CDATA[교착상태와 해결 방법]]>https://catch-npe.netlify.app/jc19/https://catch-npe.netlify.app/jc19/Mon, 22 Sep 2025 00:00:00 GMT<h2 id="교착상태란Dead-Lock" style="position:relative;"><a href="#%EA%B5%90%EC%B0%A9%EC%83%81%ED%83%9C%EB%9E%80Dead-Lock" aria-label="교착상태란Dead Lock permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>교착상태란?(Dead Lock)</h2> +<hr> +<p><strong>교착상태</strong>란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다.</p> +<p><strong>교착상태</strong>를 설명하는 대표적인 예시로 <strong>식사하는 철학자 문제</strong>라는게 있습니다.</p> +<br> +<h3 id="식사하는-철학자" style="position:relative;"><a href="#%EC%8B%9D%EC%82%AC%ED%95%98%EB%8A%94-%EC%B2%A0%ED%95%99%EC%9E%90" aria-label="식사하는 철학자 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>식사하는 철학자</h3> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 386px; '> + <a class='gatsby-resp-image-link' href='/static/ac3e35aa0a3b2f0934e3f7c0935bbeac/d999c/dpp.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 89.41176470588235%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB+klEQVR42p1U22oiQRCd/3/cENigediX7MPmKUKyYVECmsQgEQlERWXG++B1vN/1pE+xJcYYJ6Sgpmemi9OnTlW1tdlscMzX6zWWyyVWqxX8YunWsU3aZDJBrVZDo9H4Eqh1jBltMBigXq+Lz+dz+ce9bzMcDocolUpwHAez2Uz+7R66D24dYsaVuo3HY/T7fQEj6HA0kgMWi8VxhjQCMFDfPc8T7bgfiUTw6/wcbaPjyBziuq7EEJzv1PkdIMXudDpoNptotVpot9sCzO9yuQynWET07g6uOSBfKIiWjCfzVColh6scFh8aYNs2fl9cwHZs/Lu+wevLy1YzXbvdLv7e3uI5mRQwgpKESrXVkLSpV8EwyOfzCAaDyKTTAsQM6DSmfHZ6ivj9vaS7r6d1qO/oTJvM9wtG4IYBGvR7H6r+DlAps7LsPVaV2mjfaV9ypabUl0X5FFAZqp5e10P2NS1s1ZpGq0wmg+l/eXwBxQ2DmQFlRX/+OMHD44Mwds2kXF3+QSAQ2LLznRRNazqdIv4URywWk9R7vZ7Mcst40aQbCoUQjUYlzndSaNVqFUnTFkyPwrNV6JSDIIlEAuFwGLlcTiq9O9/WIXaVSgVp0zJaZU7F0rQHV+2EbDYrGegQfADcBWaK1O3QdaWtw9tHwb58ffndRPtgBHwDfadqXrKxi3cAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/ac3e35aa0a3b2f0934e3f7c0935bbeac/d999c/dpp.png' srcset='/static/ac3e35aa0a3b2f0934e3f7c0935bbeac/e7570/dpp.png 170w, +/static/ac3e35aa0a3b2f0934e3f7c0935bbeac/f46e7/dpp.png 340w, +/static/ac3e35aa0a3b2f0934e3f7c0935bbeac/d999c/dpp.png 386w' sizes='(max-width: 386px) 100vw, 386px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습니다. +식사를 하려면 두개의 포크를 들어야 하는 상황입니다.</p> +<p>이를 순서도로 표현하면</p> +<ol> +<li>생각을 하다가 왼쪽 포크를 들 수 있다면 든다.</li> +<li>생각을 하다가 오른쪽 포크를 들 수 있다면 든다.</li> +<li>왼쪽, 오른쪽 포크를 모두 집어들면 정해진 시간동안 식사를 한다.</li> +<li>식사 시간이 끝나면 오른쪽 포크를 내려놓는다.</li> +<li>나머지 왼쪽 포크도 내려놓는다.</li> +<li>1번부터 반복한다.</li> +</ol> +<br> +<p>위와같은 상황일때 모든 철학자가 왼쪽 포크를 들고 있거나, 반대쪽 포크를 들고 있다면 식사는 영원히 끝나지 않습니다. 이유는 포크라는 자원은 +철학자의 수만큼 존재하고 각 철학자는 두개의 포크를 원하는 상태에서 모든 포크를 얻을때까지 가디라기 떄문에, 모든 철학자가 포크를 기다리기만 하는 +상황이 발생합니다.</p> +<p>이러한 문제는 <strong>일어나지 않을 사건을 기다리며 진행이 멈춰 버리는</strong> <strong>교착상태</strong>와 같습니다.</p> +<p>여기서 철학자를 <strong>프로세스 혹은 스레드</strong> 포크를 <strong>자원</strong> 그리고 생각하는 행위가 자원을 기다리는 것이라고 생각한다면, 프로세스와 스레드는 +<strong>자원</strong>을 사용하기 위해 <strong>기다리는 행위</strong>만 계속하는 상황이 되는것입니다.</p> +<br> +<br> +<h2 id="교착상태-발생조건" style="position:relative;"><a href="#%EA%B5%90%EC%B0%A9%EC%83%81%ED%83%9C-%EB%B0%9C%EC%83%9D%EC%A1%B0%EA%B1%B4" aria-label="교착상태 발생조건 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>교착상태 발생조건</h2> +<hr> +<p>교착상태가 발생할 조건에는 네가지가 있습니다. 차례대로 <strong>상호배제</strong>, <strong>점유와 대기</strong>, <strong>비선점</strong>, <strong>원형 대기</strong>입니다. 해당 조건은 +모두 만족해야지 <strong>교착상태</strong>가 발생하고 하나라도 해당하지 않는다면 <strong>교착상태</strong>는 발생하지 않습니다.</p> +<br> +<h3 id="1-상호-배제" style="position:relative;"><a href="#1-%EC%83%81%ED%98%B8-%EB%B0%B0%EC%A0%9C" aria-label="1 상호 배제 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>1. 상호 배제</h3> +<p>교착 상태가 발생한 근본적인 원인은 해당 자원을 하나의 프로세스만 사용하기 때문입니다. 프로세스도 마찬가지로 한 프로세스가 사용하는 자원을 다른 프로세스가 +사용할 수 없을때, 교착상태가 발생합니다.</p> +<h3 id="2-점유와-대기" style="position:relative;"><a href="#2-%EC%A0%90%EC%9C%A0%EC%99%80-%EB%8C%80%EA%B8%B0" aria-label="2 점유와 대기 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>2. 점유와 대기</h3> +<p>프로세스는 자원을 할당받은 상태에서 다른 자원을 할당받기를 기다린다면 교착 상태가 발생할 수 있습니다. 이렇게 <strong>자원을 할당받은 상태에서 다른 자원을 +할당받기를 기다리는 상태</strong>를 <strong>점유와 대기</strong>라고 합니다.</p> +<h3 id="3-비선점" style="position:relative;"><a href="#3-%EB%B9%84%EC%84%A0%EC%A0%90" aria-label="3 비선점 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>3. 비선점</h3> +<p>이전에 <strong>선점</strong>, <strong>비선점</strong>이라는 개념을 보았습니다. <strong>비선점</strong>이란 프로세스나 스레드가 자원을 할당받으면 그 작업이 끝나기전까지 자원을 뻇어갈수 없다는 +특징이 있었습니다. 교착상태가 발생하는 원인은 <strong>점유와 대기</strong>상태중 필요한 자원을 <strong>선점</strong>할수 없이 계속 기다리기만 하여서 발생하는 문제 입니다.</p> +<h3 id="4-원형-대기" style="position:relative;"><a href="#4-%EC%9B%90%ED%98%95-%EB%8C%80%EA%B8%B0" aria-label="4 원형 대기 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>4. 원형 대기</h3> +<p><strong>자원 할당 그래프</strong>가 원의 형태로 그려지면 교착 상태가 발생할 수 있습니다. 이렇게 프로세스들이 원의 형태로 자원을 대기하는 것을 <strong>원형 대기</strong>라고 합니다.</p> +<br> +<br> +<h2 id="교착상태-해결방법" style="position:relative;"><a href="#%EA%B5%90%EC%B0%A9%EC%83%81%ED%83%9C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95" aria-label="교착상태 해결방법 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>교착상태 해결방법</h2> +<hr> +<p>교착상태를 해결하는 방법은 크게 세가지로 나눌수 있습니다.</p> +<blockquote> +<ol> +<li>예방</li> +<li>회피</li> +<li>검출 후 회복</li> +</ol> +</blockquote> +<br> +<br> +<h2 id="예방을-통한-해결" style="position:relative;"><a href="#%EC%98%88%EB%B0%A9%EC%9D%84-%ED%86%B5%ED%95%9C-%ED%95%B4%EA%B2%B0" aria-label="예방을 통한 해결 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>예방을 통한 해결</h2> +<hr> +<p>예방이란 교착상태 발생 조건에 부합하지 않게 자원을 분배하는 방식입니다.</p> +<p>이전에 말한 <strong>교착상태</strong>발생 조건에 해당하는 네 가지 중 하나를 충족 하게 되면 <strong>교착 상태</strong>를 해결할 수 있습니다.</p> +<h3 id="상호-배제를-없애는-방식" style="position:relative;"><a href="#%EC%83%81%ED%98%B8-%EB%B0%B0%EC%A0%9C%EB%A5%BC-%EC%97%86%EC%95%A0%EB%8A%94-%EB%B0%A9%EC%8B%9D" aria-label="상호 배제를 없애는 방식 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>상호 배제를 없애는 방식</h3> +<blockquote> +<p>이론적으로는 가능하나, 모든 자원이 상호 배제를 없애기는 어렵기 때문에 비현실적이다.</p> +</blockquote> +<br> +<h3 id="점유와-대기를-없애는-방식" style="position:relative;"><a href="#%EC%A0%90%EC%9C%A0%EC%99%80-%EB%8C%80%EA%B8%B0%EB%A5%BC-%EC%97%86%EC%95%A0%EB%8A%94-%EB%B0%A9%EC%8B%9D" aria-label="점유와 대기를 없애는 방식 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>점유와 대기를 없애는 방식</h3> +<blockquote> +<p>특정 자원이 먼저 점유를 수행하여 작업을 끝내고, 다른 프로세스에게 자원을 몰아주는 방식으로 해결이 가능합니다.</p> +<p>하지만 이런 방식은 자원 활용률이 낮아 진다는 문제가 있습니다.</p> +</blockquote> +<br> +<h3 id="비선점-조건을-없애는-방식" style="position:relative;"><a href="#%EB%B9%84%EC%84%A0%EC%A0%90-%EC%A1%B0%EA%B1%B4%EC%9D%84-%EC%97%86%EC%95%A0%EB%8A%94-%EB%B0%A9%EC%8B%9D" aria-label="비선점 조건을 없애는 방식 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>비선점 조건을 없애는 방식</h3> +<blockquote> +<p>비선점 방식으로 작업을 다루게 되면 교착상태가 발생해도 자원을 뺏어 해결 할 수 있습니다.</p> +<p>하지만, 이런방식의 문제점은 모든 자원이 비선점 기능을 사용할 수 없다는 점에 있습니다.</p> +<p>예를들어, 프린터는 비선점 방식을 수행하는 자원입니다.</p> +</blockquote> +<br> +<h3 id="원형-대기-조건을-없애는-방식" style="position:relative;"><a href="#%EC%9B%90%ED%98%95-%EB%8C%80%EA%B8%B0-%EC%A1%B0%EA%B1%B4%EC%9D%84-%EC%97%86%EC%95%A0%EB%8A%94-%EB%B0%A9%EC%8B%9D" aria-label="원형 대기 조건을 없애는 방식 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>원형 대기 조건을 없애는 방식</h3> +<blockquote> +<p>모든 자원에 번홀을 붙이고 오름차순으로 자원을 할당하면 원형 대기는 방생하지 않습니다. +마치 원형이 아닌, 선형으로 자원을 나열하는 방식입니다.</p> +<p>이런 방식은 자원에 일일이 번호를 붙여야 한다는점과, 특정 번호는 자원 활용률이 떨어질수 있다는 문제가 있습니다.</p> +</blockquote> +<br> +<br> +<h2 id="회피를-통한-해결" style="position:relative;"><a href="#%ED%9A%8C%ED%94%BC%EB%A5%BC-%ED%86%B5%ED%95%9C-%ED%95%B4%EA%B2%B0" aria-label="회피를 통한 해결 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>회피를 통한 해결</h2> +<hr> +<p>회피 방식에서는 교착 상태 발생이 한정된 자원을 무분별하게 할당하였서 그렇다고 가정합니다. 그렇기 때문에 회피방식은 자원을 신중하게 할당하는 방식으로 +해결합니다.</p> +<p>즉, 교착 상태가 발생하지 않을 정도의 양만큼만 자원을 배분하는 방법을 <strong>교착 상태 회피</strong>라고 부릅니다.</p> +<p><strong>안정 상태</strong>, <strong>불안전 상태</strong>가 있습니다. 각각 교착상태가 발생하지 않는 상태를 <strong>안정상태</strong>, 발생할 가능성이 있는 상태를 <strong>불안정 상태</strong>라고 부릅니다.</p> +<p><strong>회피</strong>를 통해 교착상태를 해결하기 위해 <strong>안전 순서열</strong>을 고려해서 문제를 해결합니다.</p> +<blockquote> +<p>안전순서열: 교착 상태 없이 안전하게 프로세스들에 자원을 할당할 수 있는 순서를 의미합니다.</p> +</blockquote> +<br> +<p>내용을 종합하면 <strong>안전 순서열</strong>이 있고 그것을 사용할때 상태를 <strong>안정상태</strong>, 안전 순서열이 없을 때 상태는 <strong>불안정상태</strong>라고 부르게 됩니다.</p> +<br> +<br> +<h2 id="교착-상태-검출-후-회복" style="position:relative;"><a href="#%EA%B5%90%EC%B0%A9-%EC%83%81%ED%83%9C-%EA%B2%80%EC%B6%9C-%ED%9B%84-%ED%9A%8C%EB%B3%B5" aria-label="교착 상태 검출 후 회복 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>교착 상태 검출 후 회복</h2> +<hr> +<p>마지막으로, 교착상태를 피하기 위해서는 <strong>검출</strong>, <strong>회복</strong> 방식을 사용합니다.</p> +<p>두가지 방식을 고려할 수 있는데,</p> +<ol> +<li>선점을 통한 회복</li> +<li>프로세스 강제종료</li> +</ol> +<br> +<h3 id="선점을-통한-회복" style="position:relative;"><a href="#%EC%84%A0%EC%A0%90%EC%9D%84-%ED%86%B5%ED%95%9C-%ED%9A%8C%EB%B3%B5" aria-label="선점을 통한 회복 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>선점을 통한 회복</h3> +<p>교착 상태가 해결될 때까지 한 프로세스씩 자원을 몰아주는 방식입니다. 교착 상태가 해결될 떄까지 다른 프로세스로부터 자원을 빼앗고 할당하는 방식입니다.</p> +<br> +<h3 id="강제종료를-통한-회복" style="position:relative;"><a href="#%EA%B0%95%EC%A0%9C%EC%A2%85%EB%A3%8C%EB%A5%BC-%ED%86%B5%ED%95%9C-%ED%9A%8C%EB%B3%B5" aria-label="강제종료를 통한 회복 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>강제종료를 통한 회복</h3> +<p>교착 상태에 놓인 순간 모든 프로세스를 종료 하는 방법 혹은 프로세스를 하나씩 종료해서 확인해보는 방법이 있습니다.</p> +<p>전자는 가장 확실하지만 모든 작업에 대한 진행사항을 잃을 가능성이 있고, 후자는 전자보다 손실에 대한 부담은 적지만 오버헤드가 커진다는 단점이 있습니다.</p> +<h2 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h2> +<hr> +<p><a href="https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard">이미지 출처</a></p><![CDATA[상호배제와 동기화 기법]]>https://catch-npe.netlify.app/jc18/https://catch-npe.netlify.app/jc18/Sun, 21 Sep 2025 00:00:00 GMT<h2 id="상호배제Mutual-Exclusion" style="position:relative;"><a href="#%EC%83%81%ED%98%B8%EB%B0%B0%EC%A0%9CMutual-Exclusion" aria-label="상호배제Mutual Exclusion permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>상호배제(Mutual Exclusion)</h2> +<hr> +<p>상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다.</p> +<p>일상생활에서 비유하면, 화장실 사용과 같습니다. +한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다. +컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 프로세스만 사용할 수 있어야 합니다.</p> +<br> +<h2 id="왜-상호배제가-필요할까" style="position:relative;"><a href="#%EC%99%9C-%EC%83%81%ED%98%B8%EB%B0%B0%EC%A0%9C%EA%B0%80-%ED%95%84%EC%9A%94%ED%95%A0%EA%B9%8C" aria-label="왜 상호배제가 필요할까 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>왜 상호배제가 필요할까?</h2> +<p>현대 운영체제는 멀티태스킹 환경에서 여러 프로세스가 동시에 실행됩니다. +이때 프로세스들이 공유하는 자원(메모리, 파일, 데이터베이스 등)에 동시에 접근하면 다음과 같은 문제가 발생할 수 있습니다.</p> +<h3 id="1경쟁-상황Race-Condition" style="position:relative;"><a href="#1%EA%B2%BD%EC%9F%81-%EC%83%81%ED%99%A9Race-Condition" aria-label="1경쟁 상황Race Condition permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>1.경쟁 상황(Race Condition)</h3> +<p>두 프로세스가 동시에 같은 데이터를 수정하려 할 때, 실행 순서에 따라 결과가 달라지는 상황입니다. +예를 들어, 은행 계좌 잔액을 동시에 업데이트하는 두 거래가 있다면, 최종 잔액이 예상과 다를 수 있습니다.</p> +<h3 id="2-데이터-일관성-파괴" style="position:relative;"><a href="#2-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9D%BC%EA%B4%80%EC%84%B1-%ED%8C%8C%EA%B4%B4" aria-label="2 데이터 일관성 파괴 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>2. 데이터 일관성 파괴</h3> +<p>여러 프로세스가 동시에 데이터를 수정하면 데이터의 무결성이 깨질 수 있습니다. 이는 시스템 전체의 신뢰성에 큰 영향을 미칩니다.</p> +<br> +<br> +<h2 id="동기화-기법" style="position:relative;"><a href="#%EB%8F%99%EA%B8%B0%ED%99%94-%EA%B8%B0%EB%B2%95" aria-label="동기화 기법 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>동기화 기법</h2> +<hr> +<p>이런 <strong>상호 배제</strong>에 대해 방지하는 방법으로는 <strong>뮤텍스</strong>, <strong>세마포어</strong>, <strong>모니터</strong> 기법이 있습니다.</p> +<br> +<br> +<h2 id="뮤텍스-락Mutex-lock" style="position:relative;"><a href="#%EB%AE%A4%ED%85%8D%EC%8A%A4-%EB%9D%BDMutex-lock" aria-label="뮤텍스 락Mutex lock permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>뮤텍스 락(Mutex lock)</h2> +<hr> +<p><strong>뮤텍스 락</strong>의 풀네임은 <strong>Mutual Exclusion Lock</strong>입니다. 즉 상호 배제 단어에 lock을 붙인 단어와 일치합니다.</p> +<p>이 말은 상호배제를 구현하기 위해 <strong>Locking</strong>방식을 사용하는 방법입니다.</p> +<p><strong>뮤텍스 락</strong>은 화장실 사용에 비유해보겠습니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 300px; '> + <a class='gatsby-resp-image-link' href='/static/f9f8af880e42af0dc1c2a6a94c2ddad0/a8a0d/toilet.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 149.41176470588235%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,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'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/f9f8af880e42af0dc1c2a6a94c2ddad0/a8a0d/toilet.png' srcset='/static/f9f8af880e42af0dc1c2a6a94c2ddad0/e7570/toilet.png 170w, +/static/f9f8af880e42af0dc1c2a6a94c2ddad0/a8a0d/toilet.png 300w' sizes='(max-width: 300px) 100vw, 300px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>화장실은 한칸에 한사람만 받을 수 있습니다. 칸에 사람이 들어가있다면 해당 칸에 다른 사람이 들어올 수 없습니다. +다른 사람이 들어오는 시점은 먼저 사용하던 사람이 해당 칸을 나가게 되면 사용할 수 있습니다.</p> +<p>이 내용을 설명하는 이유는, 위 방식의 흐름이 뮤텍스 락과 동일하기 때문입니다.</p> +<p>간단한 <strong>뮤텍스락</strong>을 코드를 통해서 보겠습니다.</p> +<p><strong>자물쇠</strong>에 해당하는 전역변수 하나, 그리고 해당 <strong>자물쇠</strong>를 잠구고, 푸는 두가지 함수만 있으면 구현가능합니다.</p> +<br> +<br> +<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token function">acquire</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token keyword">while</span> <span class="token punctuation">(</span>lock <span class="token operator">==</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> + <span class="token punctuation">}</span> + + lock <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> +<span class="token punctuation">}</span></code></pre></div> +<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token function">release</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + lock <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span> + <span class="token punctuation">}</span></code></pre></div> +<br> +<p>해당 함수들은 차례대로 화장실 문이 잠겼는지 확인하고 잠기지 않았다면 들어가서 잠구는 함수 <strong>Acquire</strong>, +그리고 화장실을 나올때 잠금을 해제 하는 <strong>Release</strong>로 볼 수 있습니다.</p> +<p>이 함수를 아래 수도코드 처럼, 임계 구역 들어가기전, 나온 후 에 사용하게 되면</p> +<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token function">acquire</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> +<span class="token comment">// 임계 구역</span> +<span class="token function">release</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> +<p><strong>lock</strong>여부를 확인 한 후, 들어가도 되면 본인이 <strong>lock</strong>을 걸고 이미 <strong>lock</strong>이 걸려있다면 +임계 구역 코드 전에서 계속 기다리게 됩니다.</p> +<br> +<h3 id="뮤텍스-락의-단점" style="position:relative;"><a href="#%EB%AE%A4%ED%85%8D%EC%8A%A4-%EB%9D%BD%EC%9D%98-%EB%8B%A8%EC%A0%90" aria-label="뮤텍스 락의 단점 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>뮤텍스 락의 단점</h3> +<p>하지만, 이런 방식에는 큰 문제가 있는데 <strong>바쁜대기(Busy Wait)</strong> 을 수행하게 됩니다. +명칭 그대로 대기를 하는 상황임에도 바쁘게 행동하는 것을 말하게 됩니다.</p> +<p><strong>대기</strong>를 하는 상황에 행동을 하는것은 <strong>lock 확인</strong>작업에 <strong>CPU</strong>를 사용하겠다는 것을 의미하고, +이런 기다림은 해당 <strong>lock</strong> 이 풀릴떄까지 지속됩니다. 즉, 비효율적입니다.</p> +<br> +<br> +<h2 id="세마포semaphore" style="position:relative;"><a href="#%EC%84%B8%EB%A7%88%ED%8F%ACsemaphore" aria-label="세마포semaphore permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>세마포(semaphore)</h2> +<hr> +<p><strong>세마포</strong>는 동기화 방식중 하나입니다. <strong>뮤텍스 락</strong>과 비교하면 공유자원의 갯수를 다루는 방식이 다릅니다. +<strong>뮤텍스 락</strong>은 공유자원이 하나라고 가정하고 라킹을 수행하지만, <strong>세마포</strong>는 공유 자원이 여러 개 있을경우 +각 프로세스는 해당 공유자원에 접근이 가능합니다.</p> +<p>마치 공중화장실에서 화장신 칸 수 만큼 공유자원이 있고, 각 칸에 사람이 들어가는 것을 관리하는 방식입니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/0207ef441e61d6de31d0ce6e37b1a2c4/ed72c/semaphore.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 133.52941176470588%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,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'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/0207ef441e61d6de31d0ce6e37b1a2c4/ca1dc/semaphore.png' srcset='/static/0207ef441e61d6de31d0ce6e37b1a2c4/e7570/semaphore.png 170w, +/static/0207ef441e61d6de31d0ce6e37b1a2c4/f46e7/semaphore.png 340w, +/static/0207ef441e61d6de31d0ce6e37b1a2c4/ca1dc/semaphore.png 680w, +/static/0207ef441e61d6de31d0ce6e37b1a2c4/02d09/semaphore.png 1020w, +/static/0207ef441e61d6de31d0ce6e37b1a2c4/9d567/semaphore.png 1360w, +/static/0207ef441e61d6de31d0ce6e37b1a2c4/ed72c/semaphore.png 1944w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p><strong>세마포</strong>는 사진과 같은 <strong>철도 신호기</strong>에서 유래한 단어 입니다. 그렇기 때문에 철도 신호와 같은 방식을 사용합니다.</p> +<p><strong>뮤텍스 락</strong>은 공유 자원을 <strong>잠금</strong>, <strong>해제</strong>를 수행하면서 해당 자원을 관리하지만,</p> +<p><strong>세마포</strong>의 경우 <strong>빨간불</strong>, <strong>초록불</strong> 처럼 가도 되는지, 멈춰야 하는지 상태를 알려줍니다.</p> +<p><strong>세마포</strong>도 간단하게 코드로 구현이 가능합니다.</p> +<p>먼저 <strong>공유자원의 갯수</strong>를 나타내는 전역 변수 한개와, 임계구역에 들어가도 되는지, 기다려야 할지 알려주는 함수 <strong>Wait</strong>, +그리고 기다리고 있는 프로세스에게 <strong>이제 출발하라</strong>를 나타내는 <strong>Signal</strong>함수가 있습니다.</p> +<br> +<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token function">wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token keyword">while</span><span class="token punctuation">(</span><span class="token class-name">S</span> <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + + <span class="token punctuation">}</span> + <span class="token class-name">S</span><span class="token operator">--</span><span class="token punctuation">;</span> +<span class="token punctuation">}</span></code></pre></div> +<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token function">signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> + <span class="token class-name">S</span><span class="token operator">++</span><span class="token punctuation">;</span> +<span class="token punctuation">}</span></code></pre></div> +<p>위 코드를 차례대로 <strong>Wait</strong>, <strong>Signal</strong>함수를 구현한것이고 전역 변수 S의 값이 양수, 즉 사용해도 되는 +공유자원이 있을 경우 <strong>Wait</strong>함수의 while문을 탈출합니다.</p> +<p>그 경우 사용가능한 공유 자원 갯수를 하나 줄입니다.</p> +<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token function">wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> +<span class="token comment">// 임계 구역</span> +<span class="token function">signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div> +<p>임계 구역을 나오게 되면 signal이 수행될것이고, 사용가능한 자원을 하나 반납하게 될것입니다.</p> +<br> +<p>근데 while문이 있다면 <strong>뮤텍스락</strong>처럼 <strong>바쁜 대기</strong> 상태가 발생할 수 있다는걸 암시하게 됩니다. +하지만 이는 세마포가 <strong>CPU</strong>를 사용하지 않게 구현하며 해결할 수 있습니다.</p> +<br> +<h2 id="세마포가-busy-wait를-해결하는-방법" style="position:relative;"><a href="#%EC%84%B8%EB%A7%88%ED%8F%AC%EA%B0%80-busy-wait%EB%A5%BC-%ED%95%B4%EA%B2%B0%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95" aria-label="세마포가 busy wait를 해결하는 방법 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>세마포가 busy wait를 해결하는 방법</h2> +<hr> +<p>아래 두가지 함수를 통해서 세마포는 <strong>busy wait</strong>를 해결합니다.</p> +<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token function">wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token class-name">S</span><span class="token operator">--</span><span class="token punctuation">;</span> + <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token class-name">S</span> <span class="token operator">&lt;</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + add <span class="token keyword">this</span> process <span class="token keyword">to</span> <span class="token class-name">Queue</span><span class="token punctuation">;</span> + <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span></code></pre></div> +<div class="gatsby-highlight" data-language="java"><pre class="language-java"><code class="language-java"><span class="token function">signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + <span class="token class-name">S</span><span class="token operator">++</span> + <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token class-name">S</span> <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">{</span> + remove a process p from <span class="token class-name">Queue</span><span class="token punctuation">;</span> + <span class="token function">wakeup</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span><span class="token punctuation">;</span> + <span class="token punctuation">}</span> +<span class="token punctuation">}</span></code></pre></div> +<p>위 방식은 이전처럼 while문을 통한 접근 가능여부를 체크하는 것이 아닌 만약 접근 불가능 한경우(사용가능한 공유 자원이 없을떄) +해당 프로세스의 <strong>PCB</strong>를 <strong>세마포</strong>를 위한 <strong>대기 큐</strong>에 넣습니다.</p> +<p>프로세스는 대기 큐에 들어가게 되면서 이후 해당 <strong>PCB</strong>를 <strong>준비 큐</strong>로 돌리기 전까지 <strong>CPU</strong>자원을 잡아 먹지 않게 됩니다.</p> +<br> +<br> +<h2 id="모니터" style="position:relative;"><a href="#%EB%AA%A8%EB%8B%88%ED%84%B0" aria-label="모니터 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>모니터</h2> +<hr> +<p>세마포 기법 자체는 동기화도구로써 좋은 효능을 보여주지만, 사용자 측면에서 불편한 점이 있다. +임계 구역에 앞뒤로 wait, signal 함수를 사용하고 휴먼에러로 인한 실수가 발생한다면 예기치 못한 결과를 발생시킬 수 있기 때문이다.</p> +<p>이에 <strong>모니터</strong>라는 동기화 도구가 생기게 된다.</p> +<p>모니터는 공유 자원과, 공유 자원에 접근하기 위한 인터페이스를 묶어 관리합니다.</p> +<br> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/669afa9347fd496414ecf17dea3f4def/65dc2/monitor.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 38.82352941176471%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABCklEQVR42l1SiarDMAzL///exqPrWwelXe/7vrXJ4FJmEE4cW5aTmOM48It5njFNk2AcxxPX2DAMgr7vT6zrCrPvOwgSqe+6DnmeS3HbtqjrGk3TiGch18xRQvosyyTfkICmhLSqqvB6OaIkTVMEQQDf9+F5njQqyxLbtp11WsPJTNs2iKLoixBJkkgBPTuSUPdhGEoeC6mQhDo2jbFlWWDY/X6/4fGw8Hz+w7L+8H7738RRRuS567pwHAe2bcueCjmNjktjTAirqkQcx6KCniNSFeVTIUmLohDFjOv96ahqJJRH+T2gkYwj6SNxTWiuPtYVFCR3qK98BTvp19EvoiRUyRhVEldSKvwAs/do84a0I/MAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/669afa9347fd496414ecf17dea3f4def/ca1dc/monitor.png' srcset='/static/669afa9347fd496414ecf17dea3f4def/e7570/monitor.png 170w, +/static/669afa9347fd496414ecf17dea3f4def/f46e7/monitor.png 340w, +/static/669afa9347fd496414ecf17dea3f4def/ca1dc/monitor.png 680w, +/static/669afa9347fd496414ecf17dea3f4def/65dc2/monitor.png 954w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>이를 위해 모니터를 통해 공유 자원에 접근하고자 하는 프로세스를 큐에 삽입하고, 큐에 삽입된 순서대로 하나씩 공유 자원을 이용하도록 합니다. +모니터는 공유 자원을 다루는 인터페이스에 접근하기 위한 큐를 만들고, 모니터 안에 항상 하나의 프로세스만 들어오도록 하여 <strong>상호 배제</strong>를 수행합니다.</p> +<p>또한, 모니터는 <strong>실행 순서</strong>를 제어하는 동기화 또한 수횅합니다. <strong>조건 변수</strong>를 사용해서 실행 순서를 제어하게 됩니다.</p> +<br> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/90c62ae0dccb15076bf6c0fc6661af14/04883/monitor2.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 60.58823529411765%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABtElEQVR42m2TiXKDMAxE8/+f1zbThEJIOHJMAhhsTDi3WjfuNfGMENjWs1Yyq2VZ8N/GeUZziGHCLfQugI62UME7ys3ameZ8HKJrW1jbobMWrbx3XYfVf5g80I8j2nADqxRsU8OoCucsxSkVSxIMfY8+TzHK/ARgniYMw4CmaZ4D77JoDxFsa6DlZK0NjHgaMyFkvF4w1QoS4eImgXLteYYC7A47TOKHYXQbtTGwIklrjVG2TU+ATyUvD8l29wFdlVBVBSNSjG6g6xqteJfh+YhZgH7MUncrtXRAfnjzQPWxgZZGsAG3txcU61dUbMr7G9TD12Xh6kZTUm8jKhzQj+8uj18y7/c7qrLE5XJBnmXI8xy32w21BLtaikxvhDoggxkQhiGiKEIqneRp/lSuZQKK49iZhzKOnW1FJgflui6TGgSBwELsBEifpIkrPrO4Xq/IJLv9fu+Ax+PRHUQgFTCequg5v2JQIncrzzMXSDufT65jDCDYZ0q4rxWBvkwcXtGfGvrBzazL787z2w9/RSiTxnfCarkF311elp8uM6CXv4EZ0hjgAUVROO/X7OO3Y9a8h5+pE5v1silExQAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/90c62ae0dccb15076bf6c0fc6661af14/ca1dc/monitor2.png' srcset='/static/90c62ae0dccb15076bf6c0fc6661af14/e7570/monitor2.png 170w, +/static/90c62ae0dccb15076bf6c0fc6661af14/f46e7/monitor2.png 340w, +/static/90c62ae0dccb15076bf6c0fc6661af14/ca1dc/monitor2.png 680w, +/static/90c62ae0dccb15076bf6c0fc6661af14/04883/monitor2.png 737w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>해당 그림처럼 기존 <strong>상호 배제를 위한 큐</strong>가 아닌 <strong>조건 변수</strong>에 대한 큐가 있습니다. 이 <strong>조건 변수</strong>는 기존처럼 <strong>wait</strong>, <strong>signal</strong> 연산을 +수횅할 수 있습니다.</p> +<p>상호 배제를 위한 큐에서 가장 선두에 있는 프로세스A보다 특정 프로세스B가 더 먼저 시행되어야 한다면, B가 수행되기 전까지 앞선 프로세스들은 <strong>wait</strong> 연산을 통해 +조건 변수에 대한 큐에서 대기하게 되고, 그렇게 대기를 하게되면 최우선 시행되는 프로세스는 <strong>B</strong>가 될것입니다. 이런 형태로 모니터는 실행 순서를 제어합니다.</p> +<h2 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h2> +<hr> +<p><a href="https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard">이미지 출처</a></p><![CDATA[임계구역과 경쟁상태]]>https://catch-npe.netlify.app/jc17/https://catch-npe.netlify.app/jc17/Sat, 20 Sep 2025 00:00:00 GMT<h3 id="공유자원" style="position:relative;"><a href="#%EA%B3%B5%EC%9C%A0%EC%9E%90%EC%9B%90" aria-label="공유자원 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>공유자원</h3> +<hr> +<p>동시에 실행되는 프로세스에서 <strong>공통</strong>으로 사용하는 자원을 우리는 <strong>공유자원</strong>이라고 부릅니다.</p> +<br> +<br> +<h2 id="임계구역Critical-Section" style="position:relative;"><a href="#%EC%9E%84%EA%B3%84%EA%B5%AC%EC%97%ADCritical-Section" aria-label="임계구역Critical Section permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>임계구역(Critical Section)</h2> +<hr> +<p>공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 <strong>임계 구역</strong>이라고 부릅니다.</p> +<p>두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한 프로세스의 +작업이 마무리되면 그제서야 기다렸던 프로세스가 임계 구역에 진입 합니다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 661px; '> + <a class='gatsby-resp-image-link' href='/static/227dd7b56ba55467737bedfce6783436/4128c/critical_section.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 38.23529411764706%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABDElEQVR42m1Rya6EMAzj/z8TicOwtGVpgbL42dWE4fAqRU2c1EncCt8zLwvGaYLzHj4E5Jwthfu+Mc8znHMYx7HYeZ5Pzm5ZFZiMIut7rNOIJXjM3iHR34jnFBGGoZCIdCE2sXFKCeu6Yts27Pv+IxS4E8wbb/qZ/nUcOFgkTHEiiSbSg+u6HhOR+Q+hxlXxuyiRWBPYWgcb3K9HZgX/NrG7soRN0HP1uq7RNA0Grqojck9tFUvHrutKvWQwTCZJKiWVkDYCLFZBIMlErP18sPiBGgfE4BClMbV2bC4NZbZhZRMo0M+KVGu3bVt8YfqEtyw6wqX/+4eLhu/A9BKRusYYSzMzEcis/vpH1z/ixG+TQlubNAAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/227dd7b56ba55467737bedfce6783436/4128c/critical_section.png' srcset='/static/227dd7b56ba55467737bedfce6783436/e7570/critical_section.png 170w, +/static/227dd7b56ba55467737bedfce6783436/f46e7/critical_section.png 340w, +/static/227dd7b56ba55467737bedfce6783436/4128c/critical_section.png 661w' sizes='(max-width: 661px) 100vw, 661px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<br> +<h2 id="경쟁상태Race-Condition" style="position:relative;"><a href="#%EA%B2%BD%EC%9F%81%EC%83%81%ED%83%9CRace-Condition" aria-label="경쟁상태Race Condition permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>경쟁상태(Race Condition)</h2> +<hr> +<p><strong>임계 구역</strong>은 두 개 이상의 프로세스가 동시에 실행되면 안 되는 영역이지만, 잘못된 실행으로 여러 프로세스가 +<strong>공유 자원</strong>을 사용하는 경우에 문제가 발생합니다. +이러한 문제를 <strong>경쟁 상태</strong>라고 합니다.</p> +<p>이러한 <strong>경쟁 상태</strong>는 데이터의 일관성이 깨지는 문제를 발생시킵니다.</p> +<br> +<br> +<h2 id="운영체제가-임계구역-문제를-해결하는-세가지-원칙" style="position:relative;"><a href="#%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EA%B0%80-%EC%9E%84%EA%B3%84%EA%B5%AC%EC%97%AD-%EB%AC%B8%EC%A0%9C%EB%A5%BC-%ED%95%B4%EA%B2%B0%ED%95%98%EB%8A%94-%EC%84%B8%EA%B0%80%EC%A7%80-%EC%9B%90%EC%B9%99" aria-label="운영체제가 임계구역 문제를 해결하는 세가지 원칙 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>운영체제가 임계구역 문제를 해결하는 세가지 원칙</h2> +<hr> +<h3 id="1-상호배제-한-프로세스가-임계-구역에-진입했다면-다른-프로세스가-들어올-수-없다" style="position:relative;"><a href="#1-%EC%83%81%ED%98%B8%EB%B0%B0%EC%A0%9C-%ED%95%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EA%B0%80-%EC%9E%84%EA%B3%84-%EA%B5%AC%EC%97%AD%EC%97%90-%EC%A7%84%EC%9E%85%ED%96%88%EB%8B%A4%EB%A9%B4-%EB%8B%A4%EB%A5%B8-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EA%B0%80-%EB%93%A4%EC%96%B4%EC%98%AC-%EC%88%98-%EC%97%86%EB%8B%A4" aria-label="1 상호배제 한 프로세스가 임계 구역에 진입했다면 다른 프로세스가 들어올 수 없다 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>1. 상호배제: 한 프로세스가 임계 구역에 진입했다면 다른 프로세스가 들어올 수 없다.</h3> +<h3 id="2-진행-임계구역에-어떤-프로세스도-진입하지-않았다면-진입하고자-하는-프로세는-들어갈-수-있어야-한다" style="position:relative;"><a href="#2-%EC%A7%84%ED%96%89-%EC%9E%84%EA%B3%84%EA%B5%AC%EC%97%AD%EC%97%90-%EC%96%B4%EB%96%A4-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%8F%84-%EC%A7%84%EC%9E%85%ED%95%98%EC%A7%80-%EC%95%8A%EC%95%98%EB%8B%A4%EB%A9%B4-%EC%A7%84%EC%9E%85%ED%95%98%EA%B3%A0%EC%9E%90-%ED%95%98%EB%8A%94-%ED%94%84%EB%A1%9C%EC%84%B8%EB%8A%94-%EB%93%A4%EC%96%B4%EA%B0%88-%EC%88%98-%EC%9E%88%EC%96%B4%EC%95%BC-%ED%95%9C%EB%8B%A4" aria-label="2 진행 임계구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세는 들어갈 수 있어야 한다 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>2. 진행: 임계구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세는 들어갈 수 있어야 한다.</h3> +<h3 id="3-유한-대기-한-프로세스가-임계구역에-진입하고-싶다면-언젠가는-임계구역에-들어갈-수-있어야-한다무한정-대기x" style="position:relative;"><a href="#3-%EC%9C%A0%ED%95%9C-%EB%8C%80%EA%B8%B0-%ED%95%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EA%B0%80-%EC%9E%84%EA%B3%84%EA%B5%AC%EC%97%AD%EC%97%90-%EC%A7%84%EC%9E%85%ED%95%98%EA%B3%A0-%EC%8B%B6%EB%8B%A4%EB%A9%B4-%EC%96%B8%EC%A0%A0%EA%B0%80%EB%8A%94-%EC%9E%84%EA%B3%84%EA%B5%AC%EC%97%AD%EC%97%90-%EB%93%A4%EC%96%B4%EA%B0%88-%EC%88%98-%EC%9E%88%EC%96%B4%EC%95%BC-%ED%95%9C%EB%8B%A4%EB%AC%B4%ED%95%9C%EC%A0%95-%EB%8C%80%EA%B8%B0x" aria-label="3 유한 대기 한 프로세스가 임계구역에 진입하고 싶다면 언젠가는 임계구역에 들어갈 수 있어야 한다무한정 대기x permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>3. 유한 대기: 한 프로세스가 임계구역에 진입하고 싶다면 언젠가는 임계구역에 들어갈 수 있어야 한다.(무한정 대기x)</h3> +<h2 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h2> +<hr> +<p><a href="https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard">이미지 출처</a></p><![CDATA[병행성과 병렬성의 차이 및 프로세스 동기화의 필요성]]>https://catch-npe.netlify.app/jc16/https://catch-npe.netlify.app/jc16/Fri, 19 Sep 2025 00:00:00 GMT<h2 id="병행성Concurrency" style="position:relative;"><a href="#%EB%B3%91%ED%96%89%EC%84%B1Concurrency" aria-label="병행성Concurrency permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>병행성(Concurrency)</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/3991c57592bd10053b35de83aab4f83d/809bd/concurrency.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 57.64705882352942%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAACGklEQVR42o1TS2/TQBD2/+RW9cKNA+IfcAEucIITEhAVJBA3qoIQqCCSCFVKSoCmoY1NEtuJ36917PXux+zmIUolYKTx7EP7zffNjA2QSSm1KxMUhd7jn940DXzfB2MMGzPKstQX/2068crruobjOEjTDEIITcqIkwQJeZrRIa8xmGR48z3Gic2Q5g2CtMYiZAhTjoT2RyMPr449tEcBynKpyXDOoYipBIb6xHEMd76AqBjuv59h57GJpx0Pjs9xOmU4JhAVZx7HXtfHbmuMW/uWBtyYAq6qCsalGooGMUnw4gL5koM3Ao2QFCUqLrTYOMkxD1PERYX1s4uAeZ7Dded0KNQVWh9/4srDc9w5sGG5FYbTEkffXAzOE0yJ5cvPHnYejXHtmYkgWTVEyd4Cbuu9jna0RN9SjzNIysEqAbZssKypEVzCzxr0zAgnk0CDXALMsg3Ddbclx+FXGzf3bbS6AcnjBF7jbJLAdFSDJDrDELdfz3D33RxhXulSLf9kuJ0K4tr5EeHe2ykO+nOUTGIR1bCcFLZXEqBAzyrw4INLzbNpQvKLNVQtj6JIz9IWmDImeYH2WYyumSHMOEknNUydc2Kjal/h03CBw1EKJyr12GlAhazmUAr5G0tgYAW4umfixnMLvfMcY7dGn+avf+rr9ReL4foLC7tPxmiTIlUq4+8/hdQjU9ccRVHoX4yxcu1Me1GsXK2V7F8rio/zBXTNqAAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/3991c57592bd10053b35de83aab4f83d/ca1dc/concurrency.png' srcset='/static/3991c57592bd10053b35de83aab4f83d/e7570/concurrency.png 170w, +/static/3991c57592bd10053b35de83aab4f83d/f46e7/concurrency.png 340w, +/static/3991c57592bd10053b35de83aab4f83d/ca1dc/concurrency.png 680w, +/static/3991c57592bd10053b35de83aab4f83d/809bd/concurrency.png 821w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>병행성은 다른 말로 <strong>동시성</strong>이라고 부르는 용어입니다. +이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 <strong>컨텍스트 스위칭</strong>을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다. +이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실행되는 것은 아닙니다.</p> +<p>동시성의 핵심 키워드는 <strong>동시에 처리되게 보이는것</strong>입니다.</p> +<br> +<br> +<h2 id="병렬성Parallelism" style="position:relative;"><a href="#%EB%B3%91%EB%A0%AC%EC%84%B1Parallelism" aria-label="병렬성Parallelism permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>병렬성(Parallelism)</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/82dde5a226f42fe16edc8cb7217d610d/e0a8c/parallelism.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 61.1764705882353%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABqklEQVR42o1T20rDQBDN3/sDfoJP+iaCoKhIQcFSi0VD7UV70ab31DZpsptsjjPTbkyVggNhd2fOnJk50zogy7IMSZoiSRIYkyKOYyilxEdBVPo+5mEsd00YjmutCGvkzac1R8jISWjo1ODozsVkGcqbSZEZjAMFRTEupgULNLwZTsoNuXN+svU7GYFmQYTBIqSODA7OK/AWgQTNtiN7Z2xntkJKHT12xzi8qeUxJkxpIoc7aQ3nqL578PwVRkTWny1x+dIVsFJaTibhbkuvfcG5n1NSwODK7eJt8pV36vD8Sm+S6oMp2iNfxl2FUV7Vmiacfd83PxDpBBHpGVNRxrJ8jq3OYNbI6mEo0SYTjsbakLLPEqvtyZ9djIOCWc24En82mQv93E0uAfsZV7QdwjgxuG1PCExkhXEvnju4dreaap1vtDMPMFxG+RR/CNkX6U0nnOR6vviPy02c1TqbzngK1pwW0vMDjFfxfkJrog8JXar34AdrPPXGstHTaguhYn13l7V35KJJF9RzGGs8tAfiC9bRzo/Yav0vQiG1G6cF2L8ld/abpEj4Dcj3p6XPYvF8AAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/82dde5a226f42fe16edc8cb7217d610d/ca1dc/parallelism.png' srcset='/static/82dde5a226f42fe16edc8cb7217d610d/e7570/parallelism.png 170w, +/static/82dde5a226f42fe16edc8cb7217d610d/f46e7/parallelism.png 340w, +/static/82dde5a226f42fe16edc8cb7217d610d/ca1dc/parallelism.png 680w, +/static/82dde5a226f42fe16edc8cb7217d610d/e0a8c/parallelism.png 998w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>병렬 처리는 프로그램의 독립적인 작업을 동시에 실행할 수 있는 능력입니다. 이러한 작업은 +다른 프로세스 코어 단위에서, 혹은 분산 시스템 처럼 완전히 다른 컴퓨터에서 동시에 실행될 수 도 있습니다.</p> +<p>병렬성의 핵심 키워드는 <strong>실제로 동시에 처리되고 있는것</strong>입니다.</p> +<br> +<br> +<h2 id="동기화" style="position:relative;"><a href="#%EB%8F%99%EA%B8%B0%ED%99%94" aria-label="동기화 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>동기화</h2> +<hr> +<p>동시다발적으로 실행되는 프로세스들은 공동의 목적을 수행하기 위해 서로 협력하며 영향을 주고 받기도 합니다. +조금 전 설명했던 <strong>동시성</strong>, <strong>병렬성</strong> 모두 동시다발적으로 수행되는 환경입니다.</p> +<p>이런 환경의 예시를 하나들면, 워드 프로세스가 있습니다. 해당 프로세스는 글을 쓸수도 있고, 쓰여진 글을 읽을 수도 있고, +맞춤법을 검사하는 기능도 있습니다. 하지만 해당 프로세스가 따로 동작하는 것이 아닌 모두 하나의 프로그램처럼 보여지고 있습니다.</p> +<p>이런 상황을 <strong>동시 다발적</strong>이란 표현을 통해 하고, 이런 동시 다발적인 상황의 <strong>수행 시기</strong>를 맞춰주는 것이 +<strong>동기화</strong>라고 합니다.</p> +<br> +<h3 id="수행-시기를-맞추다" style="position:relative;"><a href="#%EC%88%98%ED%96%89-%EC%8B%9C%EA%B8%B0%EB%A5%BC-%EB%A7%9E%EC%B6%94%EB%8B%A4" aria-label="수행 시기를 맞추다 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>수행 시기를 맞추다?</h3> +<p>이전에 설명한 <strong>수행 시기</strong>를 맞추다는 말은 추상적입니다.</p> +<p>이를 두가지 관점으로 볼 수 있습니다.</p> +<ol> +<li>실행 순서 제어: 프로세스를 올바른 순서대로 실행하는것</li> +<li>상호 배제: 동시에 접근해서는 안 되는 자원에 하나의 프로세스만 접근하는 것</li> +</ol> +<p>다시 말해 <strong>동기화</strong>는 실행 순서를 제어하는 <strong>동기화</strong>와, <strong>상호 배제</strong>를 위한 동기화가 있습니다.</p> +<br> +<br> +<h2 id="1-실행-순서를-제어하는-동기화" style="position:relative;"><a href="#1-%EC%8B%A4%ED%96%89-%EC%88%9C%EC%84%9C%EB%A5%BC-%EC%A0%9C%EC%96%B4%ED%95%98%EB%8A%94-%EB%8F%99%EA%B8%B0%ED%99%94" aria-label="1 실행 순서를 제어하는 동기화 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>1. 실행 순서를 제어하는 동기화</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 427px; '> + <a class='gatsby-resp-image-link' href='/static/013fc07c2d0d31bf3697260791d4a845/86b21/execution_order.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 63.52941176470588%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAABk0lEQVR42nVTSXKDMBD003PPQ5KcnGsqh1R+EgcDNhJI7JhtMj2A7ICtqvaURu2elV1d15RlGeV5LkjTVADfYrPs/32yE88YI//DGYaBdtZafoQznf9oHaxNKAiO5PseJYlmTia8iWvFwq9UdBWcsjKCKap1d2Ni8ryDQOtI7gBEYMGJY8XQV8Gu66iqKoE1CZkkme+l2KapqSxLyS5F+WgJW5sXVHG74G+aRgTHcaQdfgjgE319kPn+nB452ubMvDqJ6bx/pcYax4WOE4Sj54dw/0LR+xsNKxJKAfq+FwHrH+nw/ERVdKJRSu1XgktkLqWZJ7b4N+C3vm0p+/2hgds1rjMc5tLQKz8IyA8DQl8fCjKwGQff5+Ekm+BOEBOOeZLnU0hFUTzMEmVrrUirM0Vc8jq4KxlrURSZkC+Xy0ZwCYzJY1Wwg3Ecu3XZCCIryZJ3ClHvZYjTtp3wDK+Y5Z3dCMKBjJRSXELES+y5T+leydhJrTWFYShoeUC33N1SDr5pCIOAPj0aCLLHIoMH3GYHwT8kIfEBKS6EGAAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/013fc07c2d0d31bf3697260791d4a845/86b21/execution_order.png' srcset='/static/013fc07c2d0d31bf3697260791d4a845/e7570/execution_order.png 170w, +/static/013fc07c2d0d31bf3697260791d4a845/f46e7/execution_order.png 340w, +/static/013fc07c2d0d31bf3697260791d4a845/86b21/execution_order.png 427w' sizes='(max-width: 427px) 100vw, 427px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>실행 순서를 제어한다는 것은 요리 레시피 순서를 지키는것과 같습니다. +재료를 준비하고, 손질하고, 요리하는 이런 일련의 과정을 지켜 보았을 때 +재료 손질이 준비보다 먼저일 수 없고, 요리또한 손질보다 먼저일 수 없습니다.</p> +<p>프로세스도 마찬가지로 무언가를 읽게 하였는데 읽은 대상이 생성 되어있고, 작성되어있어야 합니다. +이런 것을 <strong>실행 순서</strong>라고 표현하며 이것을 지키게 하는 것을 <strong>동기화</strong>라고 표현합니다.</p> +<br> +<br> +<h2 id="2-상호-배제를-위한-동기화" style="position:relative;"><a href="#2-%EC%83%81%ED%98%B8-%EB%B0%B0%EC%A0%9C%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%8F%99%EA%B8%B0%ED%99%94" aria-label="2 상호 배제를 위한 동기화 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>2. 상호 배제를 위한 동기화</h2> +<hr> +<p><strong>상호 배제</strong>란 공유가 불가능한 자원의 동시 사용을 피하기 위해 사용하는 알고리즘입니다. +여기서 말하는 공유가 불가능한 자원은 실제로 공유하면 안되는 자원이 아닌, 동시 사용하는 경우 문제가 발생하는 +자원입니다.</p> +<p>아래 예시를 통해서 보면</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 636px; '> + <a class='gatsby-resp-image-link' href='/static/8347db1726710180f62eb67407a9a278/44bb2/mutual_exclusion.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 53.529411764705884%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABMUlEQVR42m1Sia6EIAz0///SI67rtQreIt1O3+vGA5IJBOgchahpGrLW0nEcdB/DMFBRFLQsy+NsmiZq25a6riPvvexhjlBQlqUcgmCeZ5kBYwxBEPM4jkKCGUBNVVVShxoApqI4iSlNU0qTRIoHdgvH27bJBcA59wBEQKoOsScO6+JFLSsZY3+XoApCjXGOpOj7Xu5B/HwW7UziOIqn51jXVeIt/5GUGANE2o4LIe5gofEUGB+OE3Mr8jynLMukr9pLrOu6fhKq4jmO93+ElmM17zfV3AY4QkQAJCANOlTFfd+vpHzJrQu5wZLft+CXqtghenkhhO3QIwAbi0zcO/xDtEH3sYYRwy0Z748Sjux/nxevDhf3czi0bGbkMwhCQAjPyiGEBFWs4P6ijwCSgvALbVlaKd1UugUAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/8347db1726710180f62eb67407a9a278/44bb2/mutual_exclusion.png' srcset='/static/8347db1726710180f62eb67407a9a278/e7570/mutual_exclusion.png 170w, +/static/8347db1726710180f62eb67407a9a278/f46e7/mutual_exclusion.png 340w, +/static/8347db1726710180f62eb67407a9a278/44bb2/mutual_exclusion.png 636w' sizes='(max-width: 636px) 100vw, 636px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>프로세스A는 현재 잔고에서 2만원을 더하고, 프로세스B는 현재 잔고에서 5만원을 더합니다. +이러한 경우 총합 7만원을 더하는 형태가 될것입니다.</p> +<p>하지만 프로세스A가 값을 더하고(12만원) 저장하기 전에 <strong>콘텍스트 스위칭</strong>이 일어난다면 다음 프로세스B는 +저장하기 전 값을 조회하고(10만원) 자신의 값을 저장할것 입니다(15만원). +다시 프로세스 A로 돌아오면 12만원을 저장하고 프로세스 B로 돌아오면 15만원을 저장합니다. +이과정에서 서로의 결과를 무시하는 방향으로 진행되고 최종적으로 마지막에 저장한 값은 다른 프로세스의 결과를 +반영하지 않는 상태가 됩니다.</p> +<p>이런 상황은 동시에 사용하는 자원에 대해 <strong>동기화</strong>를 이루지 못해서 발생한 경우이고, 이 경우 <strong>상호 배제를 위한 동기화</strong> +를 진행해야 합니다.</p> +<br> +<br> +<h2 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h2> +<hr> +<p><a href="https://www.baeldung.com/cs/concurrency-vs-parallelism">동시성, 병렬성 출처</a> +<a href="https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard">이미지 출처</a></p><![CDATA[멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링]]>https://catch-npe.netlify.app/jc15/https://catch-npe.netlify.app/jc15/Thu, 18 Sep 2025 00:00:00 GMT<h2 id="다단계-큐-스케쥴링Multilevel-queue-scheduling" style="position:relative;"><a href="#%EB%8B%A4%EB%8B%A8%EA%B3%84-%ED%81%90-%EC%8A%A4%EC%BC%80%EC%A5%B4%EB%A7%81Multilevel-queue-scheduling" aria-label="다단계 큐 스케쥴링Multilevel queue scheduling permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>다단계 큐 스케쥴링(Multilevel queue scheduling)</h2> +<hr> +<p>멀티 레벨 스케줄링은 <strong>우선순위</strong> 스케줄링의 발전된 형태입니다. +아래 그림을 통해 설명 하면,</p> +<br> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 494px; '> + <a class='gatsby-resp-image-link' href='/static/60e4f68cce87294a66d21c988098034a/7f4de/multilevel_queue.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 50%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABhUlEQVR42nWSW2+CQBSE/bX+y/a5D31oYkLFC0VLsVLKzb0pu0xnAa21cZMvh+UyO+cMk67r4EgHwDqH1rqxWjSHA7Qx3Hf9vTP+m3tMHF8otjHS2QvqaAmxWUNuo74Wy1cc4hV0EsMQXxWfqaaGX70ZfwgPd+NBE9u2qJIN6jyDKEvoqoauK4iqxKmpYKM5urfwglu/QpbFIDiKnMUHQaqXmwhlsoWiqMw+L+hsh9aLxIsLNgphRod+KaUQhiFKmvGLLVMwXiMNAzQfW4hdAklE+g7zmcDeCnJfZXsIqdCyuyAIMJ1O8fD4MAj6lpv0A0YwACmgWBXDkMQ7OfmWbxwqjsONLQohMJvNkOf52aHD9ypE/PyEcsEQokVPQxQDsVdig+AchjO+P0M6rHcppDYwvNanE9TxCEmM1jjSUXcjKIvfUP6nzI3gDPXbsncmWVW87N0Z73A9h4t+sasAosj/OLz5Dzsc2YLJ91BMdmAPnQ+o76xHfjEIPjvsdzBM9rrNa8Efein6YecmiY8AAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/60e4f68cce87294a66d21c988098034a/7f4de/multilevel_queue.png' srcset='/static/60e4f68cce87294a66d21c988098034a/e7570/multilevel_queue.png 170w, +/static/60e4f68cce87294a66d21c988098034a/f46e7/multilevel_queue.png 340w, +/static/60e4f68cce87294a66d21c988098034a/7f4de/multilevel_queue.png 494w' sizes='(max-width: 494px) 100vw, 494px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데, +멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다.</p> +<p>가장 높은 우선순위에 있는 큐들을 처리하고, 가장 높은 우선순위 큐가 비게 된다면 그 아래 우선순위의 큐를 처리하게 됩니다. +그림을 통해 이해하자면, 우선순위 0 -> 우선순위 1 -> 우선순위 2 이렇게 처리하게 되는것입니다.</p> +<p>멀티레벨 큐의 특징으로는 각각의 큐들을 개별적으로 핸들링 할 수 있습니다. +예를들어, 특정 큐의 타임 슬라이드와 다른 큐의 타임 슬라이드를 다르게 처리 한다던가, 혹은 스케줄링 방식 자체를 +FCFS를 적용하고 다른 곳에서는 라운드로빈을 적용하는것 처럼 개별적인 핸들링이 가능합니다.</p> +<br> +<br> +<h3 id="다단계-큐-스케쥴링-문제점" style="position:relative;"><a href="#%EB%8B%A4%EB%8B%A8%EA%B3%84-%ED%81%90-%EC%8A%A4%EC%BC%80%EC%A5%B4%EB%A7%81-%EB%AC%B8%EC%A0%9C%EC%A0%90" aria-label="다단계 큐 스케쥴링 문제점 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>다단계 큐 스케쥴링 문제점</h3> +<hr> +<p>다단계 큐 스케줄링의 문제점으로는 <strong>기아</strong> 현상이 있습니다.</p> +<p>멀티레벨 큐 방식에서는 큐간의 이동이 불가능합니다. 그렇기 떄문에 우선순위가 낮은 곳에 배정받은 프로세스들은 +이전에 보았던 <strong>에이징</strong>방식을 사용할수 없습니다. 그렇기 때문에 이러한 방식은 우선순위가 올때 까지 기다려야 하는 +기아 현상을 문제로 가지고 있습니다.</p> +<p>이러한 방식의 해결법은 아래 설명할 다단계 피드백 큐 스케줄링으로 해결이 가능합니다.</p> +<br> +<br> +<h2 id="다단계-피드백-큐-스케줄링multilevel-feedback-queue-scheduling" style="position:relative;"><a href="#%EB%8B%A4%EB%8B%A8%EA%B3%84-%ED%94%BC%EB%93%9C%EB%B0%B1-%ED%81%90-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81multilevel-feedback-queue-scheduling" aria-label="다단계 피드백 큐 스케줄링multilevel feedback queue scheduling permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>다단계 피드백 큐 스케줄링(multilevel feedback queue scheduling)</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 574px; '> + <a class='gatsby-resp-image-link' href='/static/3fb97878005bfac081fee26625bd9ede/312c2/multi_feedback_queue.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 54.11764705882353%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB8klEQVR42nVSWY6bQBT0iX2luUjmK8pnItnyijfAZrHNZuiFvVLddmYmUoJUPKCb6nqvajKOI/51mc/dMGD47/r4ga/fJn3XQSQ3iPsVOk2g0juaLIVK7ri6R+RRiLrIiQwqy6DNWvlA3/fo+K8hmc/neH//BikFJh1v4ewXgsUMpbuH8A5Q/on1iPriojtu0B02z2qwX6FwuUfXUFJa4re3N0ynU8RxjElTVSivV9Q8rW4abtTQtYbkDw2f29MWo+dgcB3WHUa+q+jyORdeRVEgDEOreNIrhWj2E/FyBsmTJVVaUKkmBkNCGEILqlTRGRXV3SgkiiKkaQohhFU7afmQB2cUeQbxKCy0qJDeb/B2DqSzRMs2TbvDS6EIfIRRjLPvwyc8z0MQBNDsyM4wP+1RXWPUNETdY2ialF18BJuVbbkhoXIWFnozt4Rmho/HA0mSICMqjm5gKmzLpt1gtUDluxAXDzIgSNjGAfrTa3ZEb8h3S6QHh3Nu0LYtZFkiOXsfEWLLNOVGVVzUdU0zPk2peVhrCN2/TZFUaPLZUlG43SD48d2aYxV2SqLcLiD362fdrSAI864Yl/awZmzWdo4WbLtkrP7EWVBhSmPGr8FuGNyGptRZ8kSeWjSvaqBeoZc0S3F24ys2SmlkeWEdNoS/ASWcP7gsZAAAAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/3fb97878005bfac081fee26625bd9ede/312c2/multi_feedback_queue.png' srcset='/static/3fb97878005bfac081fee26625bd9ede/e7570/multi_feedback_queue.png 170w, +/static/3fb97878005bfac081fee26625bd9ede/f46e7/multi_feedback_queue.png 340w, +/static/3fb97878005bfac081fee26625bd9ede/312c2/multi_feedback_queue.png 574w' sizes='(max-width: 574px) 100vw, 574px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>다단계 피드백 큐 스케줄링 같은경우는 프로세스들이 큐 사이로 이동할 수 있습니다. 그렇기 때문에 이전 방식에서 보았던 +<strong>기아</strong>현상을 직접적으로 해결할 수 있습니다.</p> +<br> +<h3 id="다단계-피드백-큐-스케줄링-특징" style="position:relative;"><a href="#%EB%8B%A4%EB%8B%A8%EA%B3%84-%ED%94%BC%EB%93%9C%EB%B0%B1-%ED%81%90-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81-%ED%8A%B9%EC%A7%95" aria-label="다단계 피드백 큐 스케줄링 특징 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>다단계 피드백 큐 스케줄링 특징</h3> +<p>이러한 이동가능한 점 때문에 <strong>멀티 레벨 큐</strong>와 다른 점이 있습니다. +<strong>멀티 레벨 피드백 큐</strong>는 처음 생성된 프로세스가 우선순위가 가장 높은 큐로 삽입이 됩니다. 그 이후 CPU를 할당받고 +타임슬라이드 동안 실행되며, 이 실행이 끝나게 된다면 다음 우선순위 큐로 넘어 갑니다(우선순위가 낮아짐). 또 다음 우선순위 +큐에서 실행이 끝나지 않는다면 또 다음 우선순위로 넘어가고 이 과정을 반복합니다.</p> +<p>이렇게 우선순위가 낮아지는 방식을 사용함으로써 자동으로 <strong>CPU 버스트</strong>가 많은 프로세스는 우선순위가 낮아지고, +<strong>IO 버스트</strong>가 많은 프로세스는 상대적으로 우선순위가 높아질것입니다.</p> +<h3 id="기아-해결" style="position:relative;"><a href="#%EA%B8%B0%EC%95%84-%ED%95%B4%EA%B2%B0" aria-label="기아 해결 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>기아 해결</h3> +<p>또한, 프로세스들이 이동가능 하기 때문에 우선순위가 낮아져 <strong>기아</strong>상태에 빠진 프로세스에는 <strong>에이징</strong>기법을 적용해 +다시 우선순위를 높이게 됩니다.</p><![CDATA[CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)]]>https://catch-npe.netlify.app/jc14/https://catch-npe.netlify.app/jc14/Wed, 17 Sep 2025 00:00:00 GMT<h2 id="스케줄링-알고리즘-개요" style="position:relative;"><a href="#%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B0%9C%EC%9A%94" aria-label="스케줄링 알고리즘 개요 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>스케줄링 알고리즘 개요</h2> +<hr> +<p>스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다.</p> +<br> +<ul> +<li>비선점 스케줄링 +<ul> +<li>선입 선처리 스케줄링 (FCFS)</li> +<li>최단 작업 우선 스케줄링 (SJF)</li> +</ul> +</li> +</ul> +<br> +<ul> +<li>선점 스케줄링 +<ul> +<li>라운드 로빈 스케줄링</li> +<li>최소 잔여 시간 우성 스케줄링 (SRT)</li> +<li>우선순위 스케줄링</li> +</ul> +</li> +</ul> +<br> +<h1 id="비-선점-스케줄링" style="position:relative;"><a href="#%EB%B9%84-%EC%84%A0%EC%A0%90-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="비 선점 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>비 선점 스케줄링</h1> +<br> +<br> +<h2 id="선입-선처리-스케줄FCFS" style="position:relative;"><a href="#%EC%84%A0%EC%9E%85-%EC%84%A0%EC%B2%98%EB%A6%AC-%EC%8A%A4%EC%BC%80%EC%A4%84FCFS" aria-label="선입 선처리 스케줄FCFS permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>선입 선처리 스케줄(FCFS)</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 495px; '> + <a class='gatsby-resp-image-link' href='/static/759055f93278a883db6ec01d61336cb4/68bae/fcfs.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 53.529411764705884%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB3klEQVR42m1T2XLbMAzUf/s7mtfmG9p+RSadpEl8yqduWrZuSpQlebukHc+kNWZ2AAnUElhAFq52xlc7dR2kUuiHweTu4nz+D1YWeCjcLZQI0EQ+ZOCiCX3kzhZiMUXp7dBeczeEHspY3CW1osk7xGyMfLMkbFTOGvl2aVBsV5C8LF/bSFcL5jZI6EvmUuY+CQd2oWEI88A3LTbtCbJR5pBu1QsC7FwHeVnB9T34YYAkz807sd+j2EcXqa6VfcZWHl4IT20LpZoLeVMjpBQxPyqLwsRJckCWpibO0gRFFKKjzsN5wM9fP/D4+B0FzxoNtelkS1Jt2vus8EiCspKs0EfK6tIsg+cHrLpEwqqllLy8wcPDN4xGIxwOB1haC5UeIeM9qr1Aa2IBz57DWcxw9By49MHKRsxBaS/WS2Tu7rYRurKUl/d9D6tZL9AvJ+hXU/TrGTE1aObvqCav9G+IX56Qvv2GssfAzsaZeelubkO5rZ7WUHJiimTNaoZ6Ob2A8eHjhXjFkRB/nlHMP1AuxqhsktEnrPTulAdq13cng+7UYug7ZGw/3G2RCIFjGCLjVFMR8TliLkbkOKjZJu7t4b/br01R9JKTVLJCXRZoqwot32nf1TUaknUcxr0/5S8QFUMlRL58dgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/759055f93278a883db6ec01d61336cb4/68bae/fcfs.png' srcset='/static/759055f93278a883db6ec01d61336cb4/e7570/fcfs.png 170w, +/static/759055f93278a883db6ec01d61336cb4/f46e7/fcfs.png 340w, +/static/759055f93278a883db6ec01d61336cb4/68bae/fcfs.png 495w' sizes='(max-width: 495px) 100vw, 495px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>FCFS는 <strong>준비 큐</strong>에 들어가있는 순서대로 CPU를 할당하는 간단한 스케줄링 입니다.</p> +<p>하지만, FCFS 방식에는 <strong>호위 효과</strong>라는 문제가 있습니다.</p> +<p>그림을 보면 프로세스 A, B, C순서대로 실행되며 각각 실행 시간이 17, 5, 2 ms가 걸리게 됩니다. +이상황에서 프로세스 B는 실행 상태가 되기 위해 최소 17ms를 기다려야 하며, 프로세스 c는 22ms를 기다리게 됩니다.</p> +<blockquote> +<p>이러한 현상을 <strong>호위 효과(Convoy effect)</strong> 라고 하며 이것이 FCFS 스케줄링의 단점입니다.</p> +</blockquote> +<br> +<br> +<p>하지만, 이러한 FCFS 방식도 배치 처리 시스템이나 작업 길이가 거의 비슷하고 사용자와 상호 작용이 필요하지 않는 환경에는 +적합하며, 멀티프로그래밍이나 실시간 시스템에서는 부적합합니다.</p> +<br> +<br> +<h2 id="최단-작업-우선-스케줄링SJF" style="position:relative;"><a href="#%EC%B5%9C%EB%8B%A8-%EC%9E%91%EC%97%85-%EC%9A%B0%EC%84%A0-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81SJF" aria-label="최단 작업 우선 스케줄링SJF permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>최단 작업 우선 스케줄링(SJF)</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 579px; '> + <a class='gatsby-resp-image-link' href='/static/75036baf2fd74f4e76ba76af9b2afbb1/ff2d6/sjf.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 48.23529411764706%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABqklEQVR42nWSDXObMAyG85/zZ9b/tNwta5u0QIAFA+EjfNiYgA28k52FdddOdzrJWPdY0stmmjSmacKk9epqHFHkOQTnmOlOK2W/m6i1svXLsnzpm+xlj+J1j853ILw3cO8IcXqzuYm30IUMXHvfhx46um/jM4zN82zhJq5AkTAMnYCsruibGorypsiQ/PIh6yuKOEJ6DiCuJcUQVRJDXBILXAj0sBXYU6GxkcbUNJaxmsARO6PlLZI0RUqAlsaPCVaWOXh+sXW32w273Xd4nrt2vAKV3c8dmNH+GGOQvUQcM4KU4AYYU3f0SEVdj1QfRRG22y2enr79BbZpDDUMkG2LXghoyjPqJDx5yKm7gGJK0Ht+QpFSt39GNlM5jmMff4y9GQIH+uGhAxW8Yz57kO4BAwnQHH6g/LnDcDpiYT40CdUn0f93aEATQbRx/x6792dcn3fghz1GAvXOC0b/aB8d3VcIFq7ATyor2tMghVV6ECZ24GVB6jLU2QVtnoEXOepLas8FiyBJtAfw03+IL2yUElVGoKZBW1V2vwYiSZiGBFJ9/8+YH4G/AaG0+VESV7i8AAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/75036baf2fd74f4e76ba76af9b2afbb1/ff2d6/sjf.png' srcset='/static/75036baf2fd74f4e76ba76af9b2afbb1/e7570/sjf.png 170w, +/static/75036baf2fd74f4e76ba76af9b2afbb1/f46e7/sjf.png 340w, +/static/75036baf2fd74f4e76ba76af9b2afbb1/ff2d6/sjf.png 579w' sizes='(max-width: 579px) 100vw, 579px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>최단작업 우선 스케줄링(SJF)는 이전 FCFS방식에서 <strong>호위 효과</strong>를 억제하기 위해 사용하는 방식입니다.</p> +<p><strong>호위 효과</strong>는 실행시간이 긴 프로세스 때문에 다른 프로세스가 기다리는 시간이 길다는 문제가 있고, +이러한 문제를 실행시간이 짧은 프로세스를 먼저 시행되게 하여 해결하는 방식입니다.</p> +<p>그림을 통해 보면 FCFS방식의 평균 대기시간은 13ms인 반면에 SJF방식의 편균대기 시간은 3ms로 줄어든것을 +확인할 수 있습니다.</p> +<blockquote> +<p>즉 SJF방식은 호위효과를 줄여 프로세스들의 평균대기시간을 줄이는 방법으로 이해하면 됩니다.</p> +</blockquote> +<p>하지만, 이러한 방식도 문제가 있는데, 실행 시간이 긴 프로세스가 <strong>기아</strong>상태에 빠지기 쉽다는 것입니다.</p> +<p>이러한 방식은 평균 대기 시간을 중요하게 여기는 시스템에 적합하며, 실시간 시스템이나 사용자 대화형 시스템에 부적합하게 됩니다.</p> +<br> +<br> +<h1 id="선점-스케줄링" style="position:relative;"><a href="#%EC%84%A0%EC%A0%90-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="선점 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>선점 스케줄링</h1> +<br> +<br> +<h2 id="라운드-로빈-스케줄링" style="position:relative;"><a href="#%EB%9D%BC%EC%9A%B4%EB%93%9C-%EB%A1%9C%EB%B9%88-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="라운드 로빈 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>라운드 로빈 스케줄링</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 543px; '> + <a class='gatsby-resp-image-link' href='/static/f49a2b955fca3b0210b9c956b64ce2eb/10880/round_robin.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 57.64705882352942%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAAB+0lEQVR42o1TaU/bQBD1///aii9VP1a0tKIIEAWVthQokEaliBzOZeLER1zbiXHsxLdfZ7ZOKiGVMtJod/Z4OzPvrZSmKbIsA495nmNlZVmu/WH8mEu2bUPXdcznc0RRJECDIEBRFOIAjxzz+pMATdOAoigiQ7bpbIp2uyUeYPN9H7Lcwmw2E/HqoX8CGoaOycRAUWXgOLaIwzAUAK7rwjC0dfxfQNM0CWCy7h8DaNpYlM/meR5UVV3Hj5kAZDAG4dIYlHtqWRa8+3vklI3rOH9iAk7TbE0gz1eEsidJIu5LXo/6NejA7jQhdzq4vjxF7WALtcN3+H74HrNeGz7tT7st1D5so360jYv9NxhcnWGudOH3ZbjqHRx3ijiOISXdW+SDFsJuA822jPrJEc43n+PLq2e4ePsSpdpFTGfiXgPftl7gdHMDZ683oF1+Qq7IyPsNRMYYeSlqhrQcDZDoKry7PoajEeSbOhon+7j9eoDm+TGW4yEWqgKPMrk+3sXN5z38+LiD0c8rxPoIy2EfgWUSYEVKRnVz7fFygSggLXLvqCd5kiKiviVEBjPLPYrJi7IA31myZmld3OX1in2JM01JEpamYUIC94mAwP4Fg5i2SQGLSn8VjdXPKf/OH8pG/IY0gU/6c60JEsoyDQNMae4T+xll8tRvx4C/AZD/j93FiWifAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/f49a2b955fca3b0210b9c956b64ce2eb/10880/round_robin.png' srcset='/static/f49a2b955fca3b0210b9c956b64ce2eb/e7570/round_robin.png 170w, +/static/f49a2b955fca3b0210b9c956b64ce2eb/f46e7/round_robin.png 340w, +/static/f49a2b955fca3b0210b9c956b64ce2eb/10880/round_robin.png 543w' sizes='(max-width: 543px) 100vw, 543px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>라운드 로빈 스케줄링은 선입 선처리 방식(FCFS)방식에서 <strong>타임 슬라이스</strong>가 더해진 방식입니다. +여기서 말하는 <strong>타임 슬라이스</strong>는 CPU를 사용할 수 있는 정해진 시간을 의미합니다.</p> +<p>그림에서처럼 타임 슬라이스가 4ms이면 한번에 4ms까지 CPU를 할당받을 수 있고, 그 이후는 큐 가장 뒤로 들어가며 +콘텍스트 스위칭이 일어나게 됩니다.</p> +<br> +<blockquote> +<p>라운드 로빈 방식의 중요한 포인트는 <strong>슬라이스 크기</strong>입니다.</p> +</blockquote> +<p>만약 슬라이스 크기가 지나치게 크다면 <strong>FCFS</strong>방식과 다를게 없을 것이고, 지나치게 작다면 콘텍스트 스위칭으로 인한 +오버헤드가 많이 발생할 것입니다.</p> +<br> +<br> +<h2 id="최소-잔여-시간-우선-스케줄링-SRT" style="position:relative;"><a href="#%EC%B5%9C%EC%86%8C-%EC%9E%94%EC%97%AC-%EC%8B%9C%EA%B0%84-%EC%9A%B0%EC%84%A0-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81-SRT" aria-label="최소 잔여 시간 우선 스케줄링 SRT permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>최소 잔여 시간 우선 스케줄링 (SRT)</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 486px; '> + <a class='gatsby-resp-image-link' href='/static/02f21191a2da2c9fc6816ec2ffc574ab/c42ee/srt.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 50.588235294117645%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABeklEQVR42l2SZ6oCQRCE9/6HUPEWggGMf1ZBEUEwhzXnHOvxNcwgb6Dobaa7prp6g8PhoPF4rEqlonK5rGq1qtlspvP5rOPxaPF0Otk3cbvdqtVqqV6vq9lsar1eC479fm8Ivt+vOLfbTYPBQJfLRe/3W5/PR5vNRtPpVFEUWQ52u50RXK9XPZ9PuX53POHr9dJoNLIXKaYJVShySlerlal/PB5aLBaeDAGekIblcukJGD+Xy6nX66lYLKrf71skT6fT6nQ6KpVKCsPQalHfbrdNDI8EqGFMxqWJy1gsZj7F43GLyWTS/EokEmo0GpbXajVT3e127RtyBAX4wsGvyWRi4/IqFjAeERvu97uNj9dE1LiDr258T0gTRaj93bDb7i+ogeQ/IQicoc58igGKAIocyJmECdj+fD43EUTIEOe3TOJ+F34HmvCVRsD4+AQx92yaCLDFbxlTAQtho5CwmHw+b9suFArKZDJKpVLKZrN2NxwOrdaBXsfzB44H6uZXmOBJAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/02f21191a2da2c9fc6816ec2ffc574ab/c42ee/srt.png' srcset='/static/02f21191a2da2c9fc6816ec2ffc574ab/e7570/srt.png 170w, +/static/02f21191a2da2c9fc6816ec2ffc574ab/f46e7/srt.png 340w, +/static/02f21191a2da2c9fc6816ec2ffc574ab/c42ee/srt.png 486w' sizes='(max-width: 486px) 100vw, 486px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>최단 작업 우선 알고리즘(SJF) 그리고 라운드 로빈 알고리즘을 합친 형태입니다. +즉 작업 시간이 짧은 프로세스를 먼저 실행하되, 타임슬라이스 보다 큰 프로세스는 다시 큐 뒤로 보내고 작업을 이어가는 방식입니다.</p> +<p>위 알고리즘은 특이한 점이 있어서 상세히 설명하겠습니다.</p> +<br> +<h3 id="SRT-동작-방식" style="position:relative;"><a href="#SRT-%EB%8F%99%EC%9E%91-%EB%B0%A9%EC%8B%9D" aria-label="SRT 동작 방식 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>SRT 동작 방식</h3> +<ol> +<li>새로운 프로세스가 도착하면 그 프로세스의 남은 실행 시간을 계산합니다</li> +<li>준비 큐에 있는 프로세스 중에서 현재 실행 중인 프로세스를 포함하여 가장 짧은 실행 시간을 가진 프로세스에 CPU를 할당합니다</li> +<li>만약 새로운 프로세스가 도착하고 현재 실행 중인 프로세스 보다 남은 실행 시간이 더 짧다면 현재 프로세스는 중단되고 CPU는 새 프로세스에 할당되는 '선점'이 발생합니다.</li> +<li>선점이 발생하면 운영체제는 콘텍스트 스위칭으로 CPU자원을 현재 프로세스에서 새 프로세스로 교체합니다.</li> +<li>선점된 프로세스는 준비 큐로 이동합니다.</li> +</ol> +<br> +<p>SRT또한 SJF와 비슷한 장 단점을 공유하는데, 평균 대기 시간을 최소화 하는 장점을 가지지만, 작업 시간이 긴 +프로세스는 CPU 할당을 받기 어렵다는 단점이 있습니다.</p> +<br> +<br> +<h2 id="우선-순위-스케줄링" style="position:relative;"><a href="#%EC%9A%B0%EC%84%A0-%EC%88%9C%EC%9C%84-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="우선 순위 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>우선 순위 스케줄링</h2> +<hr> +<p>우선순위 스케줄링은 우선순위를 부여하고, 가장 높은 우선순위를 가진 프로세스부터 실행하는 알고리즘 입니다. +만약 같은 우선순위가 있다면 선입 선처리로 처리 됩니다.</p> +<p>이러한 우선순위 알고리즘 방식은 기아(Starvation) 현상을 동반하며 이는 에이징 방식으로 해결가능 하다고 이전 파트에서 설명했으니 +넘어가겠습니다.</p> +<h2 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h2> +<hr> +<p><a href="https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard">이미지 출처</a></p> +<p><a href="https://devshovelinglife.tistory.com/977">SRT 출처</a></p><![CDATA[선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법]]>https://catch-npe.netlify.app/jc13/https://catch-npe.netlify.app/jc13/Tue, 16 Sep 2025 00:00:00 GMT<h2 id="선점형-비선점형-개요" style="position:relative;"><a href="#%EC%84%A0%EC%A0%90%ED%98%95-%EB%B9%84%EC%84%A0%EC%A0%90%ED%98%95-%EA%B0%9C%EC%9A%94" aria-label="선점형 비선점형 개요 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>선점형? 비선점형? 개요</h2> +<hr> +<p><strong>CPU 스케줄링</strong>은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다.</p> +<p>여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다.</p> +<br> +<br> +<h2 id="선점형-스케줄링" style="position:relative;"><a href="#%EC%84%A0%EC%A0%90%ED%98%95-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="선점형 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>선점형 스케줄링</h2> +<hr> +<blockquote> +<p>선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다.</p> +</blockquote> +<p>즉, 어떤 프로세스가 CPU라는 자원을 사용하고 있음에도 운영체제가 CPU를 사용중인 프로세스로부터 자원을 강제로 빼앗아 다른 프로세스에 할당할 수 있는 +스케줄링 방식을 의미합니다.</p> +<p>다르게 표현한다면 어떠한 프로세스도 CPU를 독점할 수 없다는 말입니다.</p> +<p>선점형의 예시중 하나는 지금까지 보았던, 특정 주기마다 CPU에 대한 할당 권한을 다른 프로세스에게 넘겨주는 방식이 있습니다.</p> +<br> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 571px; '> + <a class='gatsby-resp-image-link' href='/static/019e69e3d46116a8e11fb9b81b109006/503dd/preemptive.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 40.588235294117645%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABNUlEQVR42m2STXKCQBCFuas5BlVegoNEF5JFXMaNWbkgq5hIEPkZEAsEVORlXltjUZZd9Wp+uvubnp6x+r7H9Xq9y6w5PvMN99u2FTVNIyP3LDqNPYMNzezTTqcT6rpGFEWI41ig5/MZFpM4uVyoiwRzTXVdh6LYo6oqZJnSSfUdTODhcEAQBAjDEGVZSr6VZRkcx4Ft21gsPqCUwmq1gud5EhiGga4ixHb7J2ADZDJzGZ+mqT64EJ/FksfjMUYvI8zcGd7nc0ymU7hvLl4nE6zX37oKX3Q83oCmLYQplWhgLDcQYKtL9748LD+X0g9TAY1V7Pe57lWFJInkigZIo2+z+YHv/yLPsxtw+CgmeCg2m1eleADDzeMQWBS5hildzO4GfAQMv8bjYY8+fpWqKkV8cQL/AZCaY4zcYIbMAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/019e69e3d46116a8e11fb9b81b109006/503dd/preemptive.png' srcset='/static/019e69e3d46116a8e11fb9b81b109006/e7570/preemptive.png 170w, +/static/019e69e3d46116a8e11fb9b81b109006/f46e7/preemptive.png 340w, +/static/019e69e3d46116a8e11fb9b81b109006/503dd/preemptive.png 571w' sizes='(max-width: 571px) 100vw, 571px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<br> +<h2 id="비-선점형-스케줄링" style="position:relative;"><a href="#%EB%B9%84-%EC%84%A0%EC%A0%90%ED%98%95-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="비 선점형 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>비 선점형 스케줄링</h2> +<hr> +<p>비선점형 스케줄링이란 하나의 프로세스가 자원을 사용하고 있다면 그 프로세스가 종료되거나 +스스로 대기 상태에 접어들기 전까진 다른 프로세스가 끼어들 수 없는 스케줄링입니다.</p> +<p>다르게 표현한다면 특정 프로세스가 CPU를 사용하기 시작했다면 자원 사용을 독점할 수 있는 방식입니다.</p> +<br> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 586px; '> + <a class='gatsby-resp-image-link' href='/static/1032a2fbc33a2d4ef8bfa25afecab649/52581/non_preemptive.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 36.47058823529412%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAABEElEQVR42n1RW26DMBDMMblTc4iSSjS/HID+IX5obgBChIcoTxsob6ZeR6A2qTLSyLv27uxofVjXFc/YdR3CMITrumjbFsuyPK0/bAFhi6lpmiYZk0iappJ1zR8EfkMKUmDbNlRVhWEYGIZBNNZwHAd9P6AsC8EMVVUI0QTzPP8ZTPXjOMqTcimoqq9QFAXH4wssy8L7+Qxd16FpGkzTRBBc4Xku8jzbBQnkPooCMTAXa7kKA91N8HL5xOntBOPDEE4qcOGwaRowzoWrL5RVDsYKxHG0r4LQ9z183xPDHPEWSqcPO7wHNXHOJBlj+6cQ6MOSJJYOg8AX+fdNkIo2/pffL367I0e0Y8YqZFkqHf4AIlcVSpteYeAAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/1032a2fbc33a2d4ef8bfa25afecab649/52581/non_preemptive.png' srcset='/static/1032a2fbc33a2d4ef8bfa25afecab649/e7570/non_preemptive.png 170w, +/static/1032a2fbc33a2d4ef8bfa25afecab649/f46e7/non_preemptive.png 340w, +/static/1032a2fbc33a2d4ef8bfa25afecab649/52581/non_preemptive.png 586w' sizes='(max-width: 586px) 100vw, 586px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<br> +<h2 id="선점-비선점의-장-단점" style="position:relative;"><a href="#%EC%84%A0%EC%A0%90-%EB%B9%84%EC%84%A0%EC%A0%90%EC%9D%98-%EC%9E%A5-%EB%8B%A8%EC%A0%90" aria-label="선점 비선점의 장 단점 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>선점, 비선점의 장 단점</h2> +<hr> +<p>대부분의 운영체제는 <strong>선점형 스케줄링</strong>를 사용중입니다. 그럼에도 <strong>비선점형 스케줄링</strong>를 사용하는 곳이 있는데 그것은 각자의 장 단점이 존재하기 때문입니다.</p> +<br> +<ul> +<li>선점형 스케줄링 장점</li> +</ul> +<blockquote> +<p>선점형 스케줄링은 어는 한 프로세스의 자원 독점을 막고 프로세스들에 골고루 자원을 분배 할 수 있다는 장점이 있습니다.</p> +</blockquote> +<br> +<ul> +<li>선점형 스케줄링 단점</li> +</ul> +<blockquote> +<p>콘텍스트 스위칭이 빈번하기 떄문에 오버헤드가 많이 발생합니다.</p> +</blockquote> +<br> +<br> +<ul> +<li>비 선점형 스케줄링 장점</li> +</ul> +<blockquote> +<p>상대적으로 선점형 보다 콘텍스트 스위칭에 대한 오버헤드가 작게 발생합니다.</p> +</blockquote> +<br> +<ul> +<li>선점형 스케줄링 단점</li> +</ul> +<blockquote> +<p>하나의 프로세스가 작업이 끝나기를 기다려야 하기 때문에, 모든 프로세스가 골고루 자원을 사용할 수 없습니다.</p> +</blockquote> +<br> +<br> +<h2 id="기아-상태Starvation" style="position:relative;"><a href="#%EA%B8%B0%EC%95%84-%EC%83%81%ED%83%9CStarvation" aria-label="기아 상태Starvation permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>기아 상태(Starvation)</h2> +<hr> +<p>기아 상태란 우선순위가 밀린 프로세스가 영원히 자신의 우선순위까지 순서가 오지 못해 실행되지 못하는 상태를 기아 상태라고 합니다.</p> +<br> +<br> +<h2 id="기아-상태-해결법" style="position:relative;"><a href="#%EA%B8%B0%EC%95%84-%EC%83%81%ED%83%9C-%ED%95%B4%EA%B2%B0%EB%B2%95" aria-label="기아 상태 해결법 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>기아 상태 해결법</h2> +<hr> +<p>이러한 기아 상태를 해결하기 위한 방법으로는</p> +<p><strong>에이징</strong> 기법을 활용하는 것입니다.</p> +<p>기아 상태가 발생하는 이유는 항상 자신보다 높은 우선순위를 가지는 프로세스가 존재하기 떄문입니다.</p> +<p><strong>에이징</strong> 기법은 준비큐에서 대기가 길어진 프로세스들에게 우선순위를 조금씩 높여주는 방식을 사용합니다. +결국 조금씩 우선순위가 높아진다면 언젠가는 해당 프로세스가 실행될 수 있게 됩니다.</p><![CDATA[CPU 스케줄링의 목적과 스케줄러의 종류]]>https://catch-npe.netlify.app/jc12/https://catch-npe.netlify.app/jc12/Mon, 15 Sep 2025 00:00:00 GMT<h2 id="CPU-할당" style="position:relative;"><a href="#CPU-%ED%95%A0%EB%8B%B9" aria-label="CPU 할당 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>CPU 할당?</h2> +<hr> +<p>지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용 +하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등 +CPU사용에 여러 변수가 있습니다.</p> +<p>한가지 의문점은, 누가? 어떻게? CPU를 할당하는지 배운적은 없습니다. +여기서 CPU라는 리소스에 대한 사용을 결정짓는건 운영체제입니다. +그리고 오늘 글의 주제인 CPU 스케줄링은 운영체제가 CPU라는 자원을 배분하는 행위를 지칭합니다.</p> +<br> +<br> +<h2 id="CPU-스케줄링-우선순위" style="position:relative;"><a href="#CPU-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84" aria-label="CPU 스케줄링 우선순위 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>CPU 스케줄링 우선순위</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 597px; '> + <a class='gatsby-resp-image-link' href='/static/b2ebb8e3955c71f997f6f3f664eaae42/f523d/priority.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 37.05882352941176%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAABDElEQVR42oVRi06EQAzk/3/J+BPCKULgQOQReR0LHG9GpmaJucTYZEN3285MB2NZFjRNg7quoZRC27aSz/MMxr7vch7zv+7GNE2I4xiWZcF1XZimiTAMMQzDOTCOI4qikC+DpFVVYV1XOVqMALKJDQTxfB9BEIhiAjI4kOdfSJLPAzQHBaRpgjiJZI6HtSxLhNDgANfujkKWpgLEdbdtOwF934Ntvwow68xd9x1d1wnJ5fKC69UTMkN7cG9uiO03edR+MEjGZs9zUJblAXiH49jy9gNYCHgUfUivoZVUYYDg+QnzcdfeaVD6o1QjardtF//6vpctuA2JKEQ8PBW2CvXhjah7AP3vL/+ufwNqWhr42zV1RgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/b2ebb8e3955c71f997f6f3f664eaae42/f523d/priority.png' srcset='/static/b2ebb8e3955c71f997f6f3f664eaae42/e7570/priority.png 170w, +/static/b2ebb8e3955c71f997f6f3f664eaae42/f46e7/priority.png 340w, +/static/b2ebb8e3955c71f997f6f3f664eaae42/f523d/priority.png 597w' sizes='(max-width: 597px) 100vw, 597px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>운영체제는 많은 프로세스에게 공정하게 CPU라는 공용자원을 배분하기 위해 고려해야 하는것이 우선순위 입니다. +우선순위라는 기준을 매겨야 하는 이유는 +운영체제는 어떤 프로세스는 당장 처리해야 할 중요성을 띄거나, IO작업이 많거나, CPU 사용시간 자체가 길거나처럼 각자의 사정이 있고, 이 사정 가운대 효율적으로 자원을 배분해야 하기 떄문입니다.</p> +<br> +<p>'우선순위가 높다'라는 표현은 CPU 사용에 우선권을 가집니다. 즉 먼저 처리되어야 한다 라는 뜻입니다. +대표적으로 우선순위가 높은 프로세스는 입출력이 많은 프로세스 입니다. +(입출력 처리가 많은 프로세스가 우선순위가 높은 이유는 아래에서 설명합니다.)</p> +<p>대부분의 프로세스는 I/O 작업과 CPU처리를 번갈아가면서 수행하게 됩니다. 이 말은 프로세스 상태 변화에서 실행, 대기를 번갈아 가면서 사용한다는 뜻입니다. +그렇지만 모든 프로세스가 동일한 비율로 I/O와 CPU처리를 하는것은 아닙니다. 여기서 CPU작업의 비율이 많다면 <strong>CPU 집중 프로세스</strong>라고 하게 되며, 반대로 I/O작업의 +비율이 많다면 <strong>입출력 집중 프로세스</strong> 라고 부르게 됩니다.</p> +<p>CPU집중 프로세스는 실행상태가 많고, 입출력 집중 프로세스는 대기 상태가 많으니 입출력 집중 프로세스를 빠르게 대기 상태로 넘겨주는 것이 CPU사용에 대해서 더 효율적인 +방법일것입니다. 그렇기 떄문에 입출력 처리가 많은 프로세스가 우선순위가 높습니다.</p> +<p>여담으로, CPU를 이용하는 작업을 <strong>CPU 버스트</strong>, 입출력을 이용하는 작업을 <strong>입출력 버스트</strong>라고 부르게 됩니다.</p> +<br> +<br> +<p>이러한 우선순위는 <strong>PCB</strong>에 기록됩니다. <strong>PCB</strong> 우선순위 기준으로 먼저 처리할 프로세스를 결정하고 처리하게 됩니다.</p> +<br> +<br> +<h2 id="스케줄링-큐" style="position:relative;"><a href="#%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81-%ED%81%90" aria-label="스케줄링 큐 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>스케줄링 큐</h2> +<hr> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/487f1969f3212e6cb8eb342f675e2459/9490d/queue_scheduling.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 64.11764705882354%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAACHklEQVR42n1Ti27aQBDk/3+tapQCSQh1mogQMPh9vrcf09kLtKmU1JJlfN6dnZ0ZFuMwwJxPcMUZvirgTjlc12IGME8zpnmGtQ5d3yOOI6ZpglzROVjW+pJ9ZQEjv43BYvAePnuAvbtFffsNw3YNmx8gbWMM0K/PyO+W2N1+h3nOYKsSgcCmLjH8vEe3ukG3vkHY3sE1NRZjCATcwPNAP6wQNkuYwx4+DrBdB/UrQ08Guq7SIP32isP5DFWcMJCIeVjCPpLEZgVbE1BWiLqH5mR5etUhcB3DOwaPZveCmnI0BC33r9AE0txqiBHB6NSj+N2QndQv5nlOmohOI1fxbYNANvqcwxY5FJ/BWgzepcb+eEB3fIOj3pZ1Auw4/KrtOyBvx6ZeKdjsEZ5rizZJz7cdjUm1CAQZL7qZ+x+IXFlxTWssJpIRrAQ4E10mCKh52lLgNfVcIsqTK08XRHE0ElC+uc06mdk3TUrCfLkXEo35w8FI6xVjZKhpdzrCqvZdL5oXrIGmlp6x0mWZTJDYIUVs+sDwoqM0lVWFioXCyos+IaazQ56jZRYtDZFqzcFy3vNs/ofhh5eB0ywL27Z9fyegpXslo7J/yhI7RwC5jNYJTEh8CfjXcYtI8CDrb+9RM6fFluF/yaD2u/SPEcBr/X8Br0wD2fleoWGwFZv1RduOJjnRk5n7rPdTwD+TyaSnMZI/RRNaZtBQ3+v1GeBvvN7nwQjISfkAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/487f1969f3212e6cb8eb342f675e2459/ca1dc/queue_scheduling.png' srcset='/static/487f1969f3212e6cb8eb342f675e2459/e7570/queue_scheduling.png 170w, +/static/487f1969f3212e6cb8eb342f675e2459/f46e7/queue_scheduling.png 340w, +/static/487f1969f3212e6cb8eb342f675e2459/ca1dc/queue_scheduling.png 680w, +/static/487f1969f3212e6cb8eb342f675e2459/9490d/queue_scheduling.png 687w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>우선순위는 <strong>PCB</strong>에 기록되지만, 운영체제가 매 CPU 할당 과정마다 <strong>PCB</strong>를 확인하고 결정하는건 비효율 적인 방식입니다. +그렇기 때문에 프로세스는 마치 '줄을 서는것'처럼 대기하게 됩니다. 이것을 <strong>스케줄링 큐</strong>라고 부르게 됩니다.</p> +<br> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 553px; '> + <a class='gatsby-resp-image-link' href='/static/c0ffb8068b6641fd3a68af30a2c70b99/d35da/ready_queue.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 62.94117647058823%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAABuUlEQVR42pWSWW/CQAyE8///VCVUVX2vVBXISchNDiCcSZh6TDeCSDx0JWujeD3rb9bW7XbDf4PrcrkgSRJkWaYRhiHquob1quB8PiOOI0RRhDiJtSDLUvi+hzzPZfeRpin2+z02mw12u52GZQSmgm3bIlj5sO0lgsCHH3hwXQeuZ8NxbKwkV5alnj2dTmMT1vV61R9936vYMAyarOoK62gFx7VFxFUxCodhoILcaznD84fDQWupY+VFIZ2sxltMl13X43g8Shx0ZxGDiIXUxHGsHhKXFhC/aRpYjfiTSgdTH9k5C1lQVaX6x0uJRfO3260+BvMUo2hVVbDi7y8sPj9w7Qe2NyLTQ/o1X/wIrg3bWajpXdfpCxvveDkJRg+j9xmK2Zv+GMRHI8j26aHrOfCEgJ4Zr40gd+PdKFhsSiRp9uSfSbJLot2jGZEZRKWPRCU6sRWZndATdvboIdGYM/PFMxQknhHkbFJQZ1XEVRB/azqHfFHfd7FczmUG7/PYtvsnZApzPXloxB6FuYgZiYeeeEjh9TrUQpJwAl4+Cm+bBguIm8hIraNQxRi8hPjM8ZuI3InP+eT3L10Y5OBy17vlAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/c0ffb8068b6641fd3a68af30a2c70b99/d35da/ready_queue.png' srcset='/static/c0ffb8068b6641fd3a68af30a2c70b99/e7570/ready_queue.png 170w, +/static/c0ffb8068b6641fd3a68af30a2c70b99/f46e7/ready_queue.png 340w, +/static/c0ffb8068b6641fd3a68af30a2c70b99/d35da/ready_queue.png 553w' sizes='(max-width: 553px) 100vw, 553px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p>운영체제는 메모리로 적재되고 싶은 프로세스들을 큐에 삽입하여 줄을 세우고, CPU를 사용하고 싶거나, 특정 입출력장치를 사용하거 싶은 프로세스들을 줄세웁니다. +이 과정에서 사용할 자원에 따라 다른 큐에서 대기하게 됩니다.</p> +<p>운영체제가 관리하는 큐로는 <strong>준비큐</strong>와 <strong>대기큐</strong>로 이루어 져 있습니다. <strong>준비 큐</strong>는 말그대로 CPU를 이용하고 싶은 프로세스들이 대기하게 되고,</p> +<br> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 609px; '> + <a class='gatsby-resp-image-link' href='/static/76d39a23f0a57bdca9776b2d8f1cb0e5/71467/wait_queue.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 48.23529411764706%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB+0lEQVR42m2SWXPaQBCE9f9/S17ykpekKo4xNghzROYWINsIc0hISFodgMSXEQbHqcpWTWl3tdM9PT3a6XTicxyPBw5ZRr7fkx/2bDcblrZNFscc0pR9Ep//X98XRXGO61n7AJPLckWrBctahVnlJ3a9wrat43ceibodslGXbGDgmUNyyeEa5bpgaFeGIs8pfyUCGEiC4zj4riMVrvFk765WNPQ601aD+HlyBjwWJwKl2Po70v2BXM7aO/hfJvVmo8w+kbMhWq/w7Dm7twX+Ys5TQ+e1pZO+WiSxQk2E2Gjxqj9QzC3GDxU0z/MIw5Cd7xNJnzKpKOhI4sOtSL7D//1IMjRIh11yy+Q0GRALYBoEhCLft6ZY7SbrvkHv+zc0w5BNr4dpmvQGwjgZEc1MtiVJEOJsPRwhXYk5v6r3DPQaSkBcqXrZNYhUTKfTplq5Rf/6BS0V55RcHsRVlaTEIjmW5u/mzwQvMzwBD+UbvVhYnSbuUwt/3CfwPaLnKX4Z1gQl7/vV208uX3q4d8SEdh27WeOtVWfZrJ+lKSFJRW4xHeCN+uf2lKsoc0sfyr3Eh8ul5eVlurSJpmN2UnUYvTu4dl3u7u/5cXODUauyEiNUklwAL7mXmfxnDkvATEZlJ5JckelIr9aTMZupybzfxZKeLYw27mUOT/+JP7Nx7U2XJw+qAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/76d39a23f0a57bdca9776b2d8f1cb0e5/71467/wait_queue.png' srcset='/static/76d39a23f0a57bdca9776b2d8f1cb0e5/e7570/wait_queue.png 170w, +/static/76d39a23f0a57bdca9776b2d8f1cb0e5/f46e7/wait_queue.png 340w, +/static/76d39a23f0a57bdca9776b2d8f1cb0e5/71467/wait_queue.png 609w' sizes='(max-width: 609px) 100vw, 609px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<br> +<p><strong>대기 큐</strong>는 +입출력장치를 이용하기 위한 대기 상태에 돌입한 프로세스들이 서는 줄입니다. +큐에 들어와 있다고 해도 항상 순서대로 작동하는 것은 아니고 <strong>우선 순위</strong>를 고려합니다.</p> +<br> +<h2 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h2> +<hr> +<p><a href="https://www.inflearn.com/course/%ED%98%BC%EC%9E%90-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EC%BB%B4%ED%93%A8%ED%84%B0%EA%B5%AC%EC%A1%B0-%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C/dashboard">이미지 출처</a></p><![CDATA[멀티 쓰레드 프로그래밍의 동시성 이슈와 Thread-Safe 설계 방법]]>https://catch-npe.netlify.app/jc11/https://catch-npe.netlify.app/jc11/Sun, 14 Sep 2025 00:00:00 GMT<h2 id="동시성-이슈란" style="position:relative;"><a href="#%EB%8F%99%EC%8B%9C%EC%84%B1-%EC%9D%B4%EC%8A%88%EB%9E%80" aria-label="동시성 이슈란 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>동시성 이슈란?</h2> <hr> <br> -<p><img src="%EB%8F%99%EC%8B%9C%EC%84%B1%EC%9D%B4%EC%8A%88.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/176c5779bddf624de2337676780fb617/42a19/concurrency.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 80.58823529411765%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsTAAALEwEAmpwYAAACEUlEQVR42n1Ua5eiMAyd///n/OK8POoiIA95Q6G0Be4mVViY0c05EdsmNzdpkzc8ZJomq+M42rWUEqfTCZ7nwfd9XC4XuK6Lw+GAruusDduyz1re5oM0Ta1jURTLIe87joPdboeqqpZ9rTWiKML1eoUQYiG0AA7DgCRJyPkPsiyDMQZKKet4PB6x3+9tIEN2ivb6vrfBfd9D2z4BZANjNOpaQPYaZRyjCAIybtE0jWUnyaYIQpTEjFPmABzwp9wBZQ9ROWird2iVYSBQQzUczADZSQvMrA0B8T7/F6JD1+aQ4htGhT8AKbruU5T5EVUZE6MaWZ5DUDplWSyXsL4ApTQFFxh0ZElsANmB6QshoZmVvLMKsgDn6IyyLqnOI3ra64ryYStgXqVs06EaKtVvDluqk0hSiPx+IZoDUz3NL8BpCzjfNKe+lo6A2lsK1bTzY12lrCyRpwxfAc5vjp0XwAfoa8CHwStAdpwBp/8xfATbMFyYrOReX/OUOfs8YUj9mGaY4hTjLcFENTNRDHUN0XlXhPsP3D6/UZzotklNGGOMbhjju+2idHnUqwRIPyMvMurhvLSqyaG5eKgdF9HnF8KPL+THE+nZBmld3wIiyf4pkbKAXJeU+jjn4UDTxPdcZLRu6Hn09B43z4LrxNOIsrLftc69zIAdOQZhiAsB8phySGPq53k8jTza5hG3eXW/5S9FatzAC6DMCwAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/176c5779bddf624de2337676780fb617/ca1dc/concurrency.png' srcset='/static/176c5779bddf624de2337676780fb617/e7570/concurrency.png 170w, +/static/176c5779bddf624de2337676780fb617/f46e7/concurrency.png 340w, +/static/176c5779bddf624de2337676780fb617/ca1dc/concurrency.png 680w, +/static/176c5779bddf624de2337676780fb617/02d09/concurrency.png 1020w, +/static/176c5779bddf624de2337676780fb617/42a19/concurrency.png 1024w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <br> <p>동시성 이슈란 하나의 자원에 대해 여러 스레드가 접근할때 발생합니다.</p> <p>예를 들어, 좋아요가 10 인 자원에 대해 스레드 a와 b가 동시에 접근해서 좋아요 10에 대한 값을 가져옵니다. 스레드 a는 좋아요 카운트를 하나 늘리는 행위를 하고 스레드 b는 좋아요 카운트를 하나 줄이는 행위를 할때 스레드 a가 좋아요 카운트를 늘리면 11가 됩니다. 하지만 스레드 a와 b는 좋아요 카운트에 동시에 접근해서 초기값 10을 받은 상태라면 스레드 b는 늘어난 11라는 숫자대신 10을 기준으로 값을 줄이게 됩니다. 그럼 최종 결과는 10이 아닌 9라는 값으로 나오게 됩니다.</p> -<p>이처럼 멀티 스레드 환경에서는 하나의 자원에 동시에 접근하게 되면 이러한 문제가 발생할 수 있다.</p> +<p>이처럼 멀티 스레드 환경에서는 하나의 자원에 동시에 접근하게 되면 이러한 문제가 발생할 수 있습니다.</p> <br> <br> <h2 id="스레드-안전" style="position:relative;"><a href="#%EC%8A%A4%EB%A0%88%EB%93%9C-%EC%95%88%EC%A0%84" aria-label="스레드 안전 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>스레드 안전</h2> <hr> <p>그럼 우리가 추구해야 할 문제는 스레드 안전한 멀티 스레드 프로그래밍을 구현할 수 있어야 한다. 이것을 구현하는 -방법에 대해 이야기 하려고 한다.</p> +방법에 대해 이야기 하려고 합니다.</p> <br> <br> <h2 id="스레드-안전-여부-판단" style="position:relative;"><a href="#%EC%8A%A4%EB%A0%88%EB%93%9C-%EC%95%88%EC%A0%84-%EC%97%AC%EB%B6%80-%ED%8C%90%EB%8B%A8" aria-label="스레드 안전 여부 판단 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>스레드 안전 여부 판단</h2> @@ -34,7 +1586,7 @@ </ol> <br> <ul> -<li>공유 자원에 하나의 Thread만 접근할 수 있도록 세마포어/ 뮤텍스락을 통제하는 방법이다.</li> +<li>공유 자원에 하나의 Thread만 접근할 수 있도록 세마포어/ 뮤텍스락을 통제하는 방법입니다.</li> </ul> <br> <ol start="2"> @@ -42,12 +1594,12 @@ </ol> <br> <ul> -<li>공유 자원에 접근할 때 원자 연산을 이용하거나 원자적으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현하는 방법이다.</li> +<li>공유 자원에 접근할 때 원자 연산을 이용하거나 원자적으로 정의된 접근 방법을 사용함으로써 상호 배제를 구현하는 방법입니다.</li> <li>Atomic <ul> <li>공유 자원 변경에 필요한 연산을 원자적으로 분리한 뒤에 실제로 데이터의 변경이 이루어지는 시점에 Lock을 걸고,</li> </ul> -데이터를 변경하는 시간 동안 다른 쓰레드의 접근이 불가능하도록 하는 방법이다.</li> +데이터를 변경하는 시간 동안 다른 쓰레드의 접근이 불가능하도록 하는 방법입니다.</li> </ul> <br> <ol start="3"> @@ -55,8 +1607,8 @@ </ol> <br> <ul> -<li>공유 자원의 사용을 최대한 줄이고 각가의 쓰레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는 방법이다.</li> -<li>일반적으로 공유 상태를 피할 수 없을 때 사용하는 방식이며, 전역 변수 사용을 자제하라는 뜻으로 생각하면 된다.</li> +<li>공유 자원의 사용을 최대한 줄이고 각가의 쓰레드에서만 접근 가능한 저장소들을 사용함으로써 동시 접근을 막는 방법입니다.</li> +<li>일반적으로 공유 상태를 피할 수 없을 때 사용하는 방식이며, 전역 변수 사용을 자제하라는 뜻으로 생각하면 됩니다.</li> </ul> <br> <ol start="4"> @@ -64,24 +1616,34 @@ </ol> <br> <ul> -<li>쓰레드 호출과 상관 없이 프로그램에 문제가 없도록 작성하는 방법이다.</li> -<li>어떤 함수가 한 스레드에 의해 호출되어 실행 중이라면 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 옳바르게 주어져야 한다.</li> -<li>쓰레드끼리 독립적으로 동작할 수 있도록 코드를 작성하는 것으로 생각하면 된다.</li> +<li>쓰레드 호출과 상관 없이 프로그램에 문제가 없도록 작성하는 방법입니다.</li> +<li>어떤 함수가 한 스레드에 의해 호출되어 실행 중이라면 다른 스레드가 그 함수를 호출하더라도 그 결과가 각각에게 옳바르게 주어져야 합니다.</li> +<li>쓰레드끼리 독립적으로 동작할 수 있도록 코드를 작성하는 것으로 생각하면 됩니다.</li> </ul> <br> -<br><![CDATA[10. 멀티 프로세스와 멀티 쓰레드의 차이 및 장단점]]>https://catch-npe.netlify.app/10/https://catch-npe.netlify.app/10/Sat, 13 Sep 2025 00:00:00 GMT<p><img src="%EB%A9%80%ED%8B%B0%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4.png" alt="img.png"></p> -<p>멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술이다. +<br><![CDATA[멀티 프로세스와 멀티 쓰레드의 차이 및 장단점]]>https://catch-npe.netlify.app/jc10/https://catch-npe.netlify.app/jc10/Sat, 13 Sep 2025 00:00:00 GMT<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; '> + <a class='gatsby-resp-image-link' href='/static/dce47bab78e932f50f7ef763f2352112/dface/multi_process.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 50.588235294117645%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABoElEQVR42lVRx4pCQRB8/3813PSmHvSgggH1IIqiYkIFE4o55wimWqqWJ7sDzVSnqp5pYzabYTqdgrdp8/n8i5krFArI5/PCzPH+22P6zBnL5RL7/R7b7Ra73U622Wy+PvFkMlEDfTN+OBz+YRq5DILj8YhWqyW15/OJ6/WKbreL4XCI8/ksv9frYTQayX88HqpjTb/fV+zz+UhchKVSCY1GA+l0WgU8zWZTT329Xmqu1+sol8vKceJcLqeebDaLSqUizGmNy+WCVCqlQCQSkSpPrVZDMpkUpjrJMpmMfE7KWorG43EUi0X98el0+iVMJBKoVqsIBoNot9tqIgGLTUI2mAKDwQB+v19Th8NhTUsxEfLJTHAyKvE5JOCfUcR8cqfTUR3PYrFQLb+HwsxxB1yuwVWTeTweY71ea3O8aSTnRxOvVquvT8xBGGefuXEKGVTk1kh6v981He12u2n7xO/3+5/Pwxi3zxixeQz+hcPhgN1ul3m9Xng8HthsNlgsFrhcLrjdbvlWqxU+nw+xWAyBQABOp1O97IlGowiFQvgBYyLQlN0XsPsAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/dce47bab78e932f50f7ef763f2352112/dface/multi_process.png' srcset='/static/dce47bab78e932f50f7ef763f2352112/e7570/multi_process.png 170w, +/static/dce47bab78e932f50f7ef763f2352112/f46e7/multi_process.png 340w, +/static/dce47bab78e932f50f7ef763f2352112/dface/multi_process.png 600w' sizes='(max-width: 600px) 100vw, 600px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> +<p>멀티 프로세스는 운영체제에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 기술입니다. 보통은 하나의 프로그램을 실행하기 위해서 하나의 프로세스만 메모리에 생성하게 되지만, 부가적인 기능을 위해 -여러개의 프로세스를 생성하는 것이다.</p> +여러개의 프로세스를 생성하는 것입니다.</p> <br> <br> <h3 id="어떻게-멀티-프로세스를-생성할까" style="position:relative;"><a href="#%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%A9%80%ED%8B%B0-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%A5%BC-%EC%83%9D%EC%84%B1%ED%95%A0%EA%B9%8C" aria-label="어떻게 멀티 프로세스를 생성할까 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>어떻게 멀티 프로세스를 생성할까?</h3> <p>멀티 프로세스는 이전에 보았던 계층구조 프로세스 처럼 부모 프로세스가 -여러개의 자식 프로세스를 생성한다.</p> +여러개의 자식 프로세스를 생성합니다.</p> <p>부모 프로세스는 자식 프로세스의 PID를 알고있으며 자식또한 PID와 PPID를 알고있어 -서로 통신이 가능하다.</p> +서로 통신이 가능합니다.</p> <p>이런 성질은 각각 독립적이지만 통신이 가능하게 만들었고 멀티 프로세스의 대표적인 예가 -브라우저의 탭이라고 할 수 있다.</p> +브라우저의 탭이라고 할 수 있습니다.</p> <p>브라우저 탭은 문제가 발생해서 닫아야 하는 상황이여도 다른 탭까지 닫히지 않고 개별적으로 운용을 할 수 있는걸 기억해보면 독립적이란 말을 더 잘 이해할 수 있을것이다.</p> <br> @@ -91,10 +1653,10 @@ <ol> <li>안정성</li> </ol> -<p>멀티 프로세스의 안정성은 각각의 프로세스가 독립적이기 떄문에 가능하다. +<p>멀티 프로세스의 안정성은 각각의 프로세스가 독립적이기 떄문에 가능합니다. 대표적인 예로 좀전에 설명을 했던 특정 브라우저 탭이 문제가 발생하여 닫아야 하는 상황에서 -같은 브라우저의 다른 탭까지 닫히지는 않는다. -이런것이 독립적인 성격에 의한 안정성이라고 할 수 있다.</p> +같은 브라우저의 다른 탭까지 닫히지는 않습니다. +이런것이 독립적인 성격에 의한 안정성이라고 할 수 있습니다.</p> <br> <br> <h2 id="멀티-프로세스의-단점" style="position:relative;"><a href="#%EB%A9%80%ED%8B%B0-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EB%8B%A8%EC%A0%90" aria-label="멀티 프로세스의 단점 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>멀티 프로세스의 단점</h2> @@ -102,68 +1664,175 @@ <ol> <li>문맥교환 (Context Switching) Overhead</li> </ol> -<p>멀티 태스킹을 이루는 기술인 문맥 교환 과정에서 성능 저하가 발생할 수 있다. +<p>멀티 태스킹을 이루는 기술인 문맥 교환 과정에서 성능 저하가 발생할 수 있습니다. 프로세스를 컨텍스트 스위칭 하면, CPU는 다음 프로세스의 정보를 불러오기 위해 메모리를 검색하고, CPU 캐시 메모리를 초기화하며, 프로세스 상태를 저장하고, -불러올 데이터를 준비해야 하기 떄문에, 빈번한 문맥교환이 발생하고 이 비용은 곧 오버헤드로 발생할 수 있다.</p> +불러올 데이터를 준비해야 하기 떄문에, 빈번한 문맥교환이 발생하고 이 비용은 곧 오버헤드로 발생할 수 있습니다.</p> <br> <br> <ol start="2"> <li>자원 공유 비효율성</li> </ol> -<p>프로세스는 독립적인 메모리를 가지고, 멀티 프로세스는 독립적인 메모리 공간의 합일 것이다. -그렇기 때문에 메모리 비효율성을 초래한다.</p> +<p>프로세스는 독립적인 메모리를 가지고, 멀티 프로세스는 독립적인 메모리 공간의 합일 것입니다. +그렇기 때문에 메모리 비효율성을 초래합니다.</p> <br> <br> <h2 id="멀티-스레드" style="position:relative;"><a href="#%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C" aria-label="멀티 스레드 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>멀티 스레드</h2> <hr> -<p><img src="%EB%A9%80%ED%8B%B0%EC%8A%A4%EB%A0%88%EB%93%9C.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; '> + <a class='gatsby-resp-image-link' href='/static/4ea9ea45d75ae55d9a51bc2e57112be3/dface/multi_thread.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 70%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAACEklEQVR42o1TR4uiQRCdH68HFQ8KOuZ4MYPh4MGTilkx55ww54AI1vBq0J2d3Vm24fFVdVW/flXV39twOKTz+Uz7/Z4Oh8MfOB6PHL9cLgz4f8s7nU40nU7pbbPZENbj8aDv63a7UTqdpng8TuFwmJrNJt3vd/ppgfifhDg8mUxoMBhQv99n+78Ix+MxlctlqlQqVKvV2J7P5zSbzaher1Or1WLAxh5iyKlWqwycA8eLEJvBYJAUCgUZDAYKhULUbrcZZrOZxGIxSaVSslgs1Ol0mBwtgK/VaikajVKpVOL+MmGv16NUKkWJRIKSyST3DeWNRiPuHw7EYjEG9qAmm82+Yrlcjrrd7i9CTHG9XhPs1WpFi8Xi5T/jwNNHDsr+6iPOJW+3W/L5fFzW+/s7Wa1WstlspNFoGCKRiNsBIEelUnGpdrud43q9niQSCXm93k+FIPR4PCQUCjkZifB1Oh1fIBAIKBAIMGCr1epXDsjQc5x1u92fhLvdjlwuF9/WaDR4eplMhvL5PL87pVJJfr+fCTE0TBpT/ZqDs06nkx83EzocDr4NG5gs5GMA1+uVVaMlABRDBYaInEgkwo8fKqH6N0IogbpCofACfLlczmQgkMlk/DyKxSLH8YVaXPQixJSWyyWPHX8D/oon4GMf8WcO1H0HqsLUecpQZjKZ+AH/BKPRyIANJeg5eobKAPj4gucDIZK/8p95iE0AAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/4ea9ea45d75ae55d9a51bc2e57112be3/dface/multi_thread.png' srcset='/static/4ea9ea45d75ae55d9a51bc2e57112be3/e7570/multi_thread.png 170w, +/static/4ea9ea45d75ae55d9a51bc2e57112be3/f46e7/multi_thread.png 340w, +/static/4ea9ea45d75ae55d9a51bc2e57112be3/dface/multi_thread.png 600w' sizes='(max-width: 600px) 100vw, 600px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <br> -<p>이전에 보았던 것처럼 스레드는 하나의 프로세스 내에 있는 실행 흐름이다. -멀티 스레드는 하나의 프로세스 안에 여러개의 실행흐름을 가지는 것이다. -멀티 스레드 또한 멀티 프로세스 처럼 여러개의 작업을 동시 실행 할 수 있다.</p> -<p>이전에 보았던 것처럼 멀티 프로세스는 브라우저의 여러개의 탭을 통해 예시를 들었다. +<p>이전에 보았던 것처럼 스레드는 하나의 프로세스 내에 있는 실행 흐름입니다. +멀티 스레드는 하나의 프로세스 안에 여러개의 실행흐름을 가지는 것입니다. +멀티 스레드 또한 멀티 프로세스 처럼 여러개의 작업을 동시 실행 할 수 있습니다.</p> +<p>이전에 보았던 것처럼 멀티 프로세스는 브라우저의 여러개의 탭을 통해 예시를 들었습니다. 하지만, 멀티 스레드는 같은 브라우저라 할지라도 동일탭에 여러 실행 흐름을 말하게 되고 -예를들어 네트워크 처리 스레드, 검색 스레드 와 같이 동일한 프로세스 내 기능들을 말하게 된다.</p> +예를들어 네트워크 처리 스레드, 검색 스레드 와 같이 동일한 프로세스 내 기능들을 말하게 됩니다.</p> <br> <br> <h2 id="멀티-스레드의-장점" style="position:relative;"><a href="#%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9D%98-%EC%9E%A5%EC%A0%90" aria-label="멀티 스레드의 장점 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>멀티 스레드의 장점</h2> <hr> <h3 id="프로세스보다-스레드가-가벼움" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%B3%B4%EB%8B%A4-%EC%8A%A4%EB%A0%88%EB%93%9C%EA%B0%80-%EA%B0%80%EB%B2%BC%EC%9B%80" aria-label="프로세스보다 스레드가 가벼움 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스보다 스레드가 가벼움</h3> <p>스레드는 프로세스보다 용량이 가볍다. 이유는 데이터, 코드, 힙 영역을 -프로세스와 공유해서 사용하기 때문에 내장된 정보다 프로세스보다 작기 떄문이다. -그렇기 때문에 스레드를 제거하는 작업이 프로세스를 제거하는 작업보다 가볍다.</p> +프로세스와 공유해서 사용하기 때문에 내장된 정보다 프로세스보다 작기 떄문입니다. +그렇기 때문에 스레드를 제거하는 작업이 프로세스를 제거하는 작업보다 가볍습니다.</p> <br> <br> <h3 id="자원의-효율성" style="position:relative;"><a href="#%EC%9E%90%EC%9B%90%EC%9D%98-%ED%9A%A8%EC%9C%A8%EC%84%B1" aria-label="자원의 효율성 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>자원의 효율성</h3> <p>멀티 스레드는 하나의 프로세스 내에서 스택영역을 제외한 영역을 공유하기 때문에 -프로세스 간 통신을 사용하지 않고도 자원의 공유가 가능하여 자원을 효율적으로 사용할 수 있다.</p> +프로세스 간 통신을 사용하지 않고도 자원의 공유가 가능하여 자원을 효율적으로 사용할 수 있습니다.</p> <br> <br> <h3 id="Context-Switching-비용-감소" style="position:relative;"><a href="#Context-Switching-%EB%B9%84%EC%9A%A9-%EA%B0%90%EC%86%8C" aria-label="Context Switching 비용 감소 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>Context Switching 비용 감소</h3> <p>스레드 문맥 교환 또한 오버헤드가 존재하지만, 프로세스 문맥교환과 비교했을 때, -상대적으로 오버헤드가 적다.</p> +상대적으로 오버헤드가 적습니다.</p> <p>이유는 프로세스 컨텍스트 스위칭 비용은 스위칭할 때마다 CPU 캐시에 있는 내용을 모두 초기화하고, -새로운 프로세스 정보를 CPU 캐시에 적재해야 하기 떄문이다. -하지만, 스레드 문맥교환은 스레드 개별적인 정보만 교체하면 되기 떄문에 비용이 상대적으로 낮다.</p> +새로운 프로세스 정보를 CPU 캐시에 적재해야 하기 떄문입니다. +하지만, 스레드 문맥교환은 스레드 개별적인 정보만 교체하면 되기 떄문에 비용이 상대적으로 낮습니다.</p> <br> <br> <h2 id="멀티-스레드의-단점" style="position:relative;"><a href="#%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9D%98-%EB%8B%A8%EC%A0%90" aria-label="멀티 스레드의 단점 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>멀티 스레드의 단점</h2> -<p>멀티 프로세스는 개별적인 작업으로 인해 독집적이고, 각자의 문제를 전파하지 않는다고 하였다.</p> -<p>하지만, 멀티 스레드는 하나의 스레드가 문제가 발생하면 다른 스레드들고 영향을 받아 전체가 종료가 될 수 있다.</p> +<p>멀티 프로세스는 개별적인 작업으로 인해 독집적이고, 각자의 문제를 전파하지 않는다고 합니다.</p> +<p>하지만, 멀티 스레드는 하나의 스레드가 문제가 발생하면 다른 스레드들고 영향을 받아 전체가 종료가 될 수 있습니다.</p> <br> <br> <h2 id="데드락" style="position:relative;"><a href="#%EB%8D%B0%EB%93%9C%EB%9D%BD" aria-label="데드락 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>데드락</h2> <p>데드락이란 하나의 자원을 사용하기위해 여러 곳에서 접근했고, 그상황에서 교착상태가 일어났을때 -여러대의 스레드가 서로 대기하면서 무한정 기다리는 현상을 데드락이라고 한다.</p> -<p>예를들어, 스레드 1 은 자원 A을 점유하고 있는 상태에서 자원 B가 필요한 상황이다. -그리고 스레드 2 는 자원 B를 점유하고 있는 상태에서 자원 A이 필요한 상황이다. +여러대의 스레드가 서로 대기하면서 무한정 기다리는 현상을 데드락이라고 합니다.</p> +<p>예를들어, 스레드 1 은 자원 A을 점유하고 있는 상태에서 자원 B가 필요한 상황입니다. +그리고 스레드 2 는 자원 B를 점유하고 있는 상태에서 자원 A이 필요한 상황입니다. 하지만 스레드 1은 자원 B가 필요한 상황에서 자원 A을 빌려줄 수 있는 상황이 아니고, -스레드 2또한 자원 A이 필요한 상태에서 자원 B를 빌려줄 수 없는 상황인 것이다. +스레드 2또한 자원 A이 필요한 상태에서 자원 B를 빌려줄 수 없는 상황인 것입니다. 이처럼 다수의 쓰레드가 같은 lock을 동시에, -다른 명령에 의해 획득하려 할 때 서로 절대 불가능한 일을 계속적으로 기다리는 상황을 이야기 한다.</p><![CDATA[9. 쓰레드의 개념, 메모리 공유 구조 및 TCB]]>https://catch-npe.netlify.app/9/https://catch-npe.netlify.app/9/Fri, 12 Sep 2025 00:00:00 GMT<h2 id="스레드란" style="position:relative;"><a href="#%EC%8A%A4%EB%A0%88%EB%93%9C%EB%9E%80" aria-label="스레드란 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>스레드란?</h2> +다른 명령에 의해 획득하려 할 때 서로 절대 불가능한 일을 계속적으로 기다리는 상황을 이야기 합니다.</p><![CDATA[5. CPU 스케줄링]]>https://catch-npe.netlify.app/hs5/https://catch-npe.netlify.app/hs5/Fri, 12 Sep 2025 00:00:00 GMT<h2 id="기아-상태와-CPU-스케줄링" style="position:relative;"><a href="#%EA%B8%B0%EC%95%84-%EC%83%81%ED%83%9C%EC%99%80-CPU-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="기아 상태와 CPU 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>기아 상태와 CPU 스케줄링</h2> +<p>프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다. +그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나, +너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고 +이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다. +이를 컴퓨팅에서는 기아 현상이라고 하는데, +이로 인해 프로세스들에게 CPU 자원 할당을 배분해주는 CPU 스케줄링이 개발되었고, +운영체제에 반드시 필요로 하게 되었습니다.</p> +<blockquote> +<p>기아 현상에 대한 대표적인 해결 방법은 에이징 기법을 이용하는 것입니다. +오랫동안 대기한 프로세스의 우선순위에 대해 가중치를 주어, +처음에 우선순위가 낮아도 언젠가는 우선순위가 높아져 기아 현상을 막을 수 있습니다. +이와 같이 CPU 스케줄링에서는 이러한 문제 해결을 위한 다양한 방식들이 있습니다.</p> +</blockquote> +<h2 id="프로세스-우선-순위" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%9A%B0%EC%84%A0-%EC%88%9C%EC%9C%84" aria-label="프로세스 우선 순위 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스 우선 순위</h2> +<p>스케줄링을 지정하는 것은 순서를 지정하는 것과 같습니다. +그런데 어떻게 프로세스들 간의 순위를 공정하게 지원하고 있을까요?</p> +<h3 id="순차방식" style="position:relative;"><a href="#%EC%88%9C%EC%B0%A8%EB%B0%A9%EC%8B%9D" aria-label="순차방식 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>순차방식</h3> +<p>가장 단순하게 생각해보면 요청이 들어온 순서대로 할당하는 방식입니다. +그러나 이 방식은 빨리 처리해야 하는 프로세스가 있을 수 있는 상황에서 대응하지 못한다는 것입니다.</p> +<p>예시로 CPU를 많이 사용하는 프로세스가 I/O 작업을 하는 프로세스 보다 늦게 들어올 경우, +순서상으로는 뒤에 있어야 하지만, CPU 자원을 할당한다는 측면에서 볼 떄에는 앞 순위로 두는 것이 효울적일 것입니다.</p> +<h3 id="우선순위-지정-방식" style="position:relative;"><a href="#%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-%EC%A7%80%EC%A0%95-%EB%B0%A9%EC%8B%9D" aria-label="우선순위 지정 방식 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>우선순위 지정 방식</h3> +<p>위 순차적인 방식이 아닌, 별도의 우선순위를 지정하는 방식도 있습니다. +이때, 우선순위에 대한 정보는 PCB에 저장이 됩니다.</p> +<p>이로 인해 프로세스의 중요도에 맞게 프로세스가 CPU를 이용할 수 있도록 운영체제가 부여하는 것이 우선순위이며, +운영체제는 PCB를 기반으로 어떤 프로세스가 CPU를 얼마나 사용하게 될 것인지 등을 결정합니다.</p> +<p>프로세스 우선순위는 간단한 명령어나 프로그램 등으로 확인이 가능한데, +일부 우선순위의 경우에는 사용자가 직접 설정 가능한 것도 있습니다.</p> +<h3 id="스케줄링-큐" style="position:relative;"><a href="#%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81-%ED%81%90" aria-label="스케줄링 큐 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>스케줄링 큐</h3> +<p>프로세스가 여러 개일 경우, 다음 CPU 자원을 이용할 프로세스를 선택하기 위해 매번 모든 프로세스들의 PCB를 다 뒤져보는 것은 매우 비효율적일 것입니다. +또한, CPU 말고도, 메모리, 입출력 장치를 사용하고자 하는 경우에도 비슷한 상황을 겪을 것입니다.</p> +<p>때문에 운영체제는 어떤 자원을 이용하고자 할 때 대기 하는 스케줄링 큐를 활용하고 있습니다.</p> +<p>이때, 큐라고 해서 반드시 선입선출(FIFO)에 국한되지 않습니다.</p> +<h2 id="선점형-스케줄링과-비선점형-스케줄링" style="position:relative;"><a href="#%EC%84%A0%EC%A0%90%ED%98%95-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81%EA%B3%BC-%EB%B9%84%EC%84%A0%EC%A0%90%ED%98%95-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="선점형 스케줄링과 비선점형 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>선점형 스케줄링과 비선점형 스케줄링</h2> +<p>스케줄링 방식에는 선점형 스케줄링과 비선점형 스케줄링 방식이 있습니다.</p> +<h3 id="선점형-스케줄링" style="position:relative;"><a href="#%EC%84%A0%EC%A0%90%ED%98%95-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="선점형 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>선점형 스케줄링</h3> +<p>선점형 스케줄링은 현재 CPU를 사용 중인 프로세스로부터 CPU 자원을 뺴앗아 요청한 프로세스에 할당하는 방법입니다. +어느 한 프로세스의 자원 독점을 막고 프로세스에 골고루 자원을 배분할 수 있으나, 그 만큼 컨텍스트 스위칭 과정에서 오버헤드가 발생할 수 있습니다.</p> +<h3 id="비선점형-스케줄링" style="position:relative;"><a href="#%EB%B9%84%EC%84%A0%EC%A0%90%ED%98%95-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="비선점형 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>비선점형 스케줄링</h3> +<p>비선점형 스케줄링은 현재 CPU를 사용 중인 프로세스의 작업이 끝날 때까지 기다리는 방식입니다.</p> +<p>선점형 스케줄링과 반대되는 개념으로, 컨텍스트 스위칭에서 발생하는 오버헤드가 적지만, 한편으로는 모든 프로세스가 골고루 자원을 이용하기 어렵습니다.</p> +<h2 id="CPU-스케줄링-알고리즘" style="position:relative;"><a href="#CPU-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98" aria-label="CPU 스케줄링 알고리즘 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>CPU 스케줄링 알고리즘</h2> +<p>선점형 스케줄링과 비선점형 스케줄링을 기반으로 다양한 CPU 스케줄링 알고리즘이 있습니다.</p> +<h3 id="선입-선처리-스케줄링" style="position:relative;"><a href="#%EC%84%A0%EC%9E%85-%EC%84%A0%EC%B2%98%EB%A6%AC-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="선입 선처리 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>선입 선처리 스케줄링</h3> +<p>FCFS(First Come First Served) 스케줄링으로, 준비 큐에 삽입된 순서대로 처리하는 비선점 스케줄링 방식입니다. +CPU를 먼저 요청한 프로세스부터 CPU를 할당합니다. +이로 인해 프로세스들이 기다리는 시간이 매우 길어질 수 있는 부작용이 있으며, +이를 convoy effect, 호위 효과라고 합니다.</p> +<h3 id="최단-작업-우선-스케줄링" style="position:relative;"><a href="#%EC%B5%9C%EB%8B%A8-%EC%9E%91%EC%97%85-%EC%9A%B0%EC%84%A0-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="최단 작업 우선 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>최단 작업 우선 스케줄링</h3> +<p>SJF(Shortest Job First) 스케줄링으로, +사용 시간이 긴 프로세스를 나중에 실행하고, +시간이 짧은 프로세스를 먼저 실행함으로써 평균 대기 시간을 줄일 수 있습니다. +이 알고리즘은 기본적으로는 비선점형 스케줄링 방식에 속하지만, +선점형과 비선점형 스케줄링 방식으로 모두 가능합니다.</p> +<h3 id="라운드-로빈-스케줄링" style="position:relative;"><a href="#%EB%9D%BC%EC%9A%B4%EB%93%9C-%EB%A1%9C%EB%B9%88-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="라운드 로빈 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>라운드 로빈 스케줄링</h3> +<p>RR(Round Robin) 스케줄링으로, +선입 선처리 스케줄링과 시분할 시스템의 타임 슬라이스(time slice) 개념이 결합된 방식입니디. +정해진 타임 슬라이스만큼의 시간 동안 돌아가며 CPU를 이용하게 하는 선점형 스케줄링입니다.</p> +<h3 id="최소-잔여-시간-우선-스케줄링" style="position:relative;"><a href="#%EC%B5%9C%EC%86%8C-%EC%9E%94%EC%97%AC-%EC%8B%9C%EA%B0%84-%EC%9A%B0%EC%84%A0-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="최소 잔여 시간 우선 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>최소 잔여 시간 우선 스케줄링</h3> +<p>SRT(Shortest Remaining Time) 스케줄링으로, +최단 작업 우선 스케줄링과 라운드 로빈 스케줄링이 결합된 형태입니다. +정해진 시간만큼 CPU를 이용하되, +다음으로 CPU를 사용할 프로세스로는 남은 작업 시간이 가장 적은 프로세스를 선택합니다.</p> +<h3 id="우선순위-스케줄링" style="position:relative;"><a href="#%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="우선순위 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>우선순위 스케줄링</h3> +<p>프로세스들에 우선순위를 부여하고, 우선순위가 높은 프로세스부터 실행하는 방식입니다. +우선순위가 같은 프로세스들은 선입 선처리 스케줄링으로 돌아가고, +최단 작업 우선 스케줄링이나 최소 잔여 시간 스케줄링은 포괄적인 의미에서 우선순위 스케줄링에 속한다고 할 수 있습니다.</p> +<h3 id="다단계-큐-스케줄링" style="position:relative;"><a href="#%EB%8B%A4%EB%8B%A8%EA%B3%84-%ED%81%90-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="다단계 큐 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>다단계 큐 스케줄링</h3> +<p>멀티 레벨 큐 스케줄링으로도 불리는데, 우선순위 스케줄링의 발전된 형태입니다. +우선순위 별로 준비 큐를 여러 개 사용하고, 우선순위가 높은 큐에 있는 프로세스를 먼저 실행합니다. +우선순위가 높은 큐가 비어 있다면, 그 다음 우선순위 큐에 있는 프로세스를 처리합니다. +이러한 방식은 프로세스 유형별로 우선순위를 구별하게 하여 관리가 쉬워집니다. +큐 별로 타임 슬라이스를 여러 개 지정할 수도 있고, 큐마다 다른 스케줄링 알고리즘을 사용할 수도 있습니다. +기본적으로 큐 간 이동이 불가능하기 때문에, 우선순위가 낮은 프로세스는 계속해서 우선순위가 낮을 수 밖에 없고, +그로 인해 기아 현상을 겪을 수도 있습니다.</p> +<h3 id="다단계-피드백-큐-스케줄링" style="position:relative;"><a href="#%EB%8B%A4%EB%8B%A8%EA%B3%84-%ED%94%BC%EB%93%9C%EB%B0%B1-%ED%81%90-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="다단계 피드백 큐 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>다단계 피드백 큐 스케줄링</h3> +<p>멀티 레벨 피드백 큐 스케줄링으로도 불리는 이 방식은 다단계 큐 스케줄링의 발전된 형태로, +큐 간 이동이 가능합니다. +새로 준비 상태로 된 프로세스가 있으면 가장 우선순위가 높은 큐에 삽입합니다. +일정 시간 즉, 타임 슬라이스 만큼 CPU를 사용할 수 있는데, +만약 작업이 끝나지 않았다면, +그때 우선순위가 다음으로 높은 곳에 삽입을 합니다. +작업을 많이 있는 프로세스일수록 우선순위가 점점 낮아지게 되고, +따라서 CPU 집중 프로세스는 상대적으로 우선순위가 낮아지고, 입출력 집중 프로세스는 높아지게 될 겁니다. +일정 시간 이상 낮은 우선순위에서 기다리고 있던 프로세스가 있었다면 이 프로세스의 우선순위를 점차 높임으로써 기아 현상을 방지할 수 있습니다. +다단계 피드백 큐 스케줄링은 CPU 사용 시간이 길면 우선순위가 점점 낮아지고, 동시에 어떤 프로세스가 낮은 우선순위 큐에서 너무 오래 기다리면 우선순위를 높일 수도 있습니다. +다단계 피드백 큐 스케줄링은 복잡하지만, CPU 스케줄링의 가장 일반적인 형태로 알려져 있습니다.</p><![CDATA[쓰레드의 개념, 메모리 공유 구조 및 TCB]]>https://catch-npe.netlify.app/jc9/https://catch-npe.netlify.app/jc9/Fri, 12 Sep 2025 00:00:00 GMT<h2 id="스레드란" style="position:relative;"><a href="#%EC%8A%A4%EB%A0%88%EB%93%9C%EB%9E%80" aria-label="스레드란 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>스레드란?</h2> <hr> -<p><img src="%EC%8A%A4%EB%A0%88%EB%93%9C.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 220px; '> + <a class='gatsby-resp-image-link' href='/static/40c5e97b7023312340a397b47390fc34/8c324/thread.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 94.70588235294117%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAADgElEQVR42pWUa0hTcRTAb9Y0NNRGYuJjafagESVCQlSChn2wbyFFD8Qg6kNfiiLB0EC/mX4QKVdSPuaj+W6zKaJbCnMvt/A1Ta2mVGqRhFI2772nc+5217US6g9n58/d+f/O43/+h2HWr030ExYWtj0kJORkfHx8ZGJiYoRCodgZFRUVJ5dHxzAMbGL+YwnGERER21ApURQoR1FOoKSgHKD/NRrN5n+CAUAAbTIzcxKKi1tvq9VDuo6Ot+b29hlTTY21qahIfS0lJS2SbHy2YrR7JHs/jD7Iioub7nV1fViZmABA4Um7XACTk8CPjQGgg8W8PNVVCZTWISlQ3AQVFta1Op08OJ0cazAssWazh7XbgbXZgB0cXGVNpu/s8DBwFss3yM+vKvFB6fxBP0f0UlamLzMYvsCzZ6OepqZxrrFxGPr7l2FoCNABgF7/HrAE0Nw8wWk0Yx6t9h0UFdVcp7PBwcGHUQX487106c4xo3GBw5T4np6PfG2tFUZHAWw2DjBCQQgswvE72aKTt4tK5fFYROzPysr6dVGPH/c9pVrhAba39zPgBcCrV+uBNhsvaKNxSdyvEbS0tOUWdYNKpZKJvBCtdso1Pu71bLfzYLWyfpAUSNE9fNgLL19+FZxTELW15i5k7JLLY6JRxzEZGWdjdbp3y1hsAvJe7/yGwIqKPhEopN3c7JpE0L7AwG0HhH49f/6yorPT/Y2AVivHU50cDtgQWF7eDQMDK35gW9vkNDW8TCZT+h4AI9fp3szSJaARTzXERvbVUBopL1zKixdzYDKt0jeW+rOhwWFCRmJQUFCar30Ypr7e2kn1QAir07mhsrIfRkaEiP+IlKIkMPbmGjY7qFQ996mGoaGhR1BvF4B371ZcdDjWCLLW0TED1dWWDYEUNZUGwbzBMM/l5OTSG9+dmpq6Rfr0tqjVFqPbDaDVuj11dU7wXdJfgah/TE0BPHigf+Jt7HB6et4+LCgoEDo8Pf3s3pYW1+z0NEXm8eBBliLx3rwgHAqLZfGQjVptG/SnyDBJ616KCD116sI+TNdK6dJgIE2XQzIywsPr18Db7R6MrO85zscdkgyVv08bPxTX1ry8R1cw7UGcOkvd3fP4HBdYvX7uU1WVpefGjZIzFI1k0gSiVPmgzB9Q3/QQplBCQnJcdnZu8rlzN5Noaot2XlhBgOToaZRw2v0EwSQH1AYhyiYAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/40c5e97b7023312340a397b47390fc34/8c324/thread.png' srcset='/static/40c5e97b7023312340a397b47390fc34/e7570/thread.png 170w, +/static/40c5e97b7023312340a397b47390fc34/8c324/thread.png 220w' sizes='(max-width: 220px) 100vw, 220px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <br> <p>스레드는 프로세스를 구성하는 실행의 흐름 단위라고 표현합니다.</p> <p>또한, 하나의 프로세스가 복수적인 스레드를 가질 수 있습니다. 그렇기 때문에 스레드를 이용하면 @@ -176,12 +1845,34 @@ <p>스레드를 이해하기 위해서는 프로세스와 엮어서 설명하고자 합니다. 전통적인 CPU는 하나의 프로세스만 처리할 수 있었습니다. 메모장, 워드, 게임등 많은 프로세스가 하나의 실행 흐름을 가지고 한 번의 하나의 부분만 실행되는 프로세스입니다.</p> -<p>![img.png](단일스레드 프로세스.png)</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/dbd85ead6e221137ceff2c024b5cf1c0/96d37/single_process.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 77.64705882352942%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB7klEQVR42oWUh44iQQxE+f8/AkTOOed8gFgywxJEGHzzfGq0txKAVPK0aZfL1T3julk7sfeW2Kej3MHh4OBb7PtdbrebXC4XjcC2bVkul9JqtWS/3+v6er0+wR7XaDiU6fiPDAd9mU7G0mm35Ws6FRpNxmOZzWayWq1ksVjIfD6X9Xqta4g3m40+E1lPJhNx7Z0Np91OzpYlZyeedluNTjtpNBpSKpWkXq9LuVxWVKvVJ/L5vAQCAQmHw5JKpaTT6Yjr8XjI42GLRmcEMdH5tR21iURCQUEmk5FkMqlrCGkQi8UUkPf7fUP4P+wfhH6/X1VEo1ElCgaDqggyJjANa7XaZ0IKKpWKRgoA4wPyzWZTVaMea7rd7ntCVKCMong8/hz939hx8Xg8OoHJcfofRm4pKd3xKJvNSi6XU6WFQkF8Pp825H8wGAzeE3JqmI/pFKMGGBtQDTHPxWLx5ym/PhQUQYACIqCYyGFhh1GMt28J2YBvjErEJwjS6bTm8I48E0COPW8JOTXUMDYKzeU2as2okGEJuY/XBs/CkbC43W4JhULi9Xq12Ixqpvj1prz2EG/obNT9Buo56Ugk8plwNBrp5e31ehoBRdw37OCZyJppXr4pBufzWY7HoxycTxrgk2U5XyGiyQH2kNtut/IXpVuQYEMSR/YAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/dbd85ead6e221137ceff2c024b5cf1c0/ca1dc/single_process.png' srcset='/static/dbd85ead6e221137ceff2c024b5cf1c0/e7570/single_process.png 170w, +/static/dbd85ead6e221137ceff2c024b5cf1c0/f46e7/single_process.png 340w, +/static/dbd85ead6e221137ceff2c024b5cf1c0/ca1dc/single_process.png 680w, +/static/dbd85ead6e221137ceff2c024b5cf1c0/96d37/single_process.png 823w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <p>이런 프로세스를 단일 스레드 프로세스라고 부릅니다.</p> <br> <p>하지만, 스레드라는 개념이 도입되면서 하나의 프로세스가 한 번에 여러가지 일을 동시에 처리하는 것이 가능해졌습니다. 프로세스를 구성하는 명령어를 동시에 처리하는것이 가능해졌습니다.</p> -<p>![img.png](멀티스레드 프로세스.png)</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/5853f5579724a68d0bd20961dcf37777/dd6e8/multi_thread_process.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 75.29411764705883%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB4UlEQVR42o2UWY8aMRCE+f9/CMShcN/DfQaiLEoeAgrnzHAMgoo/b5zlYZfNSKW2W3a5qtueWBQGOm7WOu+2uvgHXQJfx91G19DXNYrk+77F8Xi0YDybzbRYLHQ6nRQEgUUYhjbG9qtf+vZ1qh8v3w1e9NMsnE+nCjYbHVZLbUx0myAjXi4XSwYgAuSWy6ViV7PgalRGFqGi4DXezuZ0Q+B5LbXbbQvPa5r4Oq/X60okEioWi2o0GsrlcjYfu9/vuuvtY0yOD4udTscurlarqtVqqlQqyufz6na7KhQKajabarVaSiaTGo/HfwkfcbvpZuAIe72eVQEZSiAulUo2Xy6XLdlwOFQ2m9V8Pn+H0MARUi8UshkwRpmbY9vzPGsVF5PJ5DkhxcYSytjoCJijrlDI21w6nVY8HtdoNPqckEWowSZ2sYZSkEql1O/3bTkoy4eWH5sCIZsgQw3KICOfzX6x9UM1B77flAeFEDqLFN91lAhcl90anHyqkCY4UHzXFGImk/l3/1D4dg8/IDyfz/Z06sPdA2ykjthnTqQEXHLiU0KelnsV7h5ikXpiHXLm7h4S/9syNiFxYxrFYS5HswaDwXPCyPxtDoeD9vu9drud/VGs178N1tputzb3iNVqpT/KYkhgtl4rXwAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/5853f5579724a68d0bd20961dcf37777/ca1dc/multi_thread_process.png' srcset='/static/5853f5579724a68d0bd20961dcf37777/e7570/multi_thread_process.png 170w, +/static/5853f5579724a68d0bd20961dcf37777/f46e7/multi_thread_process.png 340w, +/static/5853f5579724a68d0bd20961dcf37777/ca1dc/multi_thread_process.png 680w, +/static/5853f5579724a68d0bd20961dcf37777/dd6e8/multi_thread_process.png 799w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <br> <p>그림을 통해 스레드를 보게 되면 스레드는 '프로세스를 구성하는 실행의 흐름 단위'라고 표현 가능 할 것입니다.</p> <p>왜냐하면, 하나의 프로세스 안에 여러가지 스레드가 있고 각각의 작업 흐름을 가지며 프로세스가 하는 일을 병렬적으로 만들어 @@ -190,7 +1881,17 @@ <br> <h2 id="스레드-메모리-구조" style="position:relative;"><a href="#%EC%8A%A4%EB%A0%88%EB%93%9C-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0" aria-label="스레드 메모리 구조 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>스레드 메모리 구조</h2> <hr> -<p><img src="%EB%A9%94%EB%AA%A8%EB%A6%AC%EA%B5%AC%EC%A1%B0.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 487px; '> + <a class='gatsby-resp-image-link' href='/static/47d51a17aabda41526b35a01c6d7316b/6a170/memory_model.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 98.23529411764706%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEXUlEQVR42o2VW2hUVxSG89jHQtuH0re+9UWKD8VSWwpFKS2oaBUvUSQai5pqqUWNVqnYNmChYAuiiNqGFh1jLiaZTJ1MZjLXM3POnDkzOZlL5n7LpUZjrCZOnMx83c4UjCi0G/5z2Ju1v7X2Za3dwJJWrUJFfJ7o+VZ9rlep1ucsNW94sTmUhfXE3yXsmVnO+ib5xTuJJTFDYnqOB6WygLzI6b/Aai26KlMPSrhzs1xUpzgylGNrT5K1HQk+NST4vD9D66083w4VOOsepyM0jTd7n8nZR5TLizXKE0ZD3U+FS/5xmvvTNHYLyPUE6zqSbOpKsbknzRahvQNZjg4WOCGAp23jtNmKnBku1v6tg3l8uZmnET6cmea7wRgbe7K0mAscG55k3595dhmzNAttv5lmV1+GQ7dytFoKHBZqMRfZPlBgc2+ONR1xerUULC7UgQaDAcvQEBZF51d3hHY5wxl3kSZTnq3GArtNBQ6K6HYKwDahHcLJAVOCNvMo7VYVq0ems7MTr9dbB87Pz+PzSngcw+h+HwFFQZIV+twa56w6p6wpTjgmaqu4bAsy4PDicjqQncNCduzWIZKJBJVKpQ4sl8sosozT4cTpdCF5JNxOJx67DdXtwGwycuH8eWSXA5/Dhls4djoc2IWcws4qVpfNZp/u4fj4OF7Jg+z1oAX8NbjP50WSJCSvrzbJaDSKMRm3xyOic9WATvswLgG326yER0eZm5urA/v7+hi02HC4/Lg8fmRFJRQKEQmPCkOdYFAjHA6jqn4CwqGqKsKpgsfrx+EO4Har9Pcb0TStDozEMkyFzjAdbCMZ6GE04CGgavjEIcn+EGpAq0EVvxjzj4gxHdUfIOy3kFOvcMf/BfeL5tp9bqiUF0jm/uLuwFcgfQzZ/dyLHGUy9AMT+mXSI4Ni0y1cudxOWJNIB7u5EznHQvok5Fsgto3Hxve5q3bUgTO3b6OMRYms20v4lbcoNq4m880a4uc38FjZAYW9PEq3ihWcguIhSDZTlRqZu7SeqT2rSK1YidbwJtkLV+uHslAqEUsmGblxE3XfSbR3tpDZ0EJmuYC+vozCJyuZbVvLQtdOpr9cTfa9d4m+vAz9peUE31iFuroZ3+HvyQaCT085nUpiCehI0Qh6NIRiNhO89Acje04QensT+msfEH51BaHXPyL0YRP6sR+JXO8iovoIxXRMgRDhTL4OrOXyYonjpjF292b42Z7i4qDCVauLQDxKNK4TE/dsrKuXmNdNOBlBiY8xoCe54IrTak6x5toYPSPFJUCxnb1ylIMGiUaDxhFLjq8tRfabsvxkT9It8tQubsLvcpLT1nQtv9d3JllniNBkUDnZ5SWan3q2Hj6pOAsPZ0lnc9h8GhfNCgc6fGy8FuKzG3Ga+tKiCsXYfk3jeLdMu01FHolwe2qSSmnuvwssi2Xm798jkUphlIL8ZtNwamEmRFYtzj94ZkZ1Sa/h2Seg+r+fgMrS52KJ/T9wi0nqe6Y2LgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/47d51a17aabda41526b35a01c6d7316b/6a170/memory_model.png' srcset='/static/47d51a17aabda41526b35a01c6d7316b/e7570/memory_model.png 170w, +/static/47d51a17aabda41526b35a01c6d7316b/f46e7/memory_model.png 340w, +/static/47d51a17aabda41526b35a01c6d7316b/6a170/memory_model.png 487w' sizes='(max-width: 487px) 100vw, 487px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <p>스레드의 메모리 구조를 이해하기 위해서는 이전 프로세서의 구조를 상기해봐야 합니다.</p> <p>프로세스는 스택, 힙, 데이터, 코드 영역을 각자 가진다고 합니다. 스레드는 '프로세스를 구성하는 실행 흐름의 단위'라고 했고, 이 떄문에 스레드는 프로세스의 메모리 구조의 대부분을 공유해서 @@ -199,7 +1900,15 @@ <p>그렇다면 어떻게 스레드는 프로세스와 스레드간 데이터를 공유하는 것일까? 아래 그림을 통해서 보게되면</p> <br> -<p><img src="%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9E%90%EC%9B%90%EA%B3%B5%EC%9C%A0.png" alt="img.png"> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 670px; '> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 37.64705882352941%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABRUlEQVR42m1Ry27CMBDk43vuB/XUa8WBCypBJSnk4ZD3O0B4THdWcU61NLLX65mdXa/GccQwDIq2bdH3PZqmWc5d16EXdPIu+fzA8f0NlbPF9Hrhdrthmibdn88nuFaOs1OxLMvgui7iOIbneTgcDiiKQs/GGJjzGT/rL9SbNczxF7nkqqpaQGEV9DwXdGmd8Ux3LMKH1vk4DqjlDZ3lZYnH46ECL4mJxeHlcsH1esVZHIRhqKJ1XSNNU/i+ry4pmiSJxq3keGcF7KKoCrKSJQRBoEIkcAQswBHQIfOMeU+wKO91xvOsWWR1v9+XGUZRpGLFPJ9IBChEYp7nmi+lXRZlJxQilzuhgnRIQiBkXxyamcRY704nzYdzzA9iETvDf1vu6VBaM/sdUnFairssNoj3jpIraS+JQoTfW501QZ79EAsK/gH+r1/s5/NXMgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/81ec90193973957070b838990bb280b4/6bbca/thread_resource.png' srcset='/static/81ec90193973957070b838990bb280b4/e7570/thread_resource.png 170w, +/static/81ec90193973957070b838990bb280b4/f46e7/thread_resource.png 340w, +/static/81ec90193973957070b838990bb280b4/6bbca/thread_resource.png 670w' sizes='(max-width: 670px) 100vw, 670px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure> <a href="https://gmlwjd9405.github.io/2017/10/01/basic-concepts-of-development-os.html">사진출처</a></p> <br> <p>우선 하나의 프로세스안에 코드, 데이터, 힙, 스택 영역이 존재합니다. 그리고 프로세스 내부의 개별적인 스레드가 존재합니다.</p> @@ -245,7 +1954,19 @@ </span> <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> </figure></p> -<p><img src="TCB%ED%99%95%EC%9E%A5.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/f2697d8a2bf669a0e7e35772bfcb8d75/bbbf7/TCB3.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 57.05882352941176%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABt0lEQVR42oVTiU7CUBDs/3+F4omg4n1EY1RiPBBQgYp3sECFXvTiWbHj7kOJRxpfMnnLzO4y7W4V/DpxHMvbcRzU63XYtg3DMCS+4iAIkHSUUfT+jvgTfGzLgmWaaDU1iH4f3U4HTU3Dc6Mhefnn32vYCEGJowjx29sfhxa5EcR71Mwgtx1q4oYh+sSx9j33h8OwcILgKA//ogzz9ARO4QxR5RJ6/hB+qQi3WEA7fwBtfw9e8Rx+uSi16OpSaubpMXp0i3IJ4lqF4lCiubmOl9VlPGTn8JxbgLO1gftMGjpxrDWIu5mbhbGxJjnWOEdfWZJxazkHa30Vzt4OFHtnG1o2g+pkCtWJcVRSY2hRg7vZaTQXs7hLT6NGGuM+PTPkSOOcK8pVp1KyRpvPwN7dhhI9PUqrvlqDV6sSKohub9A5LyAgjmFelGDQ48vf1zWpcc4wn6BWIeoquJeStDb84nkAIQ2t3TWg07qEr6//D0WOm8f+tQKDwbAhNeB18VwXL7oOvd2G73kQNGnWZEPKHa3N5+okO6Q97FPDARXxLYQYxawlO0w4vV5PFrrkkGMGx8xxnPSlfADIVzRwwzJlEgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/f2697d8a2bf669a0e7e35772bfcb8d75/ca1dc/TCB3.png' srcset='/static/f2697d8a2bf669a0e7e35772bfcb8d75/e7570/TCB3.png 170w, +/static/f2697d8a2bf669a0e7e35772bfcb8d75/f46e7/TCB3.png 340w, +/static/f2697d8a2bf669a0e7e35772bfcb8d75/ca1dc/TCB3.png 680w, +/static/f2697d8a2bf669a0e7e35772bfcb8d75/02d09/TCB3.png 1020w, +/static/f2697d8a2bf669a0e7e35772bfcb8d75/bbbf7/TCB3.png 1280w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <br> <br> <p>TCB는 사진과 같은 형태로 저장되며, 아래와 같은 정보를 가진다.</p> @@ -286,7 +2007,7 @@ <td>문맥 교환 시 저장되고 복원되어야 할 정보</td> </tr> </tbody> -</table><![CDATA[8. 문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기]]>https://catch-npe.netlify.app/8/https://catch-npe.netlify.app/8/Thu, 11 Sep 2025 00:00:00 GMT<h2 id="문맥교환Context-Switching" style="position:relative;"><a href="#%EB%AC%B8%EB%A7%A5%EA%B5%90%ED%99%98Context-Switching" aria-label="문맥교환Context Switching permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>문맥교환(Context Switching)</h2> +</table><![CDATA[문맥교환 그리고 프로세스 상태 변화, 프로세스 계층과 생성 방식을 알아보기]]>https://catch-npe.netlify.app/jc8/https://catch-npe.netlify.app/jc8/Thu, 11 Sep 2025 00:00:00 GMT<h2 id="문맥교환Context-Switching" style="position:relative;"><a href="#%EB%AC%B8%EB%A7%A5%EA%B5%90%ED%99%98Context-Switching" aria-label="문맥교환Context Switching permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>문맥교환(Context Switching)</h2> <hr> <p>하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어가면 어떤 일이 발생할까요?</p> <p>프로세스 A가 CPU를 사용하다가 사용 시간이 끝나서 프로세스 B로 넘어간다면, A프로세스의 정보를 @@ -295,7 +2016,16 @@ <p>여기서 하나의 프로세스를 실행하기 위해 필요한 정보들을 문맥(Context)라고 부르게 됩니다. 이러한 문맥값들은 PCB속에 저장됩니다.환</p> <br> -<p><img src="%EB%AC%B8%EB%A7%A5%EA%B5%90%ED%99%98.png" alt="img.png"> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 77.05882352941177%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAACFUlEQVR42o1T2a7iMAzl/yX+hFceQAIe+AEkHudygbZ0ge5Z2qTLGTsMd5irGZhIVurYPjk5dif4trquRxQnaI3FMJLfD7Dd4GLWdkiuN/J79BTkGNs4/q6ffAfk5EK0EKrF2Y8gaS/J58LW9qikQS0bioWQ2kBoi8Z0/wY0VFQrYnIr8HH0EV8zVMo6lq3pHUByy/HjcMaVclTbQ7cvALt+RFEpFGWFLC/JCufzExm0qjXFSqRZ4UwQW2b+EjArJYIwIotxiRLklXbnhgALAvSDEMHlHqvfATKLUhhESeqexc9j3Wz/eHKHMLri49MjOXLSsXujITWFNStric9T4BhUyjxp2BFjgZN3oZiGbDroV4BcyCIXBetE7Ora+dxlbhizyV0sQy2kI/BfDMPkRgzvXS7lL4ZuAiwu8RVHL3AxZvgGkIQnDaVuqQGKCgwBtncN3RzSjGqeTU37fQ5fjw0x5IHl4pTGRpBODRUM9Dvw6PCFfFYL5Zipxrif4Q/AkZP73u3j839ES2uau6LAI89a486UUk8kui9/wh/n8xlhSLMVBNhut1gul1iv11gsFtjtdpBSQQjhrKoq7Pd7zOdzrFYrbDYbzGYzTKdTDMOACaPX1ElOllIiiiIcj0ccDgd3UZIk7vY0TZFRZ5kdn/m+73J4P51O8Dzv7xryYgAu5ht5NU2DOI4dkLX265l8ycN/aPgTYCqFse29h7QAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/20293fe128085a9e635e9b72c348cbb1/ca1dc/context_switching.png' srcset='/static/20293fe128085a9e635e9b72c348cbb1/e7570/context_switching.png 170w, +/static/20293fe128085a9e635e9b72c348cbb1/f46e7/context_switching.png 340w, +/static/20293fe128085a9e635e9b72c348cbb1/ca1dc/context_switching.png 680w, +/static/20293fe128085a9e635e9b72c348cbb1/4219d/context_switching.png 866w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure> <a href="https://yoongrammer.tistory.com/53">사진출처</a></p> <p>결국 프로세스 A에서 B로 프로세스가 넘어가는 순간에 프로세스 A정보를 백업하고 그작업이 끝난다면 프로세스 B의 문맥을 불러오게 되며 이 것이 프로세스를 교대하는 방법입니다.</p> @@ -309,7 +2039,15 @@ 혹은 CPU를 사용하는지와 같은 정보를 통칭해서 프로세스 상태라고 부르게 됩니다.</p> <br> <p>프로세스 상태는 크게 다섯가지로 나뉠 수 있습니다.</p> -<p>![img.png](프로세스 상태 전이도.png) +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 600px; '> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 41.76470588235294%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABOUlEQVR42n1S26qCUBDd//8NPfjWH4QgmJm+piX0YEGBpqGkllZ2sXVYA0V4Dmdg2Hsue2atpep0OsHzPOi6jtVqhcfjAdrr9RL/y5jvuk7ueZ5jOp3CMAz4vg91vV6x2WywWCyQpimez+evx//di6JAEAQyLAxDqNvthrquUVWVNHHg+XyW3OVykRxRN00jtfv9/qm3bStDeWZZJn0qSRJEUSQJNu12O8znc4xGIzkZ7/d7YUEG6/Uatm2LREREyfiOM7bbLVSfArewSF3jOBZKHMrFXMqYg5bLpejXN0Vxv53USOlwOEhMimVZSkwkNNYpEfVn/f2R6Kq/gfSI8Hg8SgMRzWYzTCYTQcY8h7CHyN86fhCapolvtywL4/FYnHdqqWkaBoMBhsOhDHZdF47jiFNP/jY86T+NBVPD1U+rPQAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/769c30263c63f230fe373d83485111c5/dface/process_state.png' srcset='/static/769c30263c63f230fe373d83485111c5/e7570/process_state.png 170w, +/static/769c30263c63f230fe373d83485111c5/f46e7/process_state.png 340w, +/static/769c30263c63f230fe373d83485111c5/dface/process_state.png 600w' sizes='(max-width: 600px) 100vw, 600px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure> <a href="https://thebook.io/080367/0021/">사진출처</a></p> <br> <h3 id="1-생성-상태" style="position:relative;"><a href="#1-%EC%83%9D%EC%84%B1-%EC%83%81%ED%83%9C" aria-label="1 생성 상태 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>1. 생성 상태</h3> @@ -341,7 +2079,20 @@ 부르게 됩니다. 부모의 프로세스와 자식의 프로세스는 각각 고유한 PID를 가지며 자식프로세스에서 부모프로세스 PID를 PPID로 가지고 있기도 합니다.</p> <br> -<p>![img.png](프로세스 계층 구조.png) +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/bef6ebdb97b3483509934d474a7c120d/4596f/process_layer.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 34.705882352941174%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAABIUlEQVR42m1R68qCUBD0/V/FwBD7F0hGZlAiphBYgUgWlCF47eZ8zIISHx1YztnLzJndVbquwy/7fD7gyfMcu90OQRAgDEMcj0c8Hg/JseY/Tvl2+iLa6/WS+3q9wnVdLBYLMRIXRSG59/s9fPyT8Pl8oqoq1HWNtm3RNI2oYZzvPs6bflmWYiQeCHvZBM3ncxiGgTiOB7U85/MZk8kEpmkKQa9ou91C13X4vj90NhDyx8vlgtPphPv9Lsq+c1mWSZyj6NXQPxwOuN1ug0plv9+LMpJFUYTlcikFnJVt2wLiYtbrtSyF7VIxMSTjCNiRZVlIkgTKarWCqqqySQ59NBoJ8Ww2g6ZpAuJmx+MxptOpdEBiYhzHQZqm2Gw24nuehz8q2Ak7FVbKdwAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/bef6ebdb97b3483509934d474a7c120d/ca1dc/process_layer.png' srcset='/static/bef6ebdb97b3483509934d474a7c120d/e7570/process_layer.png 170w, +/static/bef6ebdb97b3483509934d474a7c120d/f46e7/process_layer.png 340w, +/static/bef6ebdb97b3483509934d474a7c120d/ca1dc/process_layer.png 680w, +/static/bef6ebdb97b3483509934d474a7c120d/02d09/process_layer.png 1020w, +/static/bef6ebdb97b3483509934d474a7c120d/9d567/process_layer.png 1360w, +/static/bef6ebdb97b3483509934d474a7c120d/4596f/process_layer.png 1549w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure> [사진 출처: 혼자 공부하는 운영체제 저자:강민철]</p> <br> <br> @@ -389,13 +2140,25 @@ PID와 같은 고유한 값을 제외한다면 부모가 가진 리소스를 동일하게 사용하는 대체품이기 때문입니다.</p> <p>그렇기 때문에 자식 프로세스는 자신의 프로세스를 가지기 위해 exec 시스템 호출을 하게 됩니다.</p> <p>exec 호출을 진행하게 되면 자신의 메모리 공간을 새로운 프로그램으로 덮어쓰게 됩니다.</p> -<p>코드 영역과 데이터 영역의 내용이 실행한 프로그램으로 바뀌게 되고, 나머지 영역은 초기화 됩니다.</p><![CDATA[7. 프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기]]>https://catch-npe.netlify.app/7/https://catch-npe.netlify.app/7/Wed, 10 Sep 2025 00:00:00 GMT<h2 id="프로세스란-무엇일까" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C" aria-label="프로세스란 무엇일까 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스란 무엇일까?</h2> +<p>코드 영역과 데이터 영역의 내용이 실행한 프로그램으로 바뀌게 되고, 나머지 영역은 초기화 됩니다.</p><![CDATA[프로세스와 PCB 그리고 메모리 구조에 대해서 알아보기]]>https://catch-npe.netlify.app/jc7/https://catch-npe.netlify.app/jc7/Wed, 10 Sep 2025 00:00:00 GMT<h2 id="프로세스란-무엇일까" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C" aria-label="프로세스란 무엇일까 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스란 무엇일까?</h2> <hr> <p>우리는 흔히 보조 기억장치에 있는 프로그램 정보를 메모리로 적재하고, 적재된 정보를 CPU가 읽어 사용하는 이 과정을 프로그램이 실행되었다 라고 표현합니다.</p> <p>여기서 실행된 프로그램을 <strong>프로세스</strong>라는 개별적인 용어로 부르고 프로그램을 실행하는 과정을 프로세스를 생성한다고 표현합니다.</p> <br> <br> -<p>![img.png](실행중인 프로세스.png)</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/c50860ad005c5135458173453aaf6d35/98b00/process_in_mac.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 19.411764705882355%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAyElEQVR42lWP6w6CMAxGeRhRvHARGINt3AYIGsX3f5rPliVGf5ykXdPTb16mblB6hmkWFNWI46WEMjOEtIhTg90hgx/k2B/FFz8Qf/0vXpq3SEWHuntAk/QcKdhpJd4YCJZLNSHJWjrQEDXVzVaHiUaUGERXs71z7eWUJC961K0TcsLWPtEPL9hxJemKzr5odoeqF5R6QkkHpBpxpTAsv8QKwVnSroSXkYxhWWVuOIUlGkrLUk7JAl7i62Gs6VsFDicHSxyu59kHuTmDd4AUwo0AAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/c50860ad005c5135458173453aaf6d35/ca1dc/process_in_mac.png' srcset='/static/c50860ad005c5135458173453aaf6d35/e7570/process_in_mac.png 170w, +/static/c50860ad005c5135458173453aaf6d35/f46e7/process_in_mac.png 340w, +/static/c50860ad005c5135458173453aaf6d35/ca1dc/process_in_mac.png 680w, +/static/c50860ad005c5135458173453aaf6d35/02d09/process_in_mac.png 1020w, +/static/c50860ad005c5135458173453aaf6d35/98b00/process_in_mac.png 1202w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <br> 위 사진처럼 보이는 것보다 더 많은 프로세스가 작동하고 있는데, 여기서 사용자가 볼 수 있는 프로세스를 포그라운드 프로세스 라며 명하며, 보이지 않는 프로세스를 백그라운드 프로세스라고 부르게 됩니다. @@ -432,7 +2195,15 @@ PID와 같은 고유한 값을 제외한다면 부모가 가진 리소스를 동 레지스터의 값 혹은 상태같이 많은 정보를 담고있으며 이를 알아보고자 합니다.</p> <br> <h3 id="프로세스-ID" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-ID" aria-label="프로세스 ID permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스 ID</h3> -<p><img src="%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4ID.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 136px; '> + <a class='gatsby-resp-image-link' href='/static/e725b4a468cf14c8f8ccbb0269bd33e0/bd637/process_id.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 144.11764705882354%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAdCAYAAACqhkzFAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEwklEQVR42m1W91NiSRB+f8jV7rIKJnLOOScBiYJEUTCuiq7htryrurp/u6+/hmGxvB+G9968edP9he5B023baHvHQVsGBxn2XLSz75aBe8xjfNFZ6Ot3C+m2rfRty0o6ve3D2s2hdboTKh62KV9q0r7JJwsx9k1eSmWqMj8Yz6nXn1L1qEe1xgm1jkdkc0ZIv+v8vGGbN2x2RtTpTchkDaw3NFr8VKl1qX08pl/v/9DL21909/BCi6c3enh8I7cvQXpet3vgWQ/ZED+IZrYFP0E2WYNktYfpj69GgQxacG+0BISK73o7z9n5apN7fKMh+vPrO0d9pQPzb8gHZj+9//0vgZJ6a0DXt480mlzQ2exWRvdkKqjwDihOBucUCGVJS+eOKFuoUzJ9SHtG7yo7N+0xh7FkiTz+FAUjOcrxmliyTPlyk/AN7r2BFHl8SYryunA0LzRp5UpH1EPK2AxcLEXxkS+YFjrwkdubIDvfh/jDLzozOdwxcvEcRjCco12jh0ViyPeL17VloJpeQeYNJ9MrhnkpsLus8uTsmuGNOOsklTiRU34/u7yj2cWdwAWvmtURJhOTjExwb7aFPoiDRRBEv+Ncq2nhNaAHKDA+qAyPVdhfzfZQxJlzRATAglZnLNaZnt9KwO3VpoYN//0Ojk15Q3AC0pFdgoUJhLMSHfDBHczdaA1p3+hbVw42UXZBEKwFbbhquWJdVE6kDimTP2IFaysoXsoXG+T0xtnESRHB7oqK6vBhOFagaKIkw+mJk5fn4VlNlV29ORB/lSptyQDQFk9/0vzqnsanlwK91z+jy+sH8ocyTFNXqqZ9PKFTFuvmxxNl2E4aKgQfQ35UhvIixje2E2BI89ixr6rDJvC2DDZpFAhusYdkXiqlP5rRERd8lSP+fHlna1ytFTtq9AmUIBvYBsIhy3qzLw1lzJZCdqlMRSomGMmTBg4gCrKL8T14U1nGUmWKxovCYSJdEX5RPXGeT7JY8Cfex5l/CIpENGxSYA4Pa8fyEfqjsgMWo1pgWpQVuhGEwUCtwxl2V0yEAmw8a4PRXMhHxVxeL9alhyxLDKtc7XDAllTD1c0jN4RTGnKTwHfojUP28e39szQHBNcQDTZAROV6JQpqE1Fxj3fIAiJhLQLucf0i6wPL8llKD0QPxxfSPJGFkRcr22SYM/DUH56LIC1uxKhvcAqlFRp0J9VYNLQhmBqEQxxVSsjO6YmJoUF6OFoQQaA6+ubSOsvqUNYS2+RYVWzmC6Qpm6+zyRvr9oV5+BN9D7WsRIFAoWhOEkAfdKGaeJ2ZnaKh3FLZqpwrgI1OrGyDLn4+/yGQIRDgz/jZF8xQmSsK71vcrUHZ1c1CEtAQFRtYHRHpgXhWogAaeAEcwIIoyAJzQLCkxinCoUlI+4IVnrlCavUTyWQ6u1kTjIxAQ7Xe40roL49RXod3OF9gFVgH2UM0OVOyDDlfbErXgNtBATI2sChxFgx0eNlfSTZ9hI0ekrMjwG0uJx7NFRpSGOlsbXmmQAw/90BUTCRekD6njA2IUNnPnCkqAH95VcenbdUwVsdofzgjDETDFRyp8wVQUPxPz7+kPUFxzG8e7p8OeuV6PGy2LpUlYGCxuv7f/5nNvyL/AR5b+GPeKm9MAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/e725b4a468cf14c8f8ccbb0269bd33e0/bd637/process_id.png' srcset='/static/e725b4a468cf14c8f8ccbb0269bd33e0/bd637/process_id.png 136w' sizes='(max-width: 136px) 100vw, 136px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <p>프로세스 ID(PID)는 프로세스를 식별하기 위해 존재하는 고유 ID입니다. 메모장을 두개 킨다고 할지라도 다른 프로세스ID가 만들어지는 것처럼 중복된 활동이여도 하나의 프로세스는 고유한 ID를 가지게 됩니다.</p> <br> @@ -454,7 +2225,17 @@ PID와 같은 고유한 값을 제외한다면 부모가 가진 리소스를 동 <h2 id="프로세스의-메모리-영역" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%98%81%EC%97%AD" aria-label="프로세스의 메모리 영역 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스의 메모리 영역</h2> <hr> <p>프로세스가 생성되면 커널 영역에 PCB가 생성됩니다. 그렇다면 커널 영역이 아닌 사용자 영역에는 어떤 데이터가 들어갈까요?</p> -<p><img src="%EB%A9%94%EB%AA%A8%EB%A6%AC%EA%B5%AC%EC%A1%B0.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 487px; '> + <a class='gatsby-resp-image-link' href='/static/47d51a17aabda41526b35a01c6d7316b/6a170/memory_model.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 98.23529411764706%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEXUlEQVR42o2VW2hUVxSG89jHQtuH0re+9UWKD8VSWwpFKS2oaBUvUSQai5pqqUWNVqnYNmChYAuiiNqGFh1jLiaZTJ1MZjLXM3POnDkzOZlL5n7LpUZjrCZOnMx83c4UjCi0G/5z2Ju1v7X2Za3dwJJWrUJFfJ7o+VZ9rlep1ucsNW94sTmUhfXE3yXsmVnO+ib5xTuJJTFDYnqOB6WygLzI6b/Aai26KlMPSrhzs1xUpzgylGNrT5K1HQk+NST4vD9D66083w4VOOsepyM0jTd7n8nZR5TLizXKE0ZD3U+FS/5xmvvTNHYLyPUE6zqSbOpKsbknzRahvQNZjg4WOCGAp23jtNmKnBku1v6tg3l8uZmnET6cmea7wRgbe7K0mAscG55k3595dhmzNAttv5lmV1+GQ7dytFoKHBZqMRfZPlBgc2+ONR1xerUULC7UgQaDAcvQEBZF51d3hHY5wxl3kSZTnq3GArtNBQ6K6HYKwDahHcLJAVOCNvMo7VYVq0ems7MTr9dbB87Pz+PzSngcw+h+HwFFQZIV+twa56w6p6wpTjgmaqu4bAsy4PDicjqQncNCduzWIZKJBJVKpQ4sl8sosozT4cTpdCF5JNxOJx67DdXtwGwycuH8eWSXA5/Dhls4djoc2IWcws4qVpfNZp/u4fj4OF7Jg+z1oAX8NbjP50WSJCSvrzbJaDSKMRm3xyOic9WATvswLgG326yER0eZm5urA/v7+hi02HC4/Lg8fmRFJRQKEQmPCkOdYFAjHA6jqn4CwqGqKsKpgsfrx+EO4Har9Pcb0TStDozEMkyFzjAdbCMZ6GE04CGgavjEIcn+EGpAq0EVvxjzj4gxHdUfIOy3kFOvcMf/BfeL5tp9bqiUF0jm/uLuwFcgfQzZ/dyLHGUy9AMT+mXSI4Ni0y1cudxOWJNIB7u5EznHQvok5Fsgto3Hxve5q3bUgTO3b6OMRYms20v4lbcoNq4m880a4uc38FjZAYW9PEq3ihWcguIhSDZTlRqZu7SeqT2rSK1YidbwJtkLV+uHslAqEUsmGblxE3XfSbR3tpDZ0EJmuYC+vozCJyuZbVvLQtdOpr9cTfa9d4m+vAz9peUE31iFuroZ3+HvyQaCT085nUpiCehI0Qh6NIRiNhO89Acje04QensT+msfEH51BaHXPyL0YRP6sR+JXO8iovoIxXRMgRDhTL4OrOXyYonjpjF292b42Z7i4qDCVauLQDxKNK4TE/dsrKuXmNdNOBlBiY8xoCe54IrTak6x5toYPSPFJUCxnb1ylIMGiUaDxhFLjq8tRfabsvxkT9It8tQubsLvcpLT1nQtv9d3JllniNBkUDnZ5SWan3q2Hj6pOAsPZ0lnc9h8GhfNCgc6fGy8FuKzG3Ga+tKiCsXYfk3jeLdMu01FHolwe2qSSmnuvwssi2Xm798jkUphlIL8ZtNwamEmRFYtzj94ZkZ1Sa/h2Seg+r+fgMrS52KJ/T9wi0nqe6Y2LgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/47d51a17aabda41526b35a01c6d7316b/6a170/memory_model.png' srcset='/static/47d51a17aabda41526b35a01c6d7316b/e7570/memory_model.png 170w, +/static/47d51a17aabda41526b35a01c6d7316b/f46e7/memory_model.png 340w, +/static/47d51a17aabda41526b35a01c6d7316b/6a170/memory_model.png 487w' sizes='(max-width: 487px) 100vw, 487px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <p><a href="https://www.programmersought.com/article/98613694619/">사진출처</a></p> <p>위 그림처럼 하나의 프로세스는 크게 코드영역(Text), 데이터 영역(Bss,Gvar), 힙 영역(Heap), 스택 영역(Stack) 4가지로 나뉩니다.</p> <p>차례대로 설명하자면,</p> @@ -488,8 +2269,8 @@ CPU가 실행해야 하는 명령어가 담겨있기 때문에 읽기모드만 <p>그림을 보면 unused memory영역이 있는데, 스택 영역과 힙 영역이 동적이기 떄문에 힙은 아래에서 위로, 스택은 위에서 아래로 주소를 할당하게 됩니다. 그렇게 되면 서로 충돌없이 동적으로 값을 할당할 수 있기 때문입니다.</p> <p>여기서 만약에 힙이나 스택에 많은 정보가 담겨서 서로의 지점을 충돌 할 수 있는데, 그럴때 각각 stack overflow, -heap overflow라고 부르게 됩니다.</p><![CDATA[6. 동기식/비동기식 I/O의 차이와 활용 사례]]>https://catch-npe.netlify.app/6/https://catch-npe.netlify.app/6/Tue, 09 Sep 2025 00:00:00 GMT<h2 id="IO란" style="position:relative;"><a href="#IO%EB%9E%80" aria-label="IO란 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>IO란</h2> +heap overflow라고 부르게 됩니다.</p><![CDATA[동기식/비동기식 I/O의 차이와 활용 사례]]>https://catch-npe.netlify.app/jc6/https://catch-npe.netlify.app/jc6/Tue, 09 Sep 2025 00:00:00 GMT<h2 id="IO란" style="position:relative;"><a href="#IO%EB%9E%80" aria-label="IO란 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>IO란</h2> <p>개발을 하다 보면 I/O라는 용어를 자주 듣게 됩니다. I/O는 Input/Output의 줄임말로, 컴퓨터가 외부와 데이터를 주고받는 일련의 작업을 통칭 I/O라고 부르게 됩니다.</p> <p>예시를 들어서</p> @@ -528,18 +2309,231 @@ heap overflow라고 부르게 됩니다.</p><![CDATA[5. 인터럽트와 DMA를 통한 효율적 입출력 처리]]>https://catch-npe.netlify.app/5/https://catch-npe.netlify.app/5/Mon, 08 Sep 2025 00:00:00 GMT<h2 id="인터럽트-기반-입출력" style="position:relative;"><a href="#%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8-%EA%B8%B0%EB%B0%98-%EC%9E%85%EC%B6%9C%EB%A0%A5" aria-label="인터럽트 기반 입출력 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>인터럽트 기반 입출력</h2> +<p>이러한 방식의 특징은 구현의 복잡성이 높다는 것이지만, 대용량 데이터를 처리하는데 여러 IO작업을 동시에 처리해야 할 떄 유용합니다.</p><![CDATA[4. 쓰레드 ]]>https://catch-npe.netlify.app/hs4/https://catch-npe.netlify.app/hs4/Mon, 08 Sep 2025 00:00:00 GMT<h2 id="쓰레드란" style="position:relative;"><a href="#%EC%93%B0%EB%A0%88%EB%93%9C%EB%9E%80" aria-label="쓰레드란 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>쓰레드란?</h2> +<p>쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다.</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/a7b597dfa9cba39331beac7d6735ed14/0eb09/img.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 94.70588235294117%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAADg0lEQVR42pWUbUhTYRTHl+XMhZsWgq1aZS/Si718qIQICaUoP9lHozA/SBBBHyKyL8sgqIw+9CIYtNxyFisdG45tWrbUtfZic2up02X0pmRFQTmZu/eeztndXXeWH3rgf5/73Ps8v+ec85znSCTpbR49srOzl0mlsgNKpbIoL0+5QqFQrFapVIW5uQUr8fd8yX+0DHrk5OQswW45aj2qDLUXtQu1Qa1WZwBAhrC52JDZbV5yoqSioqrw8uW2cwZD0GQ0jrqMxpHner3/4cWLLSd27DhYQHMMBsN8EWidYIwYRj+lDQ3tF2y28ejwMMDICHDUh8MAo6PAvX4NYDa//Vpff/c4LRIMwLZFDBR2WXjpkuHRwAAHfj/D9vT8ZNzuGcbjYVivl2X7+qbiKObVK2BdrilQq5uvigwqTgGFXW7etF9/+vQbPHgQnLl/P8C1t4cBAdDfD/DyJYDdPgEGQ4jEYhjidvs4nD+vPUlrZTLZtjSXq6vr9jgcn9mhIWDRXa6lxQdoCfh8HAoSIijJ76cxyw4OAlitY5MbN+5WIaKotLR0QQqo0TzTUKxwQdzh+A4E5Bf+AZLQdXA4fiR6HMcppteuGU8jYmVtbVOmwJMZjeFh2tHjYVmCeDzxNJAgcr+xsQt6e3/RO0NG6PVuOzJWJXO0SFJZeXip2RyJBoMJIPcvkFgETMaWJQsxpYYoPzMzF9FJl0tqak4ozeaxmUAg4RInxOtfMK+XQ+BjcDqjNGb5NIqEKW2k0hy6BNvJ5VyTKfwhFEqAuK6uSTCZxmBggAeIgbSR1foJXK4YjRk8RMwKv5NczcrK2o/9pkQQW1u9ZooHHgRDCzQaJ/AWc39ZyR8W/YM4rWlq6ryCiDV438m6JQlgXV1Tlc8Xo1RhOjreQ3PzizmB/KGxHIK57u4J5ujRMzsJmJY2VEG0WteTd+8ALJaPMzqdd04gxRkPJIbXEm7csN7mEzt3a6oKUfWgvqRk39q2tsE3eGfRglgcYQy6RdeO4wUsWsZgbOORCIBW6+7BZYqkQdvSypoALSs7VKjRuPoCAY4KAke3hSwlhUL8N7d7Gm7d6nyoUKjyRB5unl1tUlCqOGfPNh7R6dwOm21isrPzyzSefNRi+TB+505vx6lTDRXiUoctC3UvdcKzoaKJkvz8/ILKymNby8uriuVy+WLhO81Jljuh7UPJ6e03LAEFr08FZd4AAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img' title='' src='/static/a7b597dfa9cba39331beac7d6735ed14/0eb09/img.png' srcset='/static/a7b597dfa9cba39331beac7d6735ed14/e7570/img.png 170w, +/static/a7b597dfa9cba39331beac7d6735ed14/f46e7/img.png 340w, +/static/a7b597dfa9cba39331beac7d6735ed14/0eb09/img.png 500w' sizes='(max-width: 500px) 100vw, 500px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<p>그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다. +이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다.</p> +<blockquote> +<h4 id="사용자-수준-쓰레드와-커널-수준-쓰레드의-차이" style="position:relative;"><a href="#%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%88%98%EC%A4%80-%EC%93%B0%EB%A0%88%EB%93%9C%EC%99%80-%EC%BB%A4%EB%84%90-%EC%88%98%EC%A4%80-%EC%93%B0%EB%A0%88%EB%93%9C%EC%9D%98-%EC%B0%A8%EC%9D%B4" aria-label="사용자 수준 쓰레드와 커널 수준 쓰레드의 차이 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>사용자 수준 쓰레드와 커널 수준 쓰레드의 차이</h4> +<p>사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다. +쓰레드와 관련된 모든 행위를 사용자 영역에서 하기 때문에, +커널은 사용자 수준 쓰레드의 존재를 알지 못하고 쓰레드 교환에 개입하지 않습니다. +커널 수준 쓰레드란, 커널이 직접 생성하고 관리하는 쓰레드를 의미합니다.</p> +</blockquote> +<h2 id="쓰레드의-메모리-공간" style="position:relative;"><a href="#%EC%93%B0%EB%A0%88%EB%93%9C%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B3%B5%EA%B0%84" aria-label="쓰레드의 메모리 공간 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>쓰레드의 메모리 공간</h2> +<p>같은 프로세스의 쓰레드는 프로세스로부터 각각의 스택을 나눠갖지만 Code, Data, Heap 메모리 영역을 공유합니다. +하지만, 쓰레드 ID, 스택, PC나 레지스터 같은 쓰레드 컨텍스트에 대해서는 각기 다른 값을 가지고 있습니다.</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 640px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/40d30535729a7736f7b9b7389df7c584/0f09e/img_1.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 61.1764705882353%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABrElEQVR42nWS54oEMQyD8/4vtg22995ne29s0/EJctyfGwjJ2LEsyQm9Xk/tdluXy0X3+12Px0O3203r9Vrj8Vj9fl/X61X1et3nzWajRqOhTqej5XIp6pvNpuOr1UrhcDgofsPhUPl83oXb7Vav18vx5/OpbDarQqFg4Ewmo1wup3K57JVKpdyEBmG/37vo/X5rsVi4G8xgGAFhDpPRaOR8q9XSYDBQrVZzrNvtOk99IDmZTAyItOPxqNPppOl0asZJkpghDc7ns2URw6L5fP4bRyk1ATYE8A2pgHOROL5QyGWk8Q9D5MIG70ulkmtgyh7wI51Oq1qtajabWSIgsOMy3lUqFcuKPhPnozHefb9fK4NEgCZewZAzYDCmI/5ixW6381QjYLFYdA33AcQqhmhAJge7v3IjIBNlIQ1AWDAMAGkCQJwuy5K5zIEAkqFPR5gQhwX7f5Jp+Pl87DMkAibTNRYDiGySFJODPc+Cj3gEZNoREPYGhD7UScYngmTAkEkT8jwvmgHMxLkHQPSQ52RAaPPu6AAQ5rKIMxSkkOOZAM6OPZyxiHfIHs8/u3J1+oO6sAQAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 1' title='' src='/static/40d30535729a7736f7b9b7389df7c584/0f09e/img_1.png' srcset='/static/40d30535729a7736f7b9b7389df7c584/e7570/img_1.png 170w, +/static/40d30535729a7736f7b9b7389df7c584/f46e7/img_1.png 340w, +/static/40d30535729a7736f7b9b7389df7c584/0f09e/img_1.png 640w' sizes='(max-width: 640px) 100vw, 640px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<p>이렇게 각자의 PC, 레지스터, 스택을 가지고 있기에 쓰레드마다 독립적으로 실행할 수 있습니다.</p> +<p>여기서 중요한 점은 프로세스의 쓰레드들은 실행에 필요한 최소한의 정보(PC, 레지스터, 스택)만을 유지한 채 +프로세스 자원을 공유하며 실행된다는 점입니다.</p> +<h2 id="TCB쓰레드-제어블록" style="position:relative;"><a href="#TCB%EC%93%B0%EB%A0%88%EB%93%9C-%EC%A0%9C%EC%96%B4%EB%B8%94%EB%A1%9D" aria-label="TCB쓰레드 제어블록 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>TCB(쓰레드 제어블록)</h2> +<p>쓰레드 또한 프로세스의 PCB(프로세스 제어 블록)처럼 TCB(쓰레드 제어 블록)을 통해 관리됩니다. +TCB는 각 쓰레드에 위치하고, 커널은 TCB를 통해 쓰레드를 관리합니다.</p> +<p>그럼 TCB에는 어떤 정보가 담겨있을까요? +TCB에는 아래와 같은 쓰레드의 메타데이터들이 담겨져 있습니다.</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/b009f54f495c2708b55ef5e9c2924fbf/78d47/img_2.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 55.294117647058826%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAACP0lEQVR42nWS6W7aQBSF/f4vUik/UokmjbJACQmEJexbMCYsNrbBLIYAAWP763hAaaWqI13PeO52zrmjBIHPYr6g997HNC3GpsloNEIXZtk2hmEwHA4wx2N5lveWxf+WEn3CMJQ/u/2BQq1L35jiByFtTafYeGfvHVltdtI3GDuccs550qItiG5RzrXomSti6R6x+xeqHR1P+B8LTa5+Ffj0Quz5hsvbNC3N4G8Q/yD0fZ+D5/M9paJP15iOy3qzl053vcOYuvIchFHRNfP1XoI6HAMGPRXbGPGx3aG166xcF6XUGXOXaXCXrlNoDpm6O5F86hbR3nz6zBwHVwQHorkpNHaWH2z2AYXHW9rlHPZ0wfP1BY5loGRrA0HlhYvrJ5KvXSbLLUc//KK12nrk4te0ynnG1oynq28sndNQFu6Kj00UHzCbLwVTD6XStfiZfJX6ZOtDIf6e7f74pUlEdWIazGcO+8MBTVXJVAdsPz2Wto6hNYW1WM0mMlZpvDukih3i2SZl1caVBX0ibaMCkV4Rdf+sQ5QUL+v8SKtUX5KUUrcUkze0KwUZq1S1iaDaIZF/o9ix2exEQQ/eGg0amQemQoJyOkG3WcGaLsk9xCRlMRO0ao7S4w31zL1A2ZbaK/mWTixR5PIuS6LQFUM4SCTGoE+3Jp7M4YjaKKP3e1Kvev6Z1XIhEWvVPLVMnFr6gVG3daJcETTfRnNagxltsW92hy9q59nIzkH4R9NoeWIAplpBKz2hFVNMBipBEPIbxqww+OhgS2QAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 2' title='' src='/static/b009f54f495c2708b55ef5e9c2924fbf/ca1dc/img_2.png' srcset='/static/b009f54f495c2708b55ef5e9c2924fbf/e7570/img_2.png 170w, +/static/b009f54f495c2708b55ef5e9c2924fbf/f46e7/img_2.png 340w, +/static/b009f54f495c2708b55ef5e9c2924fbf/ca1dc/img_2.png 680w, +/static/b009f54f495c2708b55ef5e9c2924fbf/78d47/img_2.png 800w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<ul> +<li>쓰레드 번호(TID, Thread ID): 각 쓰레드의 고유 식별 번호입니다.</li> +<li>스택 포인터 (Stack Pointer): 쓰레드가 존재하는 프로세스의 PCB에 대한 포인터</li> +<li>프로그램 카운터(PC, Program Counter): 이 쓰레드에서 실행될 다음 명령어의 주소를 가리키는 포인터(주소)입니다.</li> +<li>쓰레드 상태(Thread State): 쓰레드가 현재 어떤 상태인지를 나타내는 정보(new, ready, running, waiting, end)입니다.</li> +<li>레지스터 상태(Register State): 쓰레드의 레지스터 값 세트입니다.</li> +</ul> +<p>각 프로세스에 대한 중요 정보를 강조하는 특정 정보가 쓰레드 제어 블록에 저장됩니다.</p> +<h2 id="프로세스와-쓰레드의-차이" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%93%B0%EB%A0%88%EB%93%9C%EC%9D%98-%EC%B0%A8%EC%9D%B4" aria-label="프로세스와 쓰레드의 차이 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스와 쓰레드의 차이</h2> +<p>프로세스는 각각 독립된 메모리 영역(Code, Data, Heap, Stack)을 할당받고 고유 프로세스 ID를 가지는 특성으로 인해, +프로세스끼리는 서로의 영역에 접근할 수 없습니다. +그래서 한 프로세스가 다른 프로세스의 자원에 접근하려면 IPC(inter-process communication)을 사용해야 합니다.</p> +<p>하지만, 쓰레드는 IPC와 같은 별도의 통신 방법 없이도 앞서 언급한 것처럼 프로세스의 Code, Data, Heap 메모리 영역을 공유합니다.</p> +<p>이처럼 프로세스들 사이의 통신에 대한 어려움 해소 및 빠른 컨텍스트 스위칭으로 인해 쓰레드가 프로세스보다 더 가벼운 실행 단위로 사용됩니다. +이로 인해 현대에 와서 운영체제의 실행단위는 프로세스에서 쓰레드로 바뀌어 가고 있습니다.</p> +<h2 id="동시성-환경에서의-차이" style="position:relative;"><a href="#%EB%8F%99%EC%8B%9C%EC%84%B1-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C%EC%9D%98-%EC%B0%A8%EC%9D%B4" aria-label="동시성 환경에서의 차이 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>동시성 환경에서의 차이</h2> +<p>동시성 환경에서는 어떤지 알아볼까요? +여러 프로세스를 동시에 실행하는 멀티 프로세스와 한 프로세스에서 여러 쓰레드를 동시에 실행하는 멀티 쓰레드가 있습니다.</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/689af89b5d61dc8fbd716fd44627044a/18380/img_3.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 57.05882352941176%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB2ElEQVR42mVRiZKiUAz0//9JHQeVQ8BZFQQdFZ3yKO/7xNfzOlu4s7upSr2Qo7sTct1u9xG1IxVHsfJcX3XijsRBECoAatBPVM12VRzHqtPtqlazpcKgrb87qh1Gqu59KN+rq/v9Lv25uv+R2pYNt+aiUq6i5riwLQcaHLQwCFGtmDpfQ6FQgG3auuahVHqHWbWgyVA2KtCA0p/zfT8tFouwLEsPVmGZFkzTRONXQxqCIIDjOCBpPp+HbWty14VhGCiXyyLEsZ0/gMNkmA4GCRLtX6MvjEYjDPoDeWntdhulYklUFgtvosrUcemtBOPd0HEVlZ8KD4dDykAphZ+m8/J+dj+1whoajaacRN8QrVZLYqprNpvwPB+Xy+U34H6/F8DZbCaNw+FQ2DLAJEkQRRH6/b4e9ASAQIyZ7/V6MpcJegGeTicZ3mw2UswAt9st5vM51uu1vCRm32KxwGq1kldj4PF4iL9WppHtfD6/Vn4+n7jdbphMJuKs7XY72YIrEigMQ5njBuPx+H9AKv0XcDqdirNGxfxhGThnlsul9P31U2iUnN2CgIwJkqap1HgOxsxT3fV6FVKq5SuAmiVlM4v8GWSik53GwSzHe7GH/bzf8XgUAvZkgN9c0iuWgXRTWgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 3' title='' src='/static/689af89b5d61dc8fbd716fd44627044a/ca1dc/img_3.png' srcset='/static/689af89b5d61dc8fbd716fd44627044a/e7570/img_3.png 170w, +/static/689af89b5d61dc8fbd716fd44627044a/f46e7/img_3.png 340w, +/static/689af89b5d61dc8fbd716fd44627044a/ca1dc/img_3.png 680w, +/static/689af89b5d61dc8fbd716fd44627044a/02d09/img_3.png 1020w, +/static/689af89b5d61dc8fbd716fd44627044a/18380/img_3.png 1277w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<p>여기서 가장 큰 차이점은 프로세스끼리는 기본적으로 공유하지 않지만, 쓰레드끼리는 같은 프로세스 내의 자원을 공유한다는 점입니다.</p> +<p>즉, 멀티 프로세스는 여러 프로세스를 동시에 실행해 각각의 독립적인 프로세스 간 자원을 공유하지 않기 때문에 프로세스 간 통신 (IPC) 방식을 써야 합니다. +또한, 메모리에 동일한 내용들이 중복해서 존재하기 때문에 메모리에도 부담이 될 수 있습니다. +그러나 한편으로는 자원을 공유하지 않는 덕분에 하나의 프로세스에 문제가 생겨도 다른 프로세스들에는 문제가 발생하지 않는다는 장점이 있기도 합니다.</p> +<p>반면, 멀티 쓰레드는 실행에 필요한 최소한의 정보(PC, 레지스터, 스택)만을 유지한 채 프로세스 자원을 공유하며 실행되기에 +커널의 개입 없이 쓰레드간 통신을 할 수 있고, 메모리에도 부담이 덜합니다. +또한 fork로 인한 생성이 공유하는 부분을 제외한 부분만 복사하면 되기 때문에 프로세스보다 빠릅니다.(쓰레드가 접근하는 공유 데이터에 대해 동기화 작업을 수행해야 합니다) +<br> +하지만, 하나의 쓰레드에 문제가 생기면 같은 프로세스 내의 다른 쓰레드들에도 문제가 발생할 수 있다는 단점이 있습니다.</p><![CDATA[3. 프로세스]]>https://catch-npe.netlify.app/hs3/https://catch-npe.netlify.app/hs3/Mon, 08 Sep 2025 00:00:00 GMT<h2 id="프로세스란" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%9E%80" aria-label="프로세스란 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스란?</h2> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/733f5c69ef10b108434bafdb95c48f34/a91f8/img.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 57.64705882352942%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAACM0lEQVR42mVTyU5iQRR938APdVy3SzckdFjgsl3RIaT9An+ADUskMQwbe8NgBG0CCCYmYoIMCjxGQZpRkcnTdS7BNq9vUqmq+6rOPfecetpkMkGn08F6vQaDc7vdRrlcxv39vXx7f3/HNozrz3uGlsvlkEwmUSqVMBqN0O12YbfbYTabsbe3B4fDIfnBYAAWH4/HiEQi8Pv9CIVCcjeTyaBQKGwAubi9vRVAMuMcjUZhs9lgtVpxdnYmRZgnWwLzm8lkwtHRkYCFw2HEYjHpTqvX66hUKmg0GlKhWq3C5XIhn88jlUrJevuN8fT0hHg8LiDn5+cIBoM4Pf2Fy8vfWC6X0J6fn6Vyv9+XC2Szv78Pi8UCp9OJw8NDyW31/awj97yv6xXUalVMp1NoMASrJBIJBAIB+Hw+XFxcfAAZY7FYKMYd5HJVBdhWhdb/ALdVja5xz4sEJQO2T62ZY0xU7vp6pKQaq7OrjSkejwcPD+UPgNVqhV6vJ45SY55ha1yTMTuo1Wpybv72pkwtq31zw9Dh+IGdnS9Kq58K9BEvLy9iktfrhdvtFjbMkR21TqfTyGazKBZLAspxdTXAY2Wo6CiGBwffsbv7FZxvbm7kEp/IycmJODgcDqU9zjSOg2uy5YtotZpqdJSWXcVYuXx87FHv7ZuYMJ/PpWXqVSwW5elstZrNZvJkdF0XIErCs2+q5WRSR7HUoe/Q2E6r1cLr6+t/ZlAjo0nGX44k7u7+oNnamPIX8upapBYaCjoAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img' title='' src='/static/733f5c69ef10b108434bafdb95c48f34/ca1dc/img.png' srcset='/static/733f5c69ef10b108434bafdb95c48f34/e7570/img.png 170w, +/static/733f5c69ef10b108434bafdb95c48f34/f46e7/img.png 340w, +/static/733f5c69ef10b108434bafdb95c48f34/ca1dc/img.png 680w, +/static/733f5c69ef10b108434bafdb95c48f34/a91f8/img.png 960w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<p>컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 <a href="https://ko.wikipedia.org/wiki/%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99)#:~:text=%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4(instance)%EB%8A%94%20%ED%95%B4%EB%8B%B9%20%ED%81%B4%EB%9E%98%EC%8A%A4%EC%9D%98%20%EA%B5%AC%EC%A1%B0%EB%A1%9C%20%EC%BB%B4%ED%93%A8%ED%84%B0%20%EC%A0%80%EC%9E%A5%EA%B3%B5%EA%B0%84%EC%97%90%EC%84%9C%20%ED%95%A0%EB%8B%B9%EB%90%9C%20%EC%8B%A4%EC%B2%B4%EB%A5%BC%20%EC%9D%98%EB%AF%B8%ED%95%9C%EB%8B%A4.">인스턴스</a>를 의미합니다. +여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다.</p> +<h2 id="프로세스의-메모리-공간" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B3%B5%EA%B0%84" aria-label="프로세스의 메모리 공간 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스의 메모리 공간</h2> +<p>프로세스는 다음 4개의 메모리 영역으로 구성되고 <a href="https://ko.wikipedia.org/wiki/%EA%B0%80%EC%83%81_%EB%A9%94%EB%AA%A8%EB%A6%AC#:~:text=%EA%B0%80%EC%83%81%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EB%98%90%EB%8A%94%20%EA%B0%80%EC%83%81%20%EA%B8%B0%EC%96%B5%20%EC%9E%A5%EC%B9%98(%EB%AC%B8%ED%99%94%EC%96%B4%3A%20%EA%B0%80%EC%83%81%EA%B8%B0%EC%96%B5%EA%B8%B0%2C%20virtual%20memory%2C%20virtual%20storage)%EB%8A%94%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EA%B4%80%EB%A6%AC%20%EA%B8%B0%EB%B2%95%EC%9D%98%20%ED%95%98%EB%82%98%EB%A1%9C%2C%20%EC%BB%B4%ED%93%A8%ED%84%B0%20%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%97%90%20%EC%8B%A4%EC%A0%9C%EB%A1%9C%20%EC%9D%B4%EC%9A%A9%20%EA%B0%80%EB%8A%A5%ED%95%9C%20%EA%B8%B0%EC%96%B5%20%EC%9E%90%EC%9B%90%EC%9D%84%20%EC%9D%B4%EC%83%81%EC%A0%81%EC%9C%BC%EB%A1%9C%20%EC%B6%94%EC%83%81%ED%99%94%ED%95%98%EC%97%AC%5B1%5D%20%EC%82%AC%EC%9A%A9%EC%9E%90%EB%93%A4%EC%97%90%EA%B2%8C%20%EB%A7%A4%EC%9A%B0%20%ED%81%B0%20(%EC%A3%BC)%20%EB%A9%94%EB%AA%A8%EB%A6%AC%EB%A1%9C%20%EB%B3%B4%EC%9D%B4%EA%B2%8C%20%EB%A7%8C%EB%93%9C%EB%8A%94%20%EA%B2%83%EC%9D%84%20%EB%A7%90%ED%95%9C%EB%8B%A4.%5B2%5D%20%EA%B0%81%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%97%90%20%EC%8B%A4%EC%A0%9C%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EC%A3%BC%EC%86%8C%EA%B0%80%20%EC%95%84%EB%8B%8C%20%EA%B0%80%EC%83%81%EC%9D%98%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EC%A3%BC%EC%86%8C%EB%A5%BC%20%EC%A3%BC%EB%8A%94%20%EB%B0%A9%EC%8B%9D%EC%9D%B4%EB%8B%A4.">가상 메모리</a> 공간에 독립적으로 형성됩니다.</p> +<ul> +<li>코드 영역(Code) : 프로그램 실행 코드가 적재되는 영역입니다. 읽기 모드만 지원합니다.</li> +<li>데이터 영역(Data) : 프로세스의 초기화 된 데이터들인 전역 변수와 정적 변수들이 적재되는 영역입니다.</li> +<li>힙 영역(Heap) : 런타임 동안 생성된 데이터를 보관하기 위해 동적으로 할당받는 영역입니다.</li> +<li>스택 영역(Stack) : 지역변수, 매개변수, 리턴 값, 복귀 주소 등이 저장되는 영역입니다.</li> +</ul> +<p>이렇게 영역이 나눠진 이유는 최대한 중복적인 데이터를 방지하여 메모리 사용량을 줄이는데 목적이 있습니다.</p> +<blockquote> +<p>예를 들면, 코드에서 공통으로 사용하는 부분을 전역 변수로 지정하는 행위와 같다.</p> +</blockquote> +<h2 id="PCB프로세스-제어-블록" style="position:relative;"><a href="#PCB%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%A0%9C%EC%96%B4-%EB%B8%94%EB%A1%9D" aria-label="PCB프로세스 제어 블록 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>PCB(프로세스 제어 블록)</h2> +<p>커널은 시스템 전체에 대해 레지스터에 하나의 프로세스 테이블을 두고 모든 프로세스의 정보를 관리합니다. +여기서의 프로세스 정보는 해당 프로세스를 실행하기 위해 필요한 정보들로 컨텍스트라고 부릅니다. +여기서 프로세스의 상태에 따라 프로세스를 교체하는 작업인 컨텍스트 스위칭 작업 이루어 지는데, +이와 같은 상황에서 여러 프로세스를 관리하기 위해 각 프로세스들에 대해 식별이 가능해야 관리가 가능하기에 해당 프로세스의 정보가 필요합니다.</p> +<p>예를 들어, 인터럽트가 발생해서 자원을 할당받은 프로세스가 대기 상태가 되고 다른 프로세스를 실행 상태로 올릴 때 +대기 중인 프로세스를 나중에 다시 수행하기 위해 대기 중인 프로세스의 상태와 같은 정보를 알아야 할 것입니다.</p> +<p>운영체제의 커널은 이러한 이유로 활성된 프로세스를 관리하기 위해 해당 프로세스에 대한 정보를 PCB(프로세스 제어 블록)이라는 데이터 구조에 저장합니다. +("PCB는 운영 체제가 프로세스를 표현한 것이다."라는 말도 있습니다.)</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/7009ef4a51375d12242d8343c8488a8d/2876f/img_1.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 65.88235294117646%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAABe0lEQVR42lXTR47DMAwFUN//ekF67723pYLHAQ3PglFE6hdScvV8Psvr9Sr3+70sl8syn8/LZDIp8p/PJ2ri/X7X/9USJ581ucqPxH6/L9PptOx2u9LtdstqtSrn87mcTqd6vV6v/4j9T/LH4/FHKMnJ5XIJUuDD4RBukSRAByIdie/3GwFvj7RKJeoIbrdbECOVy7aR2ic5YR0tFotYR6NR5KqmuqCigFg056YLQZgokl6vV2azWcxevtpsNjEvcxsMBqXT6dRq5rler+OSgMbjcex1RMxZ7nKWtUOqiv1+P1ogoj0gs2y1WkFK+Hg8RifqcoLbvLyYoUNA1AkgIqJ9DrhH4Kw1xYbDYbjebrf1KwhCYCBqSO0BkHPFuTUvKus5InuuY4YIWc12gRQB8rG32+1woRP5dEncZWjZXr0mpOYyksgBq3lyAexs3r7gOmduPNFyXopkPuYEIKSOTDTJEGTkc6sfNkJknkaqJQghF1prXkjzO25+gj/TVdAnn/SAowAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 1' title='' src='/static/7009ef4a51375d12242d8343c8488a8d/ca1dc/img_1.png' srcset='/static/7009ef4a51375d12242d8343c8488a8d/e7570/img_1.png 170w, +/static/7009ef4a51375d12242d8343c8488a8d/f46e7/img_1.png 340w, +/static/7009ef4a51375d12242d8343c8488a8d/ca1dc/img_1.png 680w, +/static/7009ef4a51375d12242d8343c8488a8d/2876f/img_1.png 968w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<blockquote> +<p>PCB는 해당 프로세스가 실행되면 생성되어 종료 시 제거가 되는데 이 과정에서 PCB의 삽입 및 삭제가 용이한 연결 리스트(Linked List) 방식으로 관리됩니다.</p> +</blockquote> +<h2 id="Process-Metadata" style="position:relative;"><a href="#Process-Metadata" aria-label="Process Metadata permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>Process Metadata</h2> +<p>그럼 PCB에는 어떤 정보가 담겨있을까요? +PCB에는 아래와 같은 프로세스의 메타데이터들이 담겨져 있습니다.</p> +<ul> +<li>프로세스 번호(PID, Process ID): 각 프로세스의 고유 식별 번호입니다.(PPID: 부모 프로세스 ID)</li> +<li>프로세스 상태(Process State): 프로세스가 현재 어떤 상태인지를 나타내는 정보(new, ready, running, waiting, end)입니다.</li> +<li>프로그램 카운터(PC, Program Counter): 이 프로세스에서 실행될 다음 명령어의 주소를 가리키는 포인터(주소)입니다.</li> +<li>레지스터 상태(Register State): 프로세스의 레지스터 값 세트로, 프로세스를 다시 실행할 때 현재 상태를 복원하는 데 사용됩니다.</li> +<li>스케줄링 정보(Scheduling Information): CPU 시간 스케줄링에 대한 정보입니다.</li> +<li>메모리 관리 정보 (Memory Management Information): 프로세스의 메모리 할당과 사용에 관한 정보입니다.</li> +<li>입출력 상태 (I/O Status): 프로세스가 입출력 작업을 수행 중인 경우, 해당 상태 정보 및 장치 정보입니다.</li> +</ul> +<h2 id="프로세스-상태" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%83%81%ED%83%9C" aria-label="프로세스 상태 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스 상태</h2> +<p>운영체제의 커널은 프로세스를 관리하기 위해 프로세스 정보를 알아야 해서 PCB를 생성하는 것을 알았습니다. +여기서 커널의 프로세스 관리는 프로세스 상태를 관리하는 것이기도 합니다.</p> +<p>프로세스 상태는 위에서 언급한대로 프로세스가 현재 어떤 상태인지를 나타내는 정보로, +프로세스의 상태에 따라 CPU를 할당하거나 대기 상태로 전환하는 등의 작업이 이루어집니다. +프로세스 상태는 일반적으로 다음과 같은 상태로 구분됩니다.</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 664px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/da90d58f0e47b1811f665ea0ad22cadc/5bd9c/img_2.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 48.8235294117647%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABY0lEQVR42nWS6a6CUAyEef8H4iGUP+5xxX1FUHEXHPM1qfH+uE2aAz3tdDo9QRzHGo1G2u/32u12ul6vwm63myaTiabTqXmapiqKQu/32+6fz6c2m43G47GGw6HdUx9Q1Gq1VJalFouFTqeTDoeDJQNEMkXn81mr1cpAsX6/r0ajYbFer2eN8jxXAAAOOl6v1xWGoV3ClkbOithsNrNG2+3WpiBGfZIk1jTQjz0eDw0GA3W7XXU6HWO6XC51v9/tPssyrddrYwdrQBkV86YBH/7zer00n89tFABdV+JYs9lUu902ME7GhRXGJAbo7BwURhQAxGiMjW7H41EsEAD+Yfdb5xa4BpfLxfQACFCMQt8kpy8E7YhxIgMb/wIyIkKjDUk8oVqtZkl0Z/O8AsaFJUYueYyM5hBxtn+W4kZnGOE05OkwPkBRFJm2/9l3Ke4uLtrBHK9UKqpWq/YNuD+l34U64AcjuPeyZLidcAAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 2' title='' src='/static/da90d58f0e47b1811f665ea0ad22cadc/5bd9c/img_2.png' srcset='/static/da90d58f0e47b1811f665ea0ad22cadc/e7570/img_2.png 170w, +/static/da90d58f0e47b1811f665ea0ad22cadc/f46e7/img_2.png 340w, +/static/da90d58f0e47b1811f665ea0ad22cadc/5bd9c/img_2.png 664w' sizes='(max-width: 664px) 100vw, 664px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<ul> +<li>New(생성) : 프로세스는 저장장치에서 메모리로 로드되어 생성됩니다. 이후 커널은 메모리를 할당하고 PCB를 생성하고 프로세스 테이블에 등록합니다. 실행 준비를 마치면 ready 상태로 전이됩니다.</li> +<li>Ready(준비) : 프로세스가 CPU를 사용하고 있지는 않지만 언제든지 사용할 수 있는 상태로, 해당 상태의 프로세스들은 커널에 있는 준비 큐(<a href="https://ko.wikipedia.org/wiki/%EB%B9%84%EC%9C%A8_%EB%8B%A8%EC%A1%B0_%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81">우선순위 큐</a>)에 들어갑니다. 스케줄러가 컨텍스트 스위칭을 수행할 때, 준비 큐에서 우선순위가 높은 프로세스가 CPU 스케줄링에 따라 리소스를 할당받아 running 상태로 전이(디스패치)됩니다.</li> +<li>Running(실행) : 프로세스가 CPU를 차지하여 명령어들이 실행되고 있는 상태입니다. 할당된 시간을 모두 사용(타임아웃)했다면 타이머 인터럽트가 발생되어 준비 상태로 전이되고, 입출력 요청이나 자원 요청 등으로 인해 대기 상태로 전이될 수도 있습니다.</li> +<li>Waiting(대기) : 프로세스 실행 도중 입출력 완료(주된 원인)와 같은 수신 등을 대기하는 상태를 말합니다.</li> +<li>End(=terminated, 종료) : 프로세스의 실행이 종료된 상태입니다. 이떄, PCB와 프로세스의 메모리를 해제 또는 정리합니다.</li> +</ul> +<h2 id="프로세스-계층-구조" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EA%B3%84%EC%B8%B5-%EA%B5%AC%EC%A1%B0" aria-label="프로세스 계층 구조 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스 계층 구조</h2> +<p>프로세스는 실행 도중 시스템 콜을 통해 다른 프로세스를 생성할 수 있습니다. +이때 시스템 콜을 호출한 프로세스를 부모 프로세스, 생성된 프로세스를 자식 프로세스라 합니다.</p> +<blockquote> +<p>서로 다른 프로세스라 서로 다른 PID를 가집니다. +일부 운영체제에서는 자식 프로세스의 PCB에 부모 프로세스의 PID (PPID)가 기록되기도 합니다.</p> +</blockquote> +<p>프로세스 생성 기법은 복제와 교체 과정을 통한 방식을 사용합니다.</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 664px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/e8cab7c1ce395505ef306dd012d77bab/5bd9c/img_3.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 72.94117647058825%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAACH0lEQVR42oVTa4/SQBTl//8NTYwuq5jwwbAohCw0WWSXCGRpFnm0SymFlkeh5X2cc3VMFVZvMnSYx3nceyeFC3E8HnE6nf67vlgsEAQBttstNpsN9vs9Un9f4uJqtUK9XodhGKhWqzIqlQrG4zHCMMRkMoHv+zBNU0byXuqSCrKR2fM8OI4jQJyv12tRs9vtEMexAFMlSRjcT+GFICMPUOlwOBSSpN3D4SBk0+kU8/lciAj8IiCV8lC32xV7BEgCcl4ul5HP58XBaDQS4DNAWhgMBsJOS4woiuQS17ivo1AoIJPJwLIsSQn3zgBnsxlqtZoMMmq1nU5H1Ni2/ftss9lEsVgUQBZEikLp2govatDlcvnT2vHAHzlDxcwth24hfvXg/z8UEqTRaKDdbiNU82W4Qj86ohsBj98HMCplZWspKWCVdS6TkWIF+/2+qNK50m0QRjGuKi28KT+iM1QtMguw/1UcVl0DamcCyKalFYIwT6zoaOSqCzHi3R5vi/d49eVeAaqkz2ewn5+lAK7rSvF6vZ7kkF0ggGTSDFTXarXkIC17fgDDWuDWDvHQ7uDJbAu57j3eY5NrMAFM5oHq0uk0SqWSvJTewMJ7ZfnG9HBze4frq3eSHhLrDjjLYXKRVrLZLHK5HByVW2c8wevPX/HJ9FG4q+Pjh2t8U0Wjyn8C6qB9HmYDx3GkXsoOT5YD2w/hL0K46jVQOduGVi/FD2N1dOWzKvI/AAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 3' title='' src='/static/e8cab7c1ce395505ef306dd012d77bab/5bd9c/img_3.png' srcset='/static/e8cab7c1ce395505ef306dd012d77bab/e7570/img_3.png 170w, +/static/e8cab7c1ce395505ef306dd012d77bab/f46e7/img_3.png 340w, +/static/e8cab7c1ce395505ef306dd012d77bab/5bd9c/img_3.png 664w' sizes='(max-width: 664px) 100vw, 664px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<p>흐름의 시작인 부모 프로세스는 fork(복제) 시스템 콜을 통해 자신의 복사본을 자식 프로세스로 생성합니다. +자식 프로세스는 exec(교체) 시스템 콜을 통해 자신의 메모리 공간을 다른 프로그램으로 교체합니다. +이때, 자식 프로세스의 메모리 공간을 새로운 프로그램으로 덮어쓰게 합니다.(코드/데이터는 내용만 바꾸고, 나머지는 초기화) +자식 프로세스가 exec 시스템 콜을 호출하지 않을 경우, 부모 프로세스와 자식 프로세스는 같은 코드를 병행하여 실행하는 프로세스가 됩니다. +이러한 과정을 통해 프로세스는 계층 구조를 이루어 관리할 수 있습니다.</p> +<p>많은 운영체제에서는 이처럼 프로세스를 낳는 계층적인 구조로써 프로세스들을 관리합니다. +컴퓨터가 부팅될 때 실행되는 최초의 프로세스가 자식 프로세스들을 생성하고, +생성된 자식 프로세스들이 새로운 프로세스들을 낳는 형식으로 여러 프로세스가 동시에 실행되는 것입니다.</p> +<h2 id="프로세스-간-통신" style="position:relative;"><a href="#%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EA%B0%84-%ED%86%B5%EC%8B%A0" aria-label="프로세스 간 통신 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>프로세스 간 통신</h2> +<p>앞서 언급했던 것처럼 프로세스는 서로 독립된 메모리 공간을 가지므로, 프로세스끼리는 서로의 영역에 접근 또는 간섭할 수 없습니다. +이러한 이유로 통신이 필요할 경우, <a href="https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4_%EA%B0%84_%ED%86%B5%EC%8B%A0#:~:text=%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%20%EA%B0%84%20%ED%86%B5%EC%8B%A0(Inter%2DProcess%20Communication%2C%20IPC)%EC%9D%B4%EB%9E%80%20%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%93%A4%20%EC%82%AC%EC%9D%B4%EC%97%90%20%EC%84%9C%EB%A1%9C%20%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC%20%EC%A3%BC%EA%B3%A0%EB%B0%9B%EB%8A%94%20%ED%96%89%EC%9C%84%20%EB%98%90%EB%8A%94%20%EA%B7%B8%EC%97%90%20%EB%8C%80%ED%95%9C%20%EB%B0%A9%EB%B2%95%EC%9D%B4%EB%82%98%20%EA%B2%BD%EB%A1%9C%EB%A5%BC%20%EB%9C%BB%ED%95%9C%EB%8B%A4.">IPC</a>를 통해 프로세스 간에 통신을 할 수 있습니다. +IPC에는 공유 메모리를 이용한 통신과 파일을 통한 프로세스 간 통신 이렇게 두 가지 방법이 있습니다.</p> +<blockquote> +<p>IPC 통신 시, 프로세스 간 데이터를 동기화하고 보호하기 위해 <a href="https://ko.wikipedia.org/wiki/%EC%84%B8%EB%A7%88%ED%8F%AC%EC%96%B4">세마포어</a>와 <a href="https://ko.wikipedia.org/wiki/%EC%83%81%ED%98%B8_%EB%B0%B0%EC%A0%9C">뮤텍스</a>를 사용합니다.</p> +</blockquote><![CDATA[인터럽트와 DMA를 통한 효율적 입출력 처리]]>https://catch-npe.netlify.app/jc5/https://catch-npe.netlify.app/jc5/Mon, 08 Sep 2025 00:00:00 GMT<h2 id="인터럽트-기반-입출력" style="position:relative;"><a href="#%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8-%EA%B8%B0%EB%B0%98-%EC%9E%85%EC%B6%9C%EB%A0%A5" aria-label="인터럽트 기반 입출력 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>인터럽트 기반 입출력</h2> <hr> <p>인터럽트는 컴퓨터 시스템에서 현재 실행 중인 프로세스를 중단 하고, 인터럽트를 발생시킨 작업을 처리하기 위한 방법 혹은 과정 이다. 인터럽트는 CPU의 실행 흐름을 중단시키고 인터럽트가 끝난 후 원래의 흐름으로 돌아가는 방식을 가진다.</p> @@ -601,28 +2595,59 @@ DMA 방식을 순서로 설명하자면 <li>DMA 컨트롤러가 메모리와 입출력 장치 간의 데이터 전송을 직접 수행합니다.</li> <li>데이터 전송이 완료되면 DMA 컨트롤러가 인터럽트를 발생 시켜 CPU에게 완료를 알립니다.</li> <li>CPU는 인터럽트를 받아서 필요한 후처리 수행합니다.</li> -</ol><![CDATA[4. 멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념]]>https://catch-npe.netlify.app/4/https://catch-npe.netlify.app/4/Sun, 07 Sep 2025 00:00:00 GMT<h2 id="단일-프로세스" style="position:relative;"><a href="#%EB%8B%A8%EC%9D%BC-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4" aria-label="단일 프로세스 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>단일 프로세스</h2> +</ol><![CDATA[멀티프로그래밍, 시분할 시스템, 멀티프로세싱 개념]]>https://catch-npe.netlify.app/jc4/https://catch-npe.netlify.app/jc4/Sun, 07 Sep 2025 00:00:00 GMT<h2 id="단일-프로세스" style="position:relative;"><a href="#%EB%8B%A8%EC%9D%BC-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4" aria-label="단일 프로세스 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>단일 프로세스</h2> <hr> <p>초창기 컴퓨터를 상상하면 지금처럼 복잡한 방법이 아닌, 한번에 하나의 프로그램만 실행 할 수 있었을것이다. 이 말은 다른 프로그램을 사용 해야 하는 순간 기존 프로그램이 종료 되거나, 끝날때 까지 기다려야 합니다.</p> <br> -<p><img src="%EB%8B%A8%EC%9D%BC%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/f77a454f2f7ab46efc3084588bd02511/911ab/single_process.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 32.94117647058823%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAAA7UlEQVR42q2PvUrDUBhA81o+hIOToLOLk4ODuPoiLr5GVEqR1KYmgtFAEmPalGj6k/Teiu295njJVBy1H99ZzgcHPkvP71DrFVJKlFL8d6xPe4eP95xOp8ukLFvZNM3fg2KasRCC0TBDiLlR32bXJqrb8CY0quW338RaabY6ljecIaovdHKFcvZZOkfo3gHSu2CcZoziiDxJGL8mLHqn1PfnxucUaUIexy3FW0oeRcjJBMtJSmRtguEl6noXaR+ib/eoumc8e488uX2CwYAX74Gpfczs5oTADwg9z9zcltD3CfouVVFg1WK51Zd/ADgIFD1F+zxSAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/f77a454f2f7ab46efc3084588bd02511/ca1dc/single_process.png' srcset='/static/f77a454f2f7ab46efc3084588bd02511/e7570/single_process.png 170w, +/static/f77a454f2f7ab46efc3084588bd02511/f46e7/single_process.png 340w, +/static/f77a454f2f7ab46efc3084588bd02511/ca1dc/single_process.png 680w, +/static/f77a454f2f7ab46efc3084588bd02511/911ab/single_process.png 710w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <br> CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 IO작업동안 CPU는 멈추게 될것이고 그 상황에서 CPU가 놀고 있게 되는 시간이 늘어나는 것입니다. <br> <h2 id="멀티-프로그래밍" style="position:relative;"><a href="#%EB%A9%80%ED%8B%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D" aria-label="멀티 프로그래밍 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>멀티 프로그래밍</h2> -<p><img src="%EB%A9%80%ED%8B%B0%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/fa76ff72490a689b429d754852e6bb6e/f8d10/multiprograming.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 31.176470588235293%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsTAAALEwEAmpwYAAABJ0lEQVR42p2QP0vDUBRHC34HF8FBN3URpXVxF3QzgkURdNXd0UEnP0PBLyDubuKkCA6itUnzr2Jt81KImLamfS89JlGq4NYLh/veu5fDj5dr314Rnp1iGi77hyUen2ukFccDRqmcuLygfnzAw32ZteIJN3flb6GSmTQTD+J/DOJ4OB/upcK+UvTTYdJVrBgt15+E3Z7iNegSy0TYEkRWhcjW6Tk6bvINdcNBJufIMfi0jaxLV0dULSplB0uvUa24CQ69Tpec6be5Nn1aHUl4XsJencXaKPCi5cnP71AsaHxsLuBqS5jreWytQFhc5Gh5hbGJLabm9hif3mZyZpfqk5kmlNhekCSUyPcA6TWQopnh1wVBw0OJ9O2X9B42m3hvAvGDnyCjiC9uAK1Dx6Z8BgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/fa76ff72490a689b429d754852e6bb6e/ca1dc/multiprograming.png' srcset='/static/fa76ff72490a689b429d754852e6bb6e/e7570/multiprograming.png 170w, +/static/fa76ff72490a689b429d754852e6bb6e/f46e7/multiprograming.png 340w, +/static/fa76ff72490a689b429d754852e6bb6e/ca1dc/multiprograming.png 680w, +/static/fa76ff72490a689b429d754852e6bb6e/f8d10/multiprograming.png 705w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <p>이러한 문제를 해결하기 위해 어쩔 수 없이 작업이 멈추는 구간에 다른 작업을 진행하는 방법을 사용하게 된다. 이를 멀티 프로그래밍이라고 부르며 그림처럼 CPU 사용률을 높이기 위한 목적이었습니다.</p> <p>하지만 이러한 방식의 문제는 앞선 프로세스가 길어질 수록 즉 IO사용처럼 비는 시간없이 순수하게 많은 시간을 쓰게 된다면 이후 프로세스가 계속 기다려야 하는 문제가 있었습니다.</p> <br> <h2 id="멀티-태스킹" style="position:relative;"><a href="#%EB%A9%80%ED%8B%B0-%ED%83%9C%EC%8A%A4%ED%82%B9" aria-label="멀티 태스킹 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>멀티 태스킹</h2> -<p><img src="%EB%A9%80%ED%8B%B0%ED%83%9C%EC%8A%A4%ED%82%B9.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/cfa08a42d069dd94964b0c24f10b328d/190d7/multitasking.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 34.11764705882353%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsTAAALEwEAmpwYAAABOklEQVR42p2QzUsCARDF97+ra2goSfYJBSLRyYPQrVsSWEGnpMA0XctSCCPoYKZgWCChCCpBQQklqemu7u6v1e2SnmyY4Q2P4c28Ed53NpCLD+wdXrO5HYWPEkrCjVorogGapjJOCMWlSRqpKxxuH+ZFD73nDM39CeRKajCgqUpfVU9tBIe5gWCzIyF3e8iyhCR1kPS+3jTwPyE0Oj26imHL2KQaW1V1pBjCP71iOBHuyjUqn20evR52Z03EVq1E1mcIL1u4WLPqnJ2sawrv/Bw3ThM+h53LFRNhpw3fgo2ky4zXMk1B3AJdVLiv1nj9avOWuSUTCVA4PyF75id5dED+IkBGFHlJ+ElHRMqxY3JxkVLUTz4eIncaopoIkA4GqT2lBtcKzVZLF1Z+LRt/aHUV6t8yfVYb84c/6z3373C9i5gAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/cfa08a42d069dd94964b0c24f10b328d/ca1dc/multitasking.png' srcset='/static/cfa08a42d069dd94964b0c24f10b328d/e7570/multitasking.png 170w, +/static/cfa08a42d069dd94964b0c24f10b328d/f46e7/multitasking.png 340w, +/static/cfa08a42d069dd94964b0c24f10b328d/ca1dc/multitasking.png 680w, +/static/cfa08a42d069dd94964b0c24f10b328d/190d7/multitasking.png 706w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <p>멀티 프로그래밍 방식에서 더 나아가 모든 프로세스가 공정하게 특정 짧은 시간만 실행되게 반복한다면 길게 시행되는 프로세스 뒤에 오는 프로세스가 기다리는 문제가 없을 것이다. 이것이 멀티태스킹을 사용하는 이유입니다.</p> <p><strong>프로세스1</strong>에서 <strong>프로세스2</strong>로 작업을 스위칭 하는것을 문맥 교환(Context Switching)이라고 @@ -633,11 +2658,22 @@ CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 <p>멀티 프로세싱이란 이전 멀티 태스킹과 이름은 비슷 하지만 완전히 다른 방식입니다.</p> <p>이전 방식은 하나의 <strong>CPU</strong>를 어떻게 쪼개서 사용할까라는 목적이였다면, <strong>멀티 프로세싱</strong>은 <strong>CPU</strong> 작업단위인 코어 자체를 늘려서 여러 CPU코어가 동시에 작업하는것을 멀티 프로세싱이라고 부르게 됩니다.</p> -<p><img src="%EB%A9%80%ED%8B%B0%ED%94%84%EB%A1%9C%EC%84%B8%EC%8B%B1.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/951ebab0085a17766b360229f7e8e1d4/0d97d/multiprocessing.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 43.529411764705884%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB/klEQVR42lWSzWsTQRiH82+IB4k9iUcP4kEQ/4YexKsg6sWDGFTag0IF8aAn8VKpBPRQD1Y89KCtNiVoSmmhhqZp2jQ2ycYk+5HddTPZj3mc3dXUvofhNzPv+8z7MZlCoUAYhrC5AX2TMGgR/q6RmkzWTqeDEIKx2TbSHoy3MvKQgZXozKlslt7hIVyZJHr/kaH5Cq82/RcFhmEwMTHBu/n5ZK+eJpp+QHQ/NwYK7TVu9XYKLJVKSbCsbIPlEAUakWiNnaMoIp/PE/vpCj4aDpHLS7BaQI4EUvoE1iq+uZICPc9D+D4oR/xRkv7/JqVEqDvLsjBaLX7t7+EYPYStIy1VmdsmCh0VJ5IWZYIgwByofjjqUKjeSHEM6Ac+tuMi9D7eQGfkmOhaHbfXwBkYDHVNxams5TB+nUwc5KmGB66rot3xIOLMYhvYDt2tdVVBh1a7yXC/TDDqoTV+Iuo/cLw+2s4uQWdHeQcpcGu7ytLULeitpDgZpZNXtrCwyJuLJ5Uq8uLZHJ8nTyt9wJPcDGvXzipt8uj6Haq5C0q3U+CnL0Vmz5+AxixRMonwCPhhkbeXswnw5fM5lq+eSYBP7z1m/ea5+B8wc+Muu1OXjoDlSo2vD9XY9eI4w38lG4ZFd/NbXDyddhez/F3pEa2DJnZlLflIzVodb28j7jh/AE8Djj1JTPX8AAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/951ebab0085a17766b360229f7e8e1d4/ca1dc/multiprocessing.png' srcset='/static/951ebab0085a17766b360229f7e8e1d4/e7570/multiprocessing.png 170w, +/static/951ebab0085a17766b360229f7e8e1d4/f46e7/multiprocessing.png 340w, +/static/951ebab0085a17766b360229f7e8e1d4/ca1dc/multiprocessing.png 680w, +/static/951ebab0085a17766b360229f7e8e1d4/0d97d/multiprocessing.png 1011w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <p>멀티 프로세싱은 CPU코어 수를 늘리는 방법이기 때문에, 이를 어떻게 처리할까에 대한 내용은 멀티 프로세싱 자체의 내용이 아니고 앞서 나왔던 방법론을 도입할 수 있습니다. 그림처럼 하나의 프로세스를 여러 코어가 담당하는 방법이나, 여러 프로세스를 여러 코어가 담당 할 수 도 있습니다.</p> <h3 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h3> -<p><a href="https://medium.com/@ashappyasiknow/single-process-system-multi-programming-multitasking-%EC%9D%B4%EB%9E%80-9f9b65ec0311">사진출처</a></p><![CDATA[3. 유저모드와 커널모드 전환, 시스템 콜의 동작 원리]]>https://catch-npe.netlify.app/3/https://catch-npe.netlify.app/3/Sat, 06 Sep 2025 00:00:00 GMT<h2 id="이중모드" style="position:relative;"><a href="#%EC%9D%B4%EC%A4%91%EB%AA%A8%EB%93%9C" aria-label="이중모드 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>이중모드</h2> +<p><a href="https://medium.com/@ashappyasiknow/single-process-system-multi-programming-multitasking-%EC%9D%B4%EB%9E%80-9f9b65ec0311">사진출처</a></p><![CDATA[유저모드와 커널모드 전환, 시스템 콜의 동작 원리]]>https://catch-npe.netlify.app/jc3/https://catch-npe.netlify.app/jc3/Sat, 06 Sep 2025 00:00:00 GMT<h2 id="이중모드" style="position:relative;"><a href="#%EC%9D%B4%EC%A4%91%EB%AA%A8%EB%93%9C" aria-label="이중모드 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>이중모드</h2> <hr> <p>운영체제는 자원을 충돌 없이 효율적으로 사용하기 위해 자원 관리의 진입점이 된다고 말했습니다.</p> <blockquote> @@ -645,7 +2681,18 @@ CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 </blockquote> <p>이에 대한 답은 <strong>이중 모드</strong> 입니다.</p> <br> -<p><img src="%EC%9D%B4%EC%A4%91%EB%AA%A8%EB%93%9C.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/75e8bf8682ccd19adcacc9a00410c63f/4bd0f/dual_mode.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 72.35294117647058%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB9ElEQVR42o1U204bQQzN/7+jviEhoIBAqtSnSiBVFf2GvABJoVGyyc5esveZvZz6mJ2UhFZiJctjxz4+Y3sywfg55xDHMfIsR5IkSNMUkTFIxGdCg7Zt8ZFv4g9MiOMIWwGiNmGIUIRFqLuue5M2/B9wGAYMQy8C9H2vAEVRqLbWYrvdoixLpKKrulLmWZappv+Q+YTJQRDAmAjL5RLBOkAmyU+PT5pEQLZgPpvpWW0p9jyfI5HfCcjCJLN3ZX50MlkZRJEm53muNs/pgc3YdwwPe8AAx6pSvZYr1VWFpq5VbNPACRvGaJwMshGfHX1s3w6Qhg5GmCmgANl+gOMGjEIuTuIIRLHW7cCaxurgFLCW6sEqEFlhI72swzXi61Msrs+wuDnD+suFyCXWN+cof9yiG/5OeRjPBHeufQX0zk4qBZsNoudfWF0cY3F5gt+UqxO8iCw+H8N8+4qC7IVZUzdKhmw5XOq9K1MI2spw2qpELzZn14+bR92OreH1fC95puz10INWY/Uy3KDIZAeLHKVMthQGHJIdh6AM5eyHQnY7QBp+HbgK0+kU32/vdEDaCqnOlfqXeGZ+OArYCuDrXqUKeH//E0dHn/Dw8LgD9C05FL/QZLrXw7eLbeRPYSYvgy+FgWwDm8+nxuZT06af4mO4Nn8AQpc4EKWiZ3gAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/75e8bf8682ccd19adcacc9a00410c63f/ca1dc/dual_mode.png' srcset='/static/75e8bf8682ccd19adcacc9a00410c63f/e7570/dual_mode.png 170w, +/static/75e8bf8682ccd19adcacc9a00410c63f/f46e7/dual_mode.png 340w, +/static/75e8bf8682ccd19adcacc9a00410c63f/ca1dc/dual_mode.png 680w, +/static/75e8bf8682ccd19adcacc9a00410c63f/4bd0f/dual_mode.png 731w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <br> <p>위 사진 처럼 <strong>CPU</strong>가 명령을 실행하는 방식을 <strong>사용자 모드</strong> 와 <strong>커널 모드</strong>로 나누어 사용하게 됩니다.</p> <br> @@ -666,13 +2713,34 @@ CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 </blockquote> <p>사용자 모드에서 커널모드로 전환하는 방식은 <strong>시스템 콜</strong>에 의해서 발생합니다.</p> <br> -<p><img src="%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%BD%9C.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 621px; '> + <a class='gatsby-resp-image-link' href='/static/01cdb134d9eb0075b2f48beaac0b5e34/41b39/system_call.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 58.82352941176471%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABkklEQVR42o2TiW6CQBCGef+3atMzNRbtYRXwqHIa5VwUZPk7s0pjsSmdZIFdmG/+OdDQsrqucTgcUFUVkjiB4zgoikKdSSnRZRpf2CGJYyRJgu02hGlNMZ6Y0AdDPPX6eB9NMPoYw7Ht76CNcRAO3pwp4H6/RxSGiAnq+wEMw8LEmELXh+gR8PVtRHsLtmWhyoVSeyhLBUuSGK7rKF9JUK0tOYoirNdr9UGWZUo1n/E+oPNss4EgiNjtkNPikiwXS6yWK5QURGtSaFZMzqz4t9qKPOcH1EKA8gTJhCyp3qS0qe+lQkp9R5GPkOOHUtbkL5GmqQLKKFSrCreQIvvZFI6cZSkEReUUQwKy9LYxOKb0WZmkOp50X3aZgQyJohgbqk9IXbZtB7PZHKZpYTZfqOf54hO+5wEEq6kpf47NuTHQMKfoPw9wdX2D+/tH3N49oK+/wCYoK6y75vC8KdxR1/XU8nwfnufDDwK15+6357BTIQPLslDDqubt9NfwXbQa8C9g48yjw93OaVT4znt+1wX8AkhEov/HiEHjAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/01cdb134d9eb0075b2f48beaac0b5e34/41b39/system_call.png' srcset='/static/01cdb134d9eb0075b2f48beaac0b5e34/e7570/system_call.png 170w, +/static/01cdb134d9eb0075b2f48beaac0b5e34/f46e7/system_call.png 340w, +/static/01cdb134d9eb0075b2f48beaac0b5e34/41b39/system_call.png 621w' sizes='(max-width: 621px) 100vw, 621px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <br> <p>그림처럼 사용자 모드로 실행되는 프로그램이 자원에 접근해야 할때 운영체제에 커널 모드로 요청을 보내게 되고 이것을 <strong>시스템 콜</strong>이라고 부르게 됩니다.</p> <p><strong>시스템 호출</strong>은 <strong>소프트 웨어 인터럽트</strong>에 속합니다. 이러한 특징 때문에 <strong>CPU</strong>가 <strong>시스템 호출</strong>을 처리하는 순서가 <strong>인터럽트 처리 순서</strong>와 비슷합니다.</p> <p><strong>시스템 호출</strong>이 발생하면 <strong>지금까지의 작업을 백업</strong> 하고, 커널 영역 내의 호출 하여야 하는 코드를 실행 한 뒤 다시 돌아와 기존 프로그램을 계속 실행합니다.</p> <br> -<p><img src="%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%BD%9C%EC%9E%91%EB%8F%99%EB%B0%A9%EC%8B%9D.png" alt="img.png"></p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; '> + <a class='gatsby-resp-image-link' href='/static/25692a5972d7f1beeeccb49b63da27fa/88e66/system_call_method.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 51.764705882352935%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABk0lEQVR42o1SAW7aQBDk/99qSkPVBqUKdpFKMBhDTMD22b6zwXc3nb0SJTRtVUujXezd2ZldRnjznE4nNG0L03XYZltkhDEdGq1xPp/xP8/IWou+76HZtNs9YTaLMX+I8Pl2gsmnCeLoO6L7bzhsUoC1zmhYVcFxuOs7eO8DkcevOBqGAapSKIsC+fMBj7MIyfgjFg8z5jEeoxg/7u6gDofQYJ/3GJYLeIpwtYJ3Dv2pD+4C4YtUUSoKl8kK63WKNN1guVoHJMsEeZZBc6jWBrqu0dKRNgZN02CVJNiwXpxeESqlXi0wuuEM3xlY7q8liWsbWDZZEjk6c6wRh7WqA7HkwfLABsOimk0XthBcU8Nu1nC6heIOPS06HkzgKUCGvgjAJR8Jc83C4/GIgpbKsmJehLwoS5RVFaJihKgiueNwf3HxO64s53mOKJ5jOr3HmBf+cDPGl6/T8G6f8sqmheUK5BB/IrsiFOsllTzle2y3O2SERDmUoOK3sIa/EL0jlB+i0nG6kMsfOez3AvcPVW8JfwIkYALkgHAxawAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img.png' title='' src='/static/25692a5972d7f1beeeccb49b63da27fa/ca1dc/system_call_method.png' srcset='/static/25692a5972d7f1beeeccb49b63da27fa/e7570/system_call_method.png 170w, +/static/25692a5972d7f1beeeccb49b63da27fa/f46e7/system_call_method.png 340w, +/static/25692a5972d7f1beeeccb49b63da27fa/ca1dc/system_call_method.png 680w, +/static/25692a5972d7f1beeeccb49b63da27fa/88e66/system_call_method.png 790w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img.png</figcaption> + </figure></p> <br> <p>그림을 통해서 이해를 하게 되면,</p> <ol> @@ -684,8 +2752,8 @@ CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 </ol> <p>이런 세부적인 순서를 진행하게 됩니다.</p> <h3 id="출처" style="position:relative;"><a href="#%EC%B6%9C%EC%B2%98" aria-label="출처 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>출처</h3> -<p><a href="https://hongong.hanbit.co.kr/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EB%9E%80-%EC%BB%A4%EB%84%90%EC%9D%98-%EA%B0%9C%EB%85%90-%EC%9D%91%EC%9A%A9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%8B%A4%ED%96%89%EC%9D%84-%EC%9C%84%ED%95%9C/">사진출처</a></p><![CDATA[2. CPU 스케줄링, 시스템 자원 관리]]>https://catch-npe.netlify.app/2/https://catch-npe.netlify.app/2/Fri, 05 Sep 2025 00:00:00 GMT<h2 id="CPU-스케줄링" style="position:relative;"><a href="#CPU-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="CPU 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>CPU 스케줄링</h2> +<p><a href="https://hongong.hanbit.co.kr/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EB%9E%80-%EC%BB%A4%EB%84%90%EC%9D%98-%EA%B0%9C%EB%85%90-%EC%9D%91%EC%9A%A9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%8B%A4%ED%96%89%EC%9D%84-%EC%9C%84%ED%95%9C/">사진출처</a></p><![CDATA[CPU 스케줄링, 시스템 자원 관리]]>https://catch-npe.netlify.app/jc2/https://catch-npe.netlify.app/jc2/Fri, 05 Sep 2025 00:00:00 GMT<h2 id="CPU-스케줄링" style="position:relative;"><a href="#CPU-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81" aria-label="CPU 스케줄링 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>CPU 스케줄링</h2> <hr> <p><strong>CPU 스케줄링</strong>은 CPU를 항상 바쁘게 동작시켜 자원을 낭비하지 않고 최적으로 활용할 수 있게 돕기도 하며, <br>모든 프로세스로 하여금 CPU를 공정하게 할당할 수 있게 합니다.</p> @@ -710,7 +2778,96 @@ CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 <li>응답 시간 - 시스템이 사용자의 요청에 반응하여 첫 번째 응답을 생성하기 시작하는데 걸리는 시간</li> <li>대기 시간 - 프로세스가 실행되기 위해 CPU를 할당받아 준비 상태에서 대기하는 시간의 총합</li> <li>처리 시간 - 특정 작업이 시작되었을 때부터 그 작업이 완전히 끝나는데 걸리는 시간의 총합</li> -</ol><![CDATA[1. 운영체제의 역할과 커널의 기능]]>https://catch-npe.netlify.app/1/https://catch-npe.netlify.app/1/Thu, 04 Sep 2025 00:00:00 GMT<h2 id="운영체제란-무엇일까" style="position:relative;"><a href="#%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C" aria-label="운영체제란 무엇일까 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>운영체제란 무엇일까?</h2> +</ol><![CDATA[2. 커널의 작동 방식]]>https://catch-npe.netlify.app/hs2/https://catch-npe.netlify.app/hs2/Thu, 04 Sep 2025 00:00:00 GMT<p>앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다. +이제 커널이 어떻게 작동하는지 제대로 알아보자.</p> +<p>먼저 인터럽트(Interrupt)에 대해 알아야 한다.</p> +<p><figure class='gatsby-resp-image-figure' style='margin-bottom: 16px;'> + <span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 431px; '> + <a class='gatsby-resp-image-link' href='/static/f95d40cd5c4355157dc98470083e6eac/7921f/img_3.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 76.47058823529412%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAACjklEQVR42m1TaXPaQAz1//8tnXbamdIPTZsecQjhCOYwNsaAbcxlk4A5kwCvesrAJG01I1hrd6Wn97QGxHzfx2QyQRAEiKLo7P1+H9PpFKPRSNeDwUB9OByi1WrpHdrxeMTJDH7EcYz7+3u9NJvNkCSJftM3mw3CMMR8Psd4PNa91WqlMX7T9vs9DoeDusEAExJFp+Prmk4URPn4+KgdcN3tdrVoGIQaS9MUz8/Pep4FHh4eXhDy8Hq9kaRDNBp38h3AvP6B5XKlCMIwwE3hF9IkhWWVhYaJdvLflvnDhC+Q94LC1vYm05HGPa+DJE0wTcZYZkt0ew6OOGCxWPyTkP8GYVcqFZRKJfEicl/ewzRNFAoFXP74jo+f3iGfz6ub5jU+5z6gVC7qfrvdxm63w2szqBY5CIQX8lC1iqJkjF6vh1rNQv7mCrbd0j363V1JleZ58u773bcJeWi73SKM+gjCnqx3yLJMCfY6HqrVsqq5XC7Vt5st/K4rosUv9+Q+Wz25Ydu28JGJwg7cdlNGYq3qkaMkmYgIJUk4UT4Zz4RHnptOx8p1R4q+5tFoNBrKAytFYYRypaAq0p6ennTmSEmazmC3auj1fU2aiOIcesuydDa5ZidGvV7Xy0HQl2odaccTjiLU643zC/I8Tzn1fU+LZdIRO+DoEBCLkia64bouFvOFkP9TSV6v11qRg316dre3tygWixIb6ctpt1uKlkhZ9I0oPMjpbzTrZ0Qkn8ZXwnaJgoVJC/cd14HjtLQjx3HOHKoo5XJZgxffcqJoFc2mLeNS0ySVSglfL3K6JlccI45QPm/i99Wl3HPPCM+i8IWwvdEoVk5eO2e0VrcwiAY6Rqd4Ki8njiNV+W/7Azk3VL/ZkAN8AAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img_3.png' title='' src='/static/f95d40cd5c4355157dc98470083e6eac/7921f/img_3.png' srcset='/static/f95d40cd5c4355157dc98470083e6eac/e7570/img_3.png 170w, +/static/f95d40cd5c4355157dc98470083e6eac/f46e7/img_3.png 340w, +/static/f95d40cd5c4355157dc98470083e6eac/7921f/img_3.png 431w' sizes='(max-width: 431px) 100vw, 431px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> + <figcaption class='gatsby-resp-image-figcaption'>img_3.png</figcaption> + </figure></p> +<p>컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데 +이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다. +이중 하나가 인터럽트이다.</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 657px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/61f625e446355f48a42a5d423fc97597/1475c/img.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 11.176470588235293%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAATklEQVR42mNwc/f8n5df8N8/IOh/YmLy/6jo2P+SUjL/ZeUUwFhOXpEkzKChqf3f2cXtv4mp+X87O4f/1jZ2/3X1DP4bm5j919c3JNlQAJn9PAdfS1P/AAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img' title='' src='/static/61f625e446355f48a42a5d423fc97597/1475c/img.png' srcset='/static/61f625e446355f48a42a5d423fc97597/e7570/img.png 170w, +/static/61f625e446355f48a42a5d423fc97597/f46e7/img.png 340w, +/static/61f625e446355f48a42a5d423fc97597/1475c/img.png 657w' sizes='(max-width: 657px) 100vw, 657px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> +인터럽트는 중단시키다라는 의미로 초인종과 같다고 할 수 있다. +즉, 인터럽트가 발생하면 잠깐 멈추고 다시 실행된다.</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 372px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/1a630d318cb1fe19075afd79242ae35b/448ef/img_1.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 52.94117647058824%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB3UlEQVR42nVTXXOjMAzM//9pN5M8NPdw+WhIAySBQgFjAwab7cqkbW5uTjMaI8laa9dmVRQFvPdQSmGeZ4hJLN9f/v/Ywz/lxVZt20Jrjc1mg+h0wjiO0MbA+WXz5Bz6vl+a2DBOE0zXheaOecv9kveP+koKwzAgSRLElwuqRuHwofGmJ1yMw1s74qXQ+KMk9oiUxb7USAdgVxqc1YBX5s/aQU8zVnKyAMZxHEDFq6oChII4J32tNE5mClMJA0MGYUJOuiHoffCM5rA9TCiUoijCfr/HibR1q0jhh7I0+odG00TA7gfQDBZL5aGh6DdRl7Isv9NJ3cI6v8SzQ6F7VNajHme8mxG5WgBV16MwFg3zH5zSelI+Ho9Q1O12u0FuvKlrvOQNTtSwI2ZBoN/Ur2BDIYDdiF9ZC+VA7RwiejV65KwPAuhISTTM8xxZluGda9XUyDqLnM03TlSYnqMS3U3w44B7rZDzoFR1sNZSZ6JTChFxVXMieYNCPTgFT9MULUG1alDmGZL4wulLKD4xWbP7PdTSJMb1ekXdNKiII08oXMqzyQ3udrtAXyzLcqzX63CY2J1g+8OBscF2u8X5fP6r/x9AkUBARYavv0ZozX65JMlLXfbJE5L1+U/5BNw3UlWifQkoAAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 1' title='' src='/static/1a630d318cb1fe19075afd79242ae35b/448ef/img_1.png' srcset='/static/1a630d318cb1fe19075afd79242ae35b/e7570/img_1.png 170w, +/static/1a630d318cb1fe19075afd79242ae35b/f46e7/img_1.png 340w, +/static/1a630d318cb1fe19075afd79242ae35b/448ef/img_1.png 372w' sizes='(max-width: 372px) 100vw, 372px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<p>실제 발생하는 대부분의 인터럽트는 I/O 인터럽트이다. +예를들면, 우리가 자바에서 print을 할 때 print라는 API를 파일이라는 인터페이스를 통해서 유저모드에서 커널 모드로 시스템 콜이 발생한다. +유저모드 API에서 커널모드 구성요소에서 시스템 콜이 이어지고 디바이스 드라이버를 제어하기 시작하는데 +<a href="https://en.wikipedia.org/wiki/Interrupt_request#:~:text=In%20a%20computer,or%20mouse%20movements.">이때 디바이스 드라이버가 인터럽트를 CPU에 요청한다. 이 행위를 IRQ라고 한다.</a> +이러한 IRQ는 장치마다 다른 번호로 관리하게 된다. +아무튼 출력기기에 출력이 되면, 다시 역순으로 디바이스(하드웨어)에서 디바이스 드라이버로, +디바이스 드라이버에서 커널 모드로 해서 최종적으로 유저 모드로 다시 돌아오게 된다.</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/5ad9fd0cefdd153390ee5a6d0acfa4f9/a91f8/img_4.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 47.05882352941176%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAABnUlEQVR42l2Sy0/CQBDG++/jhYSDGhOvJoQYiI9IjCdPxsdRjUGUvhBoS5/Qdnfbz5kFBJlkspPdmd98M60Bsqos8dVqYXBwgGGziUGjoX10dIRaCGyslBVO7z5w3H/Dye27Pg9vXnF2/wmpap1jaCAVOefncDodjLtd7Xa7DbfXQyXlFigUrp9GuHwycfFo4urZRPfhG/0XC0pVK2BVVVgul6jrGhkp9cIQfhQhpSaK3sSOQo4rpaBEAZFnkMUCtRSo1wxmGYoSFosFAs9DmiSITBPxaISEoLPp9B9QihJDZwp3MoPrjjH+mSAIQnievwWSNAhSNp/Pkec5AlIYETgvCoQUy52RFamxJz6SNEMcR4ioaUm1Oo9OZhk5qYvjGGmW6QQGB0GgnWMu+NthWcCfRwjont9839ewkOoSYuSk0lA0EkP5ISOobdvaE1LJBf93WMKdEiSKYdJqXNdFlqar6QimaJrVyDQeK+RdWpalnWNusP9R4iTVzRjoOI7eHefJ9ST6t+EvzAtl44SCGmzu+NzY7h035HXs5/0CfzWpjbds3BAAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 4' title='' src='/static/5ad9fd0cefdd153390ee5a6d0acfa4f9/ca1dc/img_4.png' srcset='/static/5ad9fd0cefdd153390ee5a6d0acfa4f9/e7570/img_4.png 170w, +/static/5ad9fd0cefdd153390ee5a6d0acfa4f9/f46e7/img_4.png 340w, +/static/5ad9fd0cefdd153390ee5a6d0acfa4f9/ca1dc/img_4.png 680w, +/static/5ad9fd0cefdd153390ee5a6d0acfa4f9/a91f8/img_4.png 960w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> +이때, 이러한 행위 도중 wait을 걸면 블라킹(동기) 안걸면 논블라킹(비동기)으로 동작하게 된다.</p> +<p>인터럽트에는 우선순위가 있고 외부 인터럽트인지 내부 인터럽트인지에 따라 우선순위가 달라진다.</p> +<p>먼저, 외부 인터럽트로 내부 인터럽트보다 우선 시 된다.</p> +<p>그 중에서도 우선 순위가 있는데, 다음과 같다.</p> +<ul> +<li>전원 이상 인터럽트: 말 그대로 정전 또는 파워 이상</li> +<li>기계 착오 인터럽트: CPU의 기능적인 오류.</li> +<li>외부 신호 인터럽트: 타이머 또는, 키보드 인터럽트 키(Ctrl + Alt + Delete). 외부장치로부터 인터럽트 요청이 있는 경우. I/O 인터럽트와 다른 개념이다.</li> +<li>입출력 인터럽트: 입출력 장치가 데이터 전송을 요구하거나 전송이 끝나 다음 동작이 수행되어야 할 경우. 입출력 데이터에 이상이 있는 경우. 우리가 자주 다루게 될 인터럽트 부분이다.</li> +</ul> +<p>이제 내부 인터럽트인데, 사실 우리가 주로 다루게 될 것은 외부 인터럽트에 있어 내부 인터럽트는 뭐가 있는지만 대강 본다.</p> +<ul> +<li>명령어 잘못 인터럽트: 잘못된 명령어나 잘못된 데이터를 사용할 때 발생하며 Trap이라 부른다,</li> +<li>프로그램 검사</li> +<li>소프트웨어 인터럽트(=SVC, SuperVisor Call)</li> +</ul> +<p>인터럽트 동작 순서에 대해 다시 살펴보면 다음과 같은데,</p> +<ol> +<li>인터럽트 요청</li> +<li>프로그램 실행 중단</li> +<li>현재 프로그램 상태 보존 -> PCB(Process Control Block), PC(Program Counter) 등</li> +<li>인터럽트 서비스 루틴 실행: 인터럽트 처리 코드</li> +<li>상태 복구</li> +<li>중단 프로그램 실행 재개</li> +</ol> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 307px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/0c0c26d4cb27ec122a387afdfb39ca8f/ca17f/img_2.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 78.23529411764706%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsTAAALEwEAmpwYAAACTUlEQVR42qWUW5OaQBCF/f9/I295yEuSqq11t7LxLoogKqgooomilK6KIuLtpHsEZbdqH5J0VeOMM/NxTvdo6nQ6IfB32O0C+PTpb33sovn5fAbH5XK5JUe4D8WegPbEud/vxVpqtfYgqw1IDQPflQ7qTQMVmiuajsPhgGTEQMse0ZkmVDrDWavraHf7d6BCEMkw8bneQ6NtokbzYkWG4ziYTCawbRuWZWE4HMJ1XbSMDmR6odJqi6xqLbTNCLhcrfEzm8dLQcK3XAWZbAG5cgWP6WeyvROqlsslptOpUHy5nNEnhaWqgvTTDzw8plEoV9HpDyLgeo1soQyJNlRkRSyyulxJEmrcmQtnclXK6dH+pt6Gqnfo5UU8Pb9AJZVGbHlJlllyUZKRKZRQllVU603I9cathlHpROyDAFpTR62hk+2mqLdM45vlI3X593iMiTOBaZoYDAYYjX4Jm8kuc6xWK/F9z7KFCFbGKSdryI/NZoMwDLHdbkX6vi8Wk8DFYiGAcZfZBTfzqvQdkN/KED7EQK5brGpNNeMOB2Q1Dmt4BWpGV+Qby/yYzWZC5WLxig0BZ9OZWOQuc2NYfdJ6b2CjojRE4zL5EiRFg97t3YFshYvted7NMo/n8/kNkvyljKnrRseEWtdQU1QYdHdtqvsdSLZe1xv0Vnu43hY2WWLFH0US/n4ugMfjEfmxhy8dF+kRwTdRU5L35UP427kAekGIFyfAp2oPX60lHD+6f/j7SEUVwtALkHND6Isd+B/oXyMVDw7HkwCFZP9/4g/m37cx2ey4VAAAAABJRU5ErkJggg=='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 2' title='' src='/static/0c0c26d4cb27ec122a387afdfb39ca8f/ca17f/img_2.png' srcset='/static/0c0c26d4cb27ec122a387afdfb39ca8f/e7570/img_2.png 170w, +/static/0c0c26d4cb27ec122a387afdfb39ca8f/ca17f/img_2.png 307w' sizes='(max-width: 307px) 100vw, 307px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<p>이 과정에서 유저모드에서 커널모드로 넘어갈 떄 컨텍스트 스위칭이 되면서 오버헤드가 발생하는데 이로 인해 시스템 상 지연이 발생한다. +하지만 고성능 어플리케이션을 할 때 이 지연은 꽤나 치명적일 것이다. +그래서 위와 같이 DMA(Direct Memory Access)라는 기술을 사용하게 됐다. +예를들어, DirectX라는 것이 있는데 이는 게임을 할 때 이러한 컨텍스트 스위칭 되는 부분을 건너뛰어 직접 드라이버까지 가는 방식이 있다. +이렇듯 DirectX처럼 인터럽트 시 컨텍스트 스위칭으로 인한 오버헤드가 발생하면서 지연이 발생하는데 이걸 해소하는 것이 DMA인 것이다. +정리하자면, <a href="https://en.wikipedia.org/wiki/Direct_memory_access#:~:text=DMA%20(%20Direct%20Memory%20Access%20)%EB%8A%94%20%ED%8A%B9%EC%A0%95%20%ED%95%98%EB%93%9C%EC%9B%A8%EC%96%B4%20%ED%95%98%EC%9C%84%20%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%B4%20%EC%A4%91%EC%95%99%20%EC%B2%98%EB%A6%AC%20%EC%9E%A5%EC%B9%98%20(CPU)%20%EC%99%80%20%EB%8F%85%EB%A6%BD%EC%A0%81%EC%9C%BC%EB%A1%9C%20%EC%A3%BC%20%EC%8B%9C%EC%8A%A4%ED%85%9C%20%EB%A9%94%EB%AA%A8%EB%A6%AC%20%EC%97%90%20%EC%95%A1%EC%84%B8%EC%8A%A4%ED%95%A0%20%EC%88%98%20%EC%9E%88%EB%8F%84%EB%A1%9D%20%ED%95%98%EB%8A%94%20%EC%BB%B4%ED%93%A8%ED%84%B0%20%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%9D%98%20%EA%B8%B0%EB%8A%A5%EC%9E%85%EB%8B%88%EB%8B%A4%20.">DMA는 RAM에 일정 부분을 예약해 불필요한 컨텍스트 스위칭을 스킵해 오버헤드 방지 및 지연을 획기적으로 줄이는 방식이다.</a></p><![CDATA[운영체제의 역할과 커널의 기능]]>https://catch-npe.netlify.app/jc1/https://catch-npe.netlify.app/jc1/Thu, 04 Sep 2025 00:00:00 GMT<h2 id="운영체제란-무엇일까" style="position:relative;"><a href="#%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C" aria-label="운영체제란 무엇일까 permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>운영체제란 무엇일까?</h2> <hr> <p><strong>운영체제</strong>는 컴퓨터 하드웨어와 소프트웨어를 관리하고, 사용자와 컴퓨터 사이 인터페이스 역할을 합니다. 대표적인 기능으로는 <strong>자원</strong>을 <strong>관리</strong>하고, </br> 프로세스를 관리하는 등 여러가지 일을 수행합니다.</p> @@ -758,4 +2915,90 @@ CPU 관점에서 본다면 특정 작업을 수행중 IO 작업이 생긴다면 </br> <strong>테이프</strong>를 가지고 누가먼저 쓸지 싸우는 학생, </br> 혹은 <strong>지우개</strong>를 망가뜨린 학생등 많은 사고가 있을 것입니다.</p> <p>이러한 문제가 벌어지는 이유는 공용 문구를 사용할때 <strong>통제권</strong>이 모두에게 있기 떄문입니다. 그렇다면 이를 해결하기 위해서 -모두에게 있는 <strong>통제권</strong>을 하나로 합쳐서 해결하면 되는 문제이고 이것이 자원을 사용하기 위해 <strong>커널의 관리</strong>를 받아야 하는 이유입니다.</p> \ No newline at end of file +모두에게 있는 <strong>통제권</strong>을 하나로 합쳐서 해결하면 되는 문제이고 이것이 자원을 사용하기 위해 <strong>커널의 관리</strong>를 받아야 하는 이유입니다.</p><![CDATA[1. 운영체제의 개념과 구조]]>https://catch-npe.netlify.app/hs1/https://catch-npe.netlify.app/hs1/Wed, 03 Sep 2025 00:00:00 GMT<h2 id="운영체제OS-Operating-System" style="position:relative;"><a href="#%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9COS-Operating-System" aria-label="운영체제OS Operating System permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>운영체제(OS, Operating System)</h2> +<p><a href="https://en.wikipedia.org/wiki/Operating_system#:~:text=An%20operating%20system%20(OS)%20is%20system%20software%20that%20manages%20computer%20hardware%20and%20software%20resources%2C%20and%20provides%20common%20services%20for%20computer%20programs.">운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다.</a></p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 321px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/f088a9700a8076ec085906f440e7ba02/4f068/img.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 48.8235294117647%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABQElEQVR42l2SDZKCMAyFe/8LeoOVAVGkvxQw2y8QdTczMZi+pC8vdSEEGcdRns+n5Jzl8XjIPM9yu92EM3Mw0zSJ917WdZXX6yW1Vq253+9aB87llBWEL2XRIospJokxagw+iJ+9xBBl3zbBaFxKaWQmbQbOlXKwgsGyFAWQ6/tefPBHrvkHs5yYwzmHIYRS1oZHAmcMjNwwDJrDaIIE5LaT3b7vGpHncrkoQyRw/GA0A2z6AKAJTLuu0++x+c/1qjLQEDz1XGgXO/tTW7RbyOlo57g6Xou5SaFj1uMcrPezkrDJHEKyBARPKb3ZmrEcWMIQt7NveVgUPYjOCrnNGta1SkxRwTwL2CC4MSWCZWyiMcTeDTmkmMZoxLeJznZZEAxphulzas3A2YL+NPw2xEZPZdbeaTiL9aJ0MLbF/LdfQpcKG3KLFN8AAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img' title='' src='/static/f088a9700a8076ec085906f440e7ba02/4f068/img.png' srcset='/static/f088a9700a8076ec085906f440e7ba02/e7570/img.png 170w, +/static/f088a9700a8076ec085906f440e7ba02/4f068/img.png 321w' sizes='(max-width: 321px) 100vw, 321px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<p>운영체제가 없으면 어떻게 될까? 꼭 필요할까?</p> +<blockquote> +<p><em>A computer is a machine that can be programmed to automatically carry out sequences of arithmetic or logical operations</em> +(컴퓨터는 산술적 또는 논리적 연산(계산)의 순서를 자동으로 수행하도록 프로그래밍할 수 있는 기계이다). +<a href="https://en.wikipedia.org/wiki/Computer#:~:text=A%20computer%20is%20a%20machine%20that%20can%20be%20programmed%20to%20automatically%20carry%20out%20sequences%20of%20arithmetic%20or%20logical%20operations%20(computation)."> - wikepedia</a></p> +</blockquote> +<p>운영체제가 없다면 컴퓨터는 그저 하드웨어의 집합체에 불과하다. +사용자는 프로그램을 실행하기 위해서 매번 하드웨어를 직접 제어해야 하며, 이렇게 하는 것은 매우 비효율적일거다. +또한 직접 제어를 한다고 해도 하드웨어의 성능은 제한적이므로 이 환경에서 최대한의 성능을 끌어내기 위해 최적화라는 고통스러운 작업을 해야 할 것이다. +이러한 상황을 상상해보면 "배보다 배꼽이 더 크다"라는 말이 떠오른다.</p> +<p>실제로 운영체제라는 개념이 있기 전에는 사용자들이 하나의 작업을 위해 펀치카드를 소지하며 관리해야 했다. +그리고 단순 하드웨어에 올려 실행하는 과정의 방식이기에 한 번에 하나의 프로그램만 실행할 수 있었고, 해당 프로그램이 끝나야 다른 프로그램을 수행할 수 있었다. +지금처럼 복잡한 방식의 프로그램은 꿈도 꿀 수 없었을 것이다.</p> +<p>이러한 문제를 해결하기 위해 운영체제가 나왔고, 다음과 같은 목적을 지닌다.</p> +<ul> +<li>사용자에게 컴퓨터의 프로그램을 쉽고 효율적으로 실행할 수 있는 환경을 제공한다.</li> +<li>컴퓨터 시스템 하드웨어 및 소프트웨어 자원을 여러 사용자 간에 효율적 할당, 관리, 보호하는 것</li> +<li>운영체제는 제어 프로그램으로서 사용자 프로그램의 오류나 잘못된 자원 사용을 감시하는 것과 입출력 장치 등의 자원에 대한 연산과 제어를 관리한다.</li> +</ul> +<p>운영체제은 위와 같은 목적을 위해 다양한 방식을 가지고 있다.</p> +<h3 id="일괄-처리-시스템-Batch-Operating-System" style="position:relative;"><a href="#%EC%9D%BC%EA%B4%84-%EC%B2%98%EB%A6%AC-%EC%8B%9C%EC%8A%A4%ED%85%9C-Batch-Operating-System" aria-label="일괄 처리 시스템 Batch Operating System permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>일괄 처리 시스템 (Batch Operating System)</h3> +<p>사용자의 개입없이 비슷한 작업들을 모아서 순차적으로 처리하는 방식이다. +한 작업이 끝나야 다음 작업이 실행되기 때문에 모든 작업이 완료될 때까지 기다릴 수 있는 환경에서 사용된다. +주로 대용량 데이터를 처리하거나 시간이 많이 소요되는 작업에 활용되며, 사용자의 개입이 필요하지 않고 반복적인 작업을 일괄적으로 처리할 수 있다.</p> +<h3 id="다중-프로그래밍-시스템-Multi-Programming-System" style="position:relative;"><a href="#%EB%8B%A4%EC%A4%91-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%8B%9C%EC%8A%A4%ED%85%9C-Multi-Programming-System" aria-label="다중 프로그래밍 시스템 Multi Programming System permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>다중 프로그래밍 시스템 (Multi Programming System)</h3> +<p>이 방식은 CPU을 최대한 사용하고 하는 방식으로, +여러 응용프로그램을 메모리에 동시에 올라가 CPU가 쉬지 않고 여러 작업을 번갈아서 실행하며 항상 연산을 수행하는 상태로 활용하는 방식이다. +하나의 프로그램을 실행하는 동안 다른 프로그램은 대기하거나 I/O 작업 등을 수행하며 메모리에 올라간 상태로 대기하게 된다. +운영 체제는 이런 과정에서 CPU를 배분하는 작업 스케줄링과 CPU 스케줄링을 진행하며, +이를 통해 시스템 자원을 효율적으로 활용하고 응용 프로그램들이 서로 영향을 주지 않으면서 병렬적으로 실행된다.</p> +<h3 id="시분할-시스템-Time-Sharing-System" style="position:relative;"><a href="#%EC%8B%9C%EB%B6%84%ED%95%A0-%EC%8B%9C%EC%8A%A4%ED%85%9C-Time-Sharing-System" aria-label="시분할 시스템 Time Sharing System permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>시분할 시스템 (Time Sharing System)</h3> +<p>이 방식은 CPU에 대해 일정 시간을 할당 받아 짧은 간격으로 번갈아 실행하는 방식이다. +다중 프로그래밍 시스템에서는 Context Switching(CPU 점유 권한 전환)이 I/O작업에서만 발생한다. +이를 통해서만 스케줄링을 할 경우 하나의 프로세스가 아주 오래 CPU를 독점하고 있는 상태가 발생할 수 있다는 문제점이 있다. +이를 해결하기 위한 것이 시분할 시스템으로, 다중 프로그래밍과 비슷하지만 모든 프로세스가 특정 시간만 CPU를 점유하고 다른 프로세스에 권한을 넘겨주는 방식으로 +Context Switching 기준 시간으로 시분할을 구현해서 RR(Round-Robin) 알고리즘으로 스케줄링을 한다.</p> +<h3 id="대화형-시스템Interactive-System" style="position:relative;"><a href="#%EB%8C%80%ED%99%94%ED%98%95-%EC%8B%9C%EC%8A%A4%ED%85%9CInteractive-System" aria-label="대화형 시스템Interactive System permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>대화형 시스템(Interactive System)</h3> +<p>앞서 설명한 일괄 처리 시스템은 처리해야할 작업들을 한번에 정의하고 일괄적으로 처리하는 방식이었다. +이러한 일괄 처리 시스템의 문제점은 처리가 이루어지는 중에 시스템의 상태를 확인하기가 힘들고, +작업이 끝나 결과가 도출되기 전까지는 작업을 수정할 수도 없다는 문제점이 있었다. +이를 보완하기위해 등장한 시스템이 대화형 시스템으로, +작업 중에도 사용자가 데이터, 명령 또는 작업을 입력하면 컴퓨터가 즉각적으로 해당 입력에 응답하는 사용자와 컴퓨터 간의 상호작용을 통해 작동하는 방식이다.</p> +<h2 id="커널Kernel" style="position:relative;"><a href="#%EC%BB%A4%EB%84%90Kernel" aria-label="커널Kernel permalink" class="heading-anchor before"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24"><path d="M6.188 8.719c.439-.439.926-.801 1.444-1.087 2.887-1.591 6.589-.745 8.445 2.069l-2.246 2.245c-.644-1.469-2.243-2.305-3.834-1.949-.599.134-1.168.433-1.633.898l-4.304 4.306c-1.307 1.307-1.307 3.433 0 4.74 1.307 1.307 3.433 1.307 4.74 0l1.327-1.327c1.207.479 2.501.67 3.779.575l-2.929 2.929c-2.511 2.511-6.582 2.511-9.093 0s-2.511-6.582 0-9.093l4.304-4.306zm6.836-6.836l-2.929 2.929c1.277-.096 2.572.096 3.779.574l1.326-1.326c1.307-1.307 3.433-1.307 4.74 0 1.307 1.307 1.307 3.433 0 4.74l-4.305 4.305c-1.311 1.311-3.44 1.3-4.74 0-.303-.303-.564-.68-.727-1.051l-2.246 2.245c.236.358.481.667.796.982.812.812 1.846 1.417 3.036 1.704 1.542.371 3.194.166 4.613-.617.518-.286 1.005-.648 1.444-1.087l4.304-4.305c2.512-2.511 2.512-6.582.001-9.093-2.511-2.51-6.581-2.51-9.092 0z"/></svg></a>커널(Kernel)</h2> +<p>그럼 우리들의 컴퓨터 속 운영체제는 어떻게 이러한 기능을 수행하고 있을까?</p> +<p><a href="https://en.wikipedia.org/wiki/Kernel_(operating_system)#:~:text=A%20kernel%20is%20a%20computer%20program%20at%20the%20core%20of%20a%20computer%27s%20operating%20system%20that%20always%20has%20complete%20control%20over%20everything%20in%20the%20system.">운영체제의 이러한 핵심적인 부분을 담당하고 수행하는 것이 바로 커널이다.</a></p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 680px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/ebd2df5e4fc75937d87288e2d3c9faaa/ca1dc/img_3.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 11.76470588235294%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAPklEQVR42mOIio75HxIS9j8hMem/uYXVfylp2f/yCkr/5eQVycIMRsam/62sbf+bAQ3T0tb9LyMrT7ZhIAMBwgY529uQYkkAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 3' title='' src='/static/ebd2df5e4fc75937d87288e2d3c9faaa/ca1dc/img_3.png' srcset='/static/ebd2df5e4fc75937d87288e2d3c9faaa/e7570/img_3.png 170w, +/static/ebd2df5e4fc75937d87288e2d3c9faaa/f46e7/img_3.png 340w, +/static/ebd2df5e4fc75937d87288e2d3c9faaa/ca1dc/img_3.png 680w' sizes='(max-width: 680px) 100vw, 680px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span> +커널을 한글로 번역하면 핵심이다! 재밌지 아니한가? 아무튼 다시 돌아와서 커널은 어떻게 운영체제의 기능을 수행할까?</p> +<p><a href="https://en.wikipedia.org/wiki/Kernel_(operating_system)#:~:text=The%20kernel%27s%20interface%20is%20a%20low%2Dlevel%20abstraction%20layer.%20When%20a%20process%20requests%20a%20service%20from%20the%20kernel%2C%20it%20must%20invoke%20a%20system%20call%2C%20usually%20through%20a%20wrapper%20function.">커널은 하드웨어를 인터페이스로 제공하여 여러 사용자 또는 여러 프로세스가 하드웨어 즉 리소스를 효율적으로 관리하며 작업을 수행할 수 있도록 해준다.</a> +여기서 중요한 점은 커널은 사용자가 직접 제어할 수는 없다. +그 이유는 보안상 유저 어플리케이션이 함부로 운영체제의 리소스를 건들지 못하게 하기 위해서다. +그래서 커널에는 하드웨어에 접근이 허가된 커널모드와 그렇지 못한 유저모드로 분리가 되어있다.</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 500px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/bc8fb9aa2787340e6ee47b5193e7e072/0eb09/img_1.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 51.764705882352935%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABbUlEQVR42oWS227CMBBE8/+fhsQDECogXJIAKQkBwj1cpz6ruo36UkujbOzZ2dm1A/1Z7/db0WikxWKhw+Gg7Xar/X6vqqr0fD713wqaQo/HQ/f7XUVRaLlcqr7dlLv4eDwazuez8Zrr9XpZIUAceDFWEsfqdDrmJk0SJQ7z+dxAvNlsdDqd1MxB6OYK0wmGTJCg2u1MKMsya3U8HmvkWp9Op4qiSMPh0FxzhkjTKflFnv+2fLlc1G63TYwYYeaGGKIgdwns+/bh+VXXtRmgkAlieTKZ2EVQjeQ0TW1vMBiYu9lsZueI0XZZlpYHH6FyvTbXJgiBy+AQIojdzMJeT2EY6qPfV99htVpZMUS5gOv1+tMRBfkGbK6dOqIc+iTm1mq11O12TbTnxLmYTzeWnZs3eQhwGXyZL2MK/PvyDqnM4CkAmXZpHzLOmBd8uB7w+VrL/CDGPAAJOASZqxq7p4QgzrJvd57rQSH/sL8Afhb6nLIccbYAAAAASUVORK5CYII='); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 1' title='' src='/static/bc8fb9aa2787340e6ee47b5193e7e072/0eb09/img_1.png' srcset='/static/bc8fb9aa2787340e6ee47b5193e7e072/e7570/img_1.png 170w, +/static/bc8fb9aa2787340e6ee47b5193e7e072/f46e7/img_1.png 340w, +/static/bc8fb9aa2787340e6ee47b5193e7e072/0eb09/img_1.png 500w' sizes='(max-width: 500px) 100vw, 500px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<p>커널의 구조는 위 사진과 같은데, 간단한 흐름을 설명하자면 사용자가 유저모드인 어플리케이션을 실행하면서 발생하는 요청이 시스템 콜을 통해 커널 모드로 전환이 된다. +애플리케이션은 커널모드로 전환되었다가 작업을 끝낸 후 응답을 반환하면서 다시 유저모드로 되돌아 가게 된다. +여기서 시스템 콜은 뭐지 싶을텐데 <a href="https://en.wikipedia.org/wiki/System_call#:~:text=In%20computing%2C%20a%20system%20call%20(syscall)%20is%20the%20programmatic%20way%20in%20which%20a%20computer%20program%20requests%20a%20service%20from%20the%20operating%20system%5Ba%5D%20on%20which%20it%20is%20executed.">어플리케이션의 요청이 커널에 접근해 시스템에 요청하는 것</a>으로 간단히 유저모드에서 커널모드로 전환하는 것이라고 생각하면 된다.</p> +<p><span class='gatsby-resp-image-wrapper' style='position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 527px; margin-bottom: 16px;'> + <a class='gatsby-resp-image-link' href='/static/a57012c6b3b5f784fbf2bdeda164852d/c6c03/img_4.png' style='display: block' target='_blank' rel='noopener'> + <span class='gatsby-resp-image-background-image' style="padding-bottom: 41.1764705882353%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABPklEQVR42q1RXY+CQAzk//+zS3zACIpEQEBgcVFgNSDxY27KAZfc801Cdrd0ptPWMsYgSRI0TQN0HXA8Ap8PRrzfQBQBw/Dzfj6BPAfI4R8EhwM8z8N2u4Vt20wbYD2Z1Pc9eoopJpdMUEUBpTXKNIXyfZQsqMoSZRxD8Z4z3j8eU8338gksTHhRWF+vqE4naApqkirXhT6fx1i126GioK5rnBnraOByuYyfvAtypMtfwdcL0r4hoaW7Ogxh9nuY+x0NCfV6DcPT3G5o23Zs78RCEUciI/PZiYgugpIQBAFiunDo7Gu1QsoEIdgUW9NhTNchCx04uzsLCT7zvCcsgjIDqeA6DiKSQopvKCSVUzpwNhv4dCwLkEXI3GeeiM7nIigPmYW4zLKMy8xHMXGklBrjcpdTXA/z5v/Awj/jG3BEX6CtiC43AAAAAElFTkSuQmCC'); background-size: cover; display: block;"></span> + <img class='gatsby-resp-image-image' alt='img 4' title='' src='/static/a57012c6b3b5f784fbf2bdeda164852d/c6c03/img_4.png' srcset='/static/a57012c6b3b5f784fbf2bdeda164852d/e7570/img_4.png 170w, +/static/a57012c6b3b5f784fbf2bdeda164852d/f46e7/img_4.png 340w, +/static/a57012c6b3b5f784fbf2bdeda164852d/c6c03/img_4.png 527w' sizes='(max-width: 527px) 100vw, 527px' style='width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;' loading='lazy' decoding='async'> + </a> + </span></p> +<p>이러한 방식을 통해 사용자의 프로세스가 직접적으로 운영체제의 리소스를 함부로 변경하지 못하게 보호해준다.</p> \ No newline at end of file diff --git a/public/search/index.html b/public/search/index.html index 8e22d3f..0fc91c9 100644 --- a/public/search/index.html +++ b/public/search/index.html @@ -1,4 +1,4 @@ -CATCH NPESERIES: CPU 스케줄링

SERIES

CPU 스케줄링

4 Posts·Last updated on September 18, 2025

CPU 스케줄링의 목적과 스케줄러의 종류

September 15, 2025

CPU 할당? 지금까지 배운 내용을 토대로 프로세스는 CPU를 필요로 하며, 프로세스가 실행 된다는 말은 메모리에 올라간 데이터를 토대로 프로세스가 CPU를 할당받아 사용 +하는것을 프로세스가 실행 된다고 표현합니다. 그 과정에서 프로세스는 일정 주기마다 컨텍스트 스위칭을 통해 CPU 할당을 바꾸고 IO요청에 대해서도 대기 상태로 들어가는 등 +CPU사용에 …


선점형과 비선점형 스케줄링의 차이 및 기아 상태와 해결 방법

September 16, 2025

선점형? 비선점형? 개요 CPU 스케줄링은 자원 선점 후 자원에 대한 권한이 뺏길 수 있냐 없냐에 따라 두가지로 나누게 됩니다. 여기서 자원을 사용하고 있음에도 외부에서 CPU 자원을 뺏는 방식과, 한번 점유한 CPU 자원을 끝가지 사용할 수 있는 방식이 있습니다. 선점형 스케줄링 선점의 사전적 정의는 '남보다 앞서서 차지함'이라는 뜻을 가지게 됩니다. …


CPU 스케줄링 알고리즘 (FCFS, SJF, SRTF, 우선순위, 라운드 로빈)

September 17, 2025

스케줄링 알고리즘 개요 스케줄링 알고리즘중 다섯가지의 알고리즘을 선점, 비선점을 통해 설명하겠습니다. 비선점 스케줄링 선입 선처리 스케줄링 (FCFS) 최단 작업 우선 스케줄링 (SJF) 선점 스케줄링 라운드 로빈 스케줄링 최소 잔여 시간 우성 스케줄링 (SRT) 우선순위 스케줄링 비 선점 스케줄링 선입 선처리 스케줄(FCFS) FCFS는 준비 큐에 들…


멀티 레벨 큐와 멀티 레벨 피드백 큐 스케줄링

September 18, 2025

다단계 큐 스케쥴링(Multilevel queue scheduling) 멀티 레벨 스케줄링은 우선순위 스케줄링의 발전된 형태입니다. +아래 그림을 통해 설명 하면, 이전에는 준비상태에 해당하는 단 하나의 큐만 사용하여 스케줄링을 진행하였는데, +멀티레벨 스케줄링은 우선순위에 따른 n개의 큐를 이용하는 방식입니다. 가장 높은 우선순위에 있는 큐들을 처리하고,…

+ + \ No newline at end of file diff --git a/public/series/index.html b/public/series/index.html old mode 100644 new mode 100755 index 17139cb..d8b2bf0 --- a/public/series/index.html +++ b/public/series/index.html @@ -1,4 +1,4 @@ -CATCH NPESERIES: 가상메모리, 메모리분할

SERIES

가상메모리, 메모리분할

4 Posts·Last updated on September 26, 2025

물리주소, 논리주소 그리고 메모리 분할 방식

September 23, 2025

물리주소와 논리주소 메모리는 보조기억장치로 부터 실행될 프로그램을 받아서 저장합니다. +이 저장된 메모리의 데이터를 CPU 혹은 실행중인 프로그램이 읽어 실행하게 됩니다. 해당 그림은 두가지 관점으로 주소를 나누고 사용하는 방식을 그림으로 나타낸 것입니다. 왜, 주소를 두가지 방식으로 나누어서 사용하게 되었을까요? 이유는 메모리에 저장되어 있는 정보는 변…


메모리 배치기법 그리고 단편화에 대해

September 24, 2025

연속 메모리 할당 연속 메모리 할당이란 메모리에 프로세스가 그림처럼 연속적으로 배치되는 상황을 가정합니다. 프로세스 A가 할당되고, 남는 주소만큼 이어서 B,C,D...를 할당하는 방식입니다. 이런 방식은 예제를 위한 단편적인 설명만 가능한데 이유는 아래에서 설명할 스와핑과 관련이 있습니다. 스와핑이란? 메모리는 실행시킬 프로세스를 적재하게 됩니다. 하…


페이징

September 25, 2025

연속 할당의 문제점 연속적 할당의 대표적인 문제점은 외부 단편화가 있습니다. 외부 단편화란 특정 프로세스를 실행시키기 위해 +필요한 공간이 있음에도 빈공간이 연속적이지 않아서 발생하는 문제입니다. 이러한 문제를 해결하기 위해서는 불연속 할당 방식 중 대표적인 페이징기법을 사용할 수 있습니다. 페이징이란? 페이징 기법은 프로세스를 일정한 단위로 자릅니다. …


요구페이징을 잘 수행하기 위해서 필요한 것들

September 26, 2025

서론 지금까지 가상 메모리를 통해서 실제 물리적 메모리 보다 더 많은 프로세스를 실행할 수 있다고 배웠습니다. +이러한 행위는 한정된 메모리를 어떻게 더 효율적으로 사용할까에서 출발하게 됩니다. 그럼에도 더 효율적인 메모리를 이용하기 위해서 두가지 방법을 더 고려하게 됩니다. 불필요한 페이지를 선별 후 스왑 아웃 한다. 프로세스에게 적절한 프레임을 할당한다…

+ + \ No newline at end of file diff --git "a/public/series/\354\232\264\354\230\201\354\262\264\354\240\234-\352\270\260\353\263\270-\352\260\234\353\205\220/index.html" "b/public/series/\354\232\264\354\230\201\354\262\264\354\240\234-\352\270\260\353\263\270-\352\260\234\353\205\220/index.html" index d09810c..a9549e3 100644 --- "a/public/series/\354\232\264\354\230\201\354\262\264\354\240\234-\352\270\260\353\263\270-\352\260\234\353\205\220/index.html" +++ "b/public/series/\354\232\264\354\230\201\354\262\264\354\240\234-\352\270\260\353\263\270-\352\260\234\353\205\220/index.html" @@ -1,4 +1,4 @@ -SERIES: 운영체제 기본 개념SERIES: 운영체제

SERIES

운영체제

5 Posts·Last updated on September 12, 2025

1. 운영체제의 개념과 구조

September 03, 2025

운영체제(OS, Operating System) 운영체제는 컴퓨터라는 기계 안에서 프로그램과 하드웨어 사이에서 문제없이 그리고 효율적으로 잘 돌아가도록 관리해주는 소프트웨어이다. 운영체제가 없으면 어떻게 될까? 꼭 필요할까? A computer is a machine that can be programmed to automatically carry ou…


2. 커널의 작동 방식

September 04, 2025

앞서, 운영체제란 무엇인지 그리고 커널에 대해 간단하게 알아봤다. +이제 커널이 어떻게 작동하는지 제대로 알아보자. 먼저 인터럽트(Interrupt)에 대해 알아야 한다. 컴퓨터는 위 사진처럼 주변 입출력 기기와 서로 통신하는데 +이 과정에서 서로 입출력 요청이 오가는데 이때 입출력 메커니즘들이 발생된다. +이중 하나가 인터럽트이다. +인터럽트는 중단시키다라…


4. 쓰레드

September 08, 2025

쓰레드란? 쓰레드는 프로세스를 구성하는 실행 흐름의 단위를 의미합니다. 그래서 하나의 프로세스는 1개 이상의 쓰레드를 가집니다. +이로 인해 하나의 프로세스에서 여러 작업을 동시에 수행할 수 있습니다. 사용자 수준 쓰레드와 커널 수준 쓰레드의 차이 사용자 수준 쓰레드란, 라이브러리를 통해 구현한 쓰레드를 의미합니다. +쓰레드와 관련된 모든 행위를 사용자 영…


3. 프로세스

September 08, 2025

프로세스란? 컴퓨팅에서 프로세스란 운영체제로부터 메모리 공간을 할당받아 실행 중인 프로그램의 인스턴스를 의미합니다. +여기서 논하는 프로그램이란, 일반적으로 하드 디스크와 같은 저장장치에 저장되어 있는 실행 코드를 뜻합니다. 프로세스의 메모리 공간 프로세스는 다음 4개의 메모리 영역으로 구성되고 가상 메모리 공간에 독립적으로 형성됩니다. 코드 영역(Cod…


5. CPU 스케줄링

September 12, 2025

기아 상태와 CPU 스케줄링 프로세스들은 실행할 때 컴퓨터 자원을 사용하는데, 이때 CPU도 사용합니다. +그런데 만약 하나의 프로세스가 오랜 시간 동안 CPU를 점유하거나, +너무 짧은 텀동안만 실행되는 경우 공정하지 못한 방법으로 자원을 할당하게 될 것이고 +이는 시스템의 효율적이지 못한 방법으로 돌아가게 하는 길을 초래할 수 있을 겁니다. +이를 컴퓨팅에서…

+ + \ No newline at end of file diff --git "a/public/series/\355\224\204\353\241\234\354\204\270\354\212\244-\353\217\231\352\270\260\355\231\224/index.html" "b/public/series/\355\224\204\353\241\234\354\204\270\354\212\244-\353\217\231\352\270\260\355\231\224/index.html" new file mode 100644 index 0000000..4fe003c --- /dev/null +++ "b/public/series/\355\224\204\353\241\234\354\204\270\354\212\244-\353\217\231\352\270\260\355\231\224/index.html" @@ -0,0 +1,129 @@ +SERIES: 프로세스 동기화

SERIES

프로세스 동기화

4 Posts·Last updated on September 22, 2025

병행성과 병렬성의 차이 및 프로세스 동기화의 필요성

September 19, 2025

병행성(Concurrency) 병행성은 다른 말로 동시성이라고 부르는 용어입니다. +이전까지 보았던 싱글 코어에서 프로세스를 처리하기 위해 많은 프로세스들을 컨텍스트 스위칭을 통해 효율적으로 프로세스를 처리했던것 기억할것 입니다. +이경우 프로세스를 동시에 처리한다고 표현하지만 사실 이는 빠른 속도로 프로세스를 스위칭해서 실행시키는 것이지 실제로 동시에 실…


임계구역과 경쟁상태

September 20, 2025

공유자원 동시에 실행되는 프로세스에서 공통으로 사용하는 자원을 우리는 공유자원이라고 부릅니다. 임계구역(Critical Section) 공유 자원을 사용하는 여러개의 프로세스 중, 해당 공유 자원에 접근하는 코드 영역을 임계 구역이라고 부릅니다. 두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기해야 합니다. 임계 구역에 먼저 진입한…


상호배제와 동기화 기법

September 21, 2025

상호배제(Mutual Exclusion) 상호배제(Mutual Exclusion)는 여러 프로세스나 스레드가 동시에 같은 공유 자원에 접근하는 것을 막는 메커니즘입니다. 일상생활에서 비유하면, 화장실 사용과 같습니다. +한 번에 한 사람만 화장실을 사용할 수 있고, 다른 사람들은 기다려야 합니다. +컴퓨터 시스템에서도 마찬가지로 특정 자원은 한 번에 하나의 …


교착상태와 해결 방법

September 22, 2025

교착상태란?(Dead Lock) 교착상태란 두개 이상의 프로세스가 각자 가지고 있는 자원을 무작정 기다리는것을 말합니다. 교착상태를 설명하는 대표적인 예시로 식사하는 철학자 문제라는게 있습니다. 식사하는 철학자 식사하는 철학자 문제는 그림처럼 동그란 원탁에 다섯명의 철학자가 앉아 있습니다. 이 철학자들은 각각 식사를 배정받고, 식사에 필요한 포크도 있습…

+ + \ No newline at end of file diff --git "a/public/series/\355\224\204\353\241\234\354\204\270\354\212\244\354\231\200-\354\223\260\353\240\210\353\223\234\354\227\220-\353\214\200\355\225\264\354\204\234-\354\225\214\354\225\204\353\263\264\352\270\260/index.html" "b/public/series/\355\224\204\353\241\234\354\204\270\354\212\244\354\231\200-\354\223\260\353\240\210\353\223\234\354\227\220-\353\214\200\355\225\264\354\204\234-\354\225\214\354\225\204\353\263\264\352\270\260/index.html" index 5a8819a..d32e84c 100644 --- "a/public/series/\355\224\204\353\241\234\354\204\270\354\212\244\354\231\200-\354\223\260\353\240\210\353\223\234\354\227\220-\353\214\200\355\225\264\354\204\234-\354\225\214\354\225\204\353\263\264\352\270\260/index.html" +++ "b/public/series/\355\224\204\353\241\234\354\204\270\354\212\244\354\231\200-\354\223\260\353\240\210\353\223\234\354\227\220-\353\214\200\355\225\264\354\204\234-\354\225\214\354\225\204\353\263\264\352\270\260/index.html" @@ -1,4 +1,4 @@ -SERIES: 프로세스와 쓰레드에 대해서 알아보기CATCH NPE