From ae6088e0e76e05678e220a63841d964e70c5b287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A0=95=EC=9C=A4?= Date: Sun, 19 Dec 2021 10:44:34 +0900 Subject: [PATCH 1/4] =?UTF-8?q?create:=20[OS]=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EB=9E=A8=20vs=20=ED=94=84=EB=A1=9C=EC=84=B8=EC=8A=A4?= =?UTF-8?q?=20vs=20=EC=8A=A4=EB=A0=88=EB=93=9C=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...s \354\212\244\353\240\210\353\223\234.md" | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 "OS/\355\224\204\353\241\234\352\267\270\353\236\250 vs \355\224\204\353\241\234\354\204\270\354\212\244 vs \354\212\244\353\240\210\353\223\234.md" diff --git "a/OS/\355\224\204\353\241\234\352\267\270\353\236\250 vs \355\224\204\353\241\234\354\204\270\354\212\244 vs \354\212\244\353\240\210\353\223\234.md" "b/OS/\355\224\204\353\241\234\352\267\270\353\236\250 vs \355\224\204\353\241\234\354\204\270\354\212\244 vs \354\212\244\353\240\210\353\223\234.md" new file mode 100644 index 0000000..68a1160 --- /dev/null +++ "b/OS/\355\224\204\353\241\234\352\267\270\353\236\250 vs \355\224\204\353\241\234\354\204\270\354\212\244 vs \354\212\244\353\240\210\353\223\234.md" @@ -0,0 +1,147 @@ +# 프로그램, 프로세스, 스레드 + +## 프로그램(Programe)이란? + +- **특정 작업을 수행하기 위해** 작성된 일련의 지침을 포함하는 **실행 파일** + +- 컴퓨터의 주 메모리에 저장되지 않고, 디스크 또는 컴퓨터의 **보조 메모리에 저장**된다. + +- 프로그램은 주 메모리에서 읽고 커널에 의해 실행된다 + + ex) chrome.exe (웹 페이지 보기), notepad.exe (텍스트 파일 편집) + +- **특징** + - **수동적(정적) 개체(passive entity)**. 실행할 명령어 그룹 저장. + - 수동으로 **삭제할 때까지 메모리에 저장**된다. + - 프로그램은 **실행 없이 어떤 작업도 수행 불가능.** + +## 프로세스(Process)란? + +> program is in execution (실행 중인 프로그램) + +- 메모리에 올라와 **실행되고 있는 프로그램의 인스턴스(독립적인 개체)** + +- 프로그램이 실행되는 실행 단위 + +- 프로그램 실행 중에 생성되어 **주 메모리에 load**된다. + + ex) google 크롬 아이콘을 더블 클릭하면 크롬 프로그램을 실행하는 프로세스가 시작된다. + +- **특징** + + - **능동적(동적) 개체(active entity)**. 응용 프로그램의 목적을 수행함 + - **수명이 매우 제한적**. 작업이 완료되면 종료된다. + - 프로세스에는 파일 디스크립터(file descriptors), 네트워크 포트와 같은 **시스템 자원이 할당**된다. + - 여러 프로세스가 동일한 프로그램과 관련될 수 있다.
ex) 메모장 프로그램의 여러 인스턴스 실행 가능 (각 인스턴스 = 프로세스) + - 프로세스에 대한 정보는 **PCB(Process Control Block)**에 저장된다. + +### PCB(Process Control Block) + +> 특정 프로세스에 대한 중요한 정보를 저장하고 있는 운영체제의 자료구조 + +- 사용자가 프로세스를 생성할 때마다 운영체제는 해당 프로세스에 해당하는 PCB를 생성한다. + +- **[PCB]에 저장되는 정보** + +| 이름 | 정의 | +| -------------------------------------- | ------------------------------------------------------------ | +| 프로세스 식별자 (Process-Id, PID) | 프로세스 식별 번호 | +| 프로세스 상태 (Process state) | new, ready, running, waiting, terminated 등의 상태를 저장 | +| 프로세스 우선순위 (Process Priority) | 수명, 소비한 자원 등으로 우선순위 나눔
숫자 값이 작을수록 해당 프로세스의 우선 순위 증가 | +| 회계정보 (Accounting Information) | 사용된 CPU 양과 시간, 시간 제한, 계정 번호 등 제공 | +| 프로그램 카운터 (Program Counter, PC) | 프로세스가 다음에 실행할 명령어의 주소 저장 | +| CPU 레지스터 (CPU Registers) | 인터럽트 발생 or 프로세스 간 문맥 교환 발생 시 임시 정보 저장. | +| PCB 포인터 (PCB Pointers) | 프로세스 상태가 ready인 다음 PCB 주소 저장 | +| 열린 파일 목록 (List of Open Files) | 프로그램이 실행되는 동안 필요한 모든 파일 정보 저장 | +| I/O 상태 정보 (I/O status Information) | 프로세스에 할당된 입출력 장치 목록 저장 | + +## 프로세스 상태 (Process State) + +![프로세스_상태도](https://github.com/KJY97/Note/blob/main/img/OS/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4_%EC%83%81%ED%83%9C%EB%8F%84.png?raw=true) + +- **New** : 프로세스가 생성중인 상태 + +- **Running** : CPU를 잡고 명령어(instruction)를 수행중인 상태 +- **Ready** : CPU를 기다리는 상태 (다른 조건을 다 만족하고 CPU만 얻으면 되는 상태를 의미) +- **Blocked(wait, sleep)** : CPU를 주어도 당장 명령어(instruction)을 수행할 수 없는 상태 + - Process 자신이 요청한 event(예: I/O)가 즉시 만족되지 않아 이를 기다리는 상태 + - ex) 디스크에서 file을 읽어와야 하는 경우 +- **Terminated** : 수행(execution)이 끝난 상태 + +## 프로그램과 프로세스 차이점 + +| | 프로그램 | 프로세스 | +| --------- | ------------------------------------------------ | -------------------------------- | +| 정의 | 프로그래밍 목표를 달성하기 위해 정렬된 작업 그룹 | 프로그램이 실행 중 | +| 상주 위치 | 디스크 or 보조 메모리 | 주 메모리 | +| 개체 유형 | 정적, 수동적 개체(passive entity) | 동적, 능동적 개체(active entity) | +| 자원 관리 | 명령어 저장을 위한 메모리만 필요 | 리소스 요구사항이 매우 높음 | +| 수명 | 수명이 길다. (삭제 전까지 저장됨) | 수명이 짧고 매우 제한적 | + + + +## 스레드(Thread) + +> 프로세스 내의 실행 흐름 + +![스레드](https://i0.wp.com/javaconceptoftheday.com/wp-content/uploads/2014/11/ThreadsAndProcesses.png?w=1200) + +- 프로세스의 **실행 가능한 가장 작은 단위** + +- 프로세스는 동시에 실행되는 여러 스레드를 가질 수 있다. + + - 이러한 프로세스를 경량 프로세스(Lightweight Process) 라고도 부른다. + +- **분류** + + | User Threads | Kernal Threads | + | ----------------------- | --------------------- | + | 사용자에 의해 구현 | OS에 의해 구현 | + | 구현이 쉬움 | 구현 복잡 | + | 종속 스레드로 설계 | 독립 스레드로 설계 | + | 문맥 교환 시간이 짧음 | 문맥 교환 시간이 길다 | + | 하드웨어 지원 필요 없음 | 하드웨어 지원 필요 | + +### 멀티 스레딩 + +**하나의 프로세스를 다수의 실행 단위로 구분**하여 자원을 공유하고 자원의 생성과 관리의 중복성을 최소화하여 **수행 능력을 향상시키는 것** + +- 즉, 하나의 프로그램에 동시에 여러개의 일을 수행할수 있도록 해주는 것 +- 하나의 프로세스 내 **메모리와 자원을 공유**한다. +- 메모리의 **code, data, heap 영역은 공유**하고, **stack과 PC 레지스터는 따로 할당**받는다. + - **각 스레드는 독립적으로 수행**되어야 하기 때문. +- **장점** + - **응답시간 단축** : 여러 스레드로 분할되면 하나의 스레드가 실행을 완료될 때 즉시 출력 반환 가능 + - **빠른 통신** : 동일한 메모리 영역을 공유해서 여러 쓰레드 간 통신이 원활함 + - **빠른 문맥 교환** : 프로세스에 비해 캐시 메모리를 비울 필요가 없기 때문. + - **시스템 처리량 향상** : 각 스레드 기능을 하나의 작업으로 간주하면서 단위 시간당 완료되는 작업 수 증가함 +- **문제점** + - **동기화 문제** + - 공유하는 자원에 동시에 접근하는 경우, 프로세스와 달리 **데이터와 힙 영역**을 공유하기 때문에 어떤 쓰레드가 다른 쓰레드에서 사용중인 변수나 자료 구조에 접근하여 엉뚱한 값을 읽어오거나 수정할 수 있다. 따라서 동기화가 필요! + - 동기화를 통해 작업 처리 순서와 공유 자원에 대한 접근을 컨트롤할 수 있다. 그러나 불필요한 부분까지 동기화를 하면 과도한 lock으로 인해 병목 현상이 병목 현상이 발생해 성능 저하 가능성 높다. + - 구현이 어려움 + - 테스트, 디버깅하기 어려움 + - 하나의 스레드의 문제가 발생하면 전체 프로세스에 영향을 끼침 + +## 프로세스와 스레드 차이점 + +| | 프로세스 | 스레드 | +| -------------- | ------------------ | -------------------------------------- | +| 정의 | 프로그램이 실행 중 | 프로세스의 세그먼트 | +| 프로세스 타입 | 중량 프로세스 | 경량 프로세스 | +| 종료 시간 | 많은 시간 소요 | 적은 시간 소요 | +| 생성 시간 | 많은 시간 소요 | 적은 시간 소요 | +| 문맥 교환 시간 | 많은 시간 소요 | 적은 시간 소요 | +| 메모리 공유 | 비공유 | 공유. 단, stack과 PC 레지스터는 비공유 | + + + +## Reference + +- https://javaconceptoftheday.com/differences-between-program-vs-process-vs-threads/ +- https://www.guru99.com/program-vs-process-difference.html#3 +- https://binaryterms.com/process-control-block-pcb.html +- https://www.geeksforgeeks.org/thread-in-operating-system/?ref=lbp +- https://www.guru99.com/difference-between-process-and-thread.html +- https://goodgid.github.io/What-is-Multi-Thread/ + From 9f9cd023f3b10e0576a5a89a54e187e6440c732e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A0=95=EC=9C=A4?= Date: Sun, 26 Dec 2021 17:28:01 +0900 Subject: [PATCH 2/4] =?UTF-8?q?update:=20[OS]=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EB=9E=A8vs=ED=94=84=EB=A1=9C=EC=84=B8=EC=8A=A4vs?= =?UTF-8?q?=EC=8A=A4=EB=A0=88=EB=93=9C=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...44 vs \354\212\244\353\240\210\353\223\234.md" | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git "a/OS/\355\224\204\353\241\234\352\267\270\353\236\250 vs \355\224\204\353\241\234\354\204\270\354\212\244 vs \354\212\244\353\240\210\353\223\234.md" "b/OS/\355\224\204\353\241\234\352\267\270\353\236\250 vs \355\224\204\353\241\234\354\204\270\354\212\244 vs \354\212\244\353\240\210\353\223\234.md" index 68a1160..e627822 100644 --- "a/OS/\355\224\204\353\241\234\352\267\270\353\236\250 vs \355\224\204\353\241\234\354\204\270\354\212\244 vs \354\212\244\353\240\210\353\223\234.md" +++ "b/OS/\355\224\204\353\241\234\352\267\270\353\236\250 vs \355\224\204\353\241\234\354\204\270\354\212\244 vs \354\212\244\353\240\210\353\223\234.md" @@ -1,5 +1,10 @@ # 프로그램, 프로세스, 스레드 +> - 프로그램이란 특정 작업을 수행하기 위한 실행파일이다. 실행파일을 클릭했을 때 메모리 할당이 이루어지고, 이 메모리공간으로 코드가 올라간다. 이 순간부터 프로세스이다. +> - 프로세스는 OS로부터 자원을 할당받는 실행되고 있는 프로그램의 인스턴스이다. 각각 독립된 메모리 영역(Code, Data, Stack, Heap 구조) 등을 할당받는다. +> - 스레드는 프로세스의 가장 작은 실행단위로, 프로세스가 할당받은 자원을 이용한다. 프로세스 내에서 각각 stack과 PC 레지스터만 따로 할당받고 Code, Data, Heap 영역은 프로세스 내에 쓰레드끼리 공유하면서 실행된다. +> - 스레드를 사용하면 응답시간 단축, 빠른 통신과 비용적음, 빠른 문맥 교환, 시스템 처리량을 향상시킬 수 있지만, 스레드의 자원 공유는 동기화 문제에 신경을 써야하며 멀티스레드 프로그래밍은 구현과 디버깅이 어렵다는 문제점이 있다. + ## 프로그램(Programe)이란? - **특정 작업을 수행하기 위해** 작성된 일련의 지침을 포함하는 **실행 파일** @@ -11,7 +16,7 @@ ex) chrome.exe (웹 페이지 보기), notepad.exe (텍스트 파일 편집) - **특징** - - **수동적(정적) 개체(passive entity)**. 실행할 명령어 그룹 저장. + - **수동적(정적) 개체(passive entity)**. 실행할 명령어 그룹을 저장.
당장 실행파일을 열어보면 다양한 명령어가 적혀있는 것을 알 수 있다. 이러한 명령어를 그룹으로 모아저 저장하는 것이 프로그램! - 수동으로 **삭제할 때까지 메모리에 저장**된다. - 프로그램은 **실행 없이 어떤 작업도 수행 불가능.** @@ -31,7 +36,7 @@ - **능동적(동적) 개체(active entity)**. 응용 프로그램의 목적을 수행함 - **수명이 매우 제한적**. 작업이 완료되면 종료된다. - - 프로세스에는 파일 디스크립터(file descriptors), 네트워크 포트와 같은 **시스템 자원이 할당**된다. + - 프로세스에는 OS로부터 **실행에 필요한 자원을 할당**받는다.
ex) 파일 디스크립터(file descriptors), 네트워크 포트, cpu시간, 메모리 영역(Code, Data, Stack, Heap 구조) - 여러 프로세스가 동일한 프로그램과 관련될 수 있다.
ex) 메모장 프로그램의 여러 인스턴스 실행 가능 (각 인스턴스 = 프로세스) - 프로세스에 대한 정보는 **PCB(Process Control Block)**에 저장된다. @@ -72,7 +77,7 @@ | | 프로그램 | 프로세스 | | --------- | ------------------------------------------------ | -------------------------------- | -| 정의 | 프로그래밍 목표를 달성하기 위해 정렬된 작업 그룹 | 프로그램이 실행 중 | +| 정의 | 프로그래밍 목표를 달성하기 위해 정렬된 작업 그룹 | 실행 중인 프로그램 | | 상주 위치 | 디스크 or 보조 메모리 | 주 메모리 | | 개체 유형 | 정적, 수동적 개체(passive entity) | 동적, 능동적 개체(active entity) | | 자원 관리 | 명령어 저장을 위한 메모리만 필요 | 리소스 요구사항이 매우 높음 | @@ -122,6 +127,10 @@ - 구현이 어려움 - 테스트, 디버깅하기 어려움 - 하나의 스레드의 문제가 발생하면 전체 프로세스에 영향을 끼침 +- 사용 사례 + - 영상통신 : 영상을 받아 화면에 출력하는 작업과 영상을 생성하여 보여주는 작업이 동시에 발생 + - 웹 브라우저 : UI를 처리하는 작업과 표시할 데이터를 가져오는 작업이 동시에 발생 + - 게임 : 그래픽을 실행하는 작업과 UI를 그리는 서버통신을 담당하는 소켓 작업이 동시에 발생 ## 프로세스와 스레드 차이점 From 0ae14c0f8d7970a4d03225061c269b3fa279773a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A0=95=EC=9C=A4?= Date: Sun, 16 Jan 2022 19:36:38 +0900 Subject: [PATCH 3/4] =?UTF-8?q?create:[Java]=20=EB=8B=A4=EC=9D=B5=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EB=9D=BC(Dijkstra)=20=EC=95=8C=EA=B3=A0=EB=A6=AC?= =?UTF-8?q?=EC=A6=98=20(#39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\353\235\274_\354\260\250\354\235\264.jpg" | Bin 0 -> 40317 bytes ...14\352\263\240\353\246\254\354\246\230.md" | 51 ++++++++++ ...4\236\245\355\212\270\353\246\254(MST).md" | 88 ++++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 "Java/img/\355\224\204\353\246\274\352\263\274_\353\213\244\354\235\265\354\212\244\355\212\270\353\235\274_\354\260\250\354\235\264.jpg" create mode 100644 "Java/\353\213\244\354\235\265\354\212\244\355\212\270\353\235\274(Dijkstra) \354\225\214\352\263\240\353\246\254\354\246\230.md" create mode 100644 "Java/\354\265\234\354\206\214\353\271\204\354\232\251 \354\213\240\354\236\245\355\212\270\353\246\254(MST).md" diff --git "a/Java/img/\355\224\204\353\246\274\352\263\274_\353\213\244\354\235\265\354\212\244\355\212\270\353\235\274_\354\260\250\354\235\264.jpg" "b/Java/img/\355\224\204\353\246\274\352\263\274_\353\213\244\354\235\265\354\212\244\355\212\270\353\235\274_\354\260\250\354\235\264.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..5deeb2435f4575072c774fa27f8ef453ffcf5a6c GIT binary patch literal 40317 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 literal 0 HcmV?d00001 diff --git "a/Java/\353\213\244\354\235\265\354\212\244\355\212\270\353\235\274(Dijkstra) \354\225\214\352\263\240\353\246\254\354\246\230.md" "b/Java/\353\213\244\354\235\265\354\212\244\355\212\270\353\235\274(Dijkstra) \354\225\214\352\263\240\353\246\254\354\246\230.md" new file mode 100644 index 0000000..265bc3c --- /dev/null +++ "b/Java/\353\213\244\354\235\265\354\212\244\355\212\270\353\235\274(Dijkstra) \354\225\214\352\263\240\353\246\254\354\246\230.md" @@ -0,0 +1,51 @@ +# 다익스트라(Dijkstra) 알고리즘 + +## 요약 + +>다익스트라 알고리즘이란 하나의 정점에서 그래프 상에 존재하는 다른 모든 정점, 즉 **두 정점 사이의 최단거리**를 구하는 알고리즘이다. + +## 정의 + +- 다이나믹 프로그래밍을 활용한 대표적인 **최단 경로(Shortest Path) 탐색 알고리즘** + - 최단 경로란 **간선의 가중치가 있는 그래프**에서 두 정점 사이의 경로들 중에 **간선의 가중치 합이 최소**인 경로 +- 하나의 정점에서 **다른 모든 정점으로 가는 최단 경로**를 구하는 알고리즘 + - 즉, **두 정점 사이의 최단거리를 구하는 알고리즘** +- 음의 가중치를 허용하지 않는다. (오로지 **양의 가중치**) +- 현실 세계에 사용하기 매우 적합한 알고리즘 중 하나
+ ex) 인공위성 GPS 소프트웨어 + +- **그리디 기법을 사용**한 알고리즘으로 **MST의 프림 알고리즘과 유사**하다. + +- 의사코드 + + ``` + s: 시작 정점, A: 인접 행렬, D: 시작정점에서의 거리 + V: 정점 집합, U: 선택된 정점 집합 + + Dijkstra(s, A, D) + U = {s}; + FOR 모든 정점 v + D[v] = A[s][v] + WHILE U != V + D[w]가 최소인 정점 w ∈ V-U를 선택 + U = U ∪ {w} + FOR w에 인접한 모든 미방문 정점 v + D[v] = min(D[v], D[w] + A[w][v]) + ``` + + + +## 프림과 다익스트라 차이 + +![프림과_다익스트라_차이](img/프림과_다익스트라_차이.jpg) + +- **프림은 다익스트라와 달리 두 노드 사이가 최단거리가 아닐 수도 있다.** +- 프림이 다익스트라를, 다익스트라가 프림을 보장해주지 않는다. + +| 프림 알고리즘 | 다익스트라 알고리즘 | +| ------------------------------------------------------ | ------------------------------------------------------ | +| 최소 신장 트리 | 최단경로 알고리즘 | +| 전체 그래프 관점에서의 모든 정점들을 최소비용으로 연결 | 정점 간의 최단 거리 연결 | +| 정점 간의 최소 비용을 보장X | 정점 간 최소 비용을 보장 | +| 무향그래프에서만 사용 | 무향,유향 그래프에서 모두 사용(단, 양의 가중치인 경우) | + diff --git "a/Java/\354\265\234\354\206\214\353\271\204\354\232\251 \354\213\240\354\236\245\355\212\270\353\246\254(MST).md" "b/Java/\354\265\234\354\206\214\353\271\204\354\232\251 \354\213\240\354\236\245\355\212\270\353\246\254(MST).md" new file mode 100644 index 0000000..92e329b --- /dev/null +++ "b/Java/\354\265\234\354\206\214\353\271\204\354\232\251 \354\213\240\354\236\245\355\212\270\353\246\254(MST).md" @@ -0,0 +1,88 @@ +# 최소비용 신장트리(MST) + +## 요약 + +>신장 트리를 구성하는 간선들의 가중치의 합이 최소가 되는 트리를 최소 신장 트리라 하며 , 대표적으로 크루스칼 알고리즘, 프림 알고리즘이 있다. +> +>크루스칼 알고리즘은 **간선 선택 기반 알고리즘**으로, 가중치가 최소인 간선을 하나씩 선택해서 MST를 만드는 알고리즘이다. +> +>프림 알고리즘은 정점 선택 기반 알고리즘으로, 하나의 정점에서 연결된 간선들 중 가중치가 최소인 간선을 가진 정점을 하나씩 선택해서 MST를 만드는 알고리즘이다. + +## 정의 + +- 신장 트리 + + N개의 정점으로 이루어진 무향 그래프에서 N개의 정점과 N-1개의 간선으로 이루어진 트리 + +- **최소 신장 트리 (Minimum Spanning Tree)** + + 무향 가중치 그래프에서 신장 트리를 구성하는 **간선들의 가중치의 합이 최소**인 신장 트리
EX) 크루스칼 알고리즘, 프림 알고리즘 + +## 크루스칼 알고리즘 + +- 매 차례마다 **가중치가 최소인 간선을 선택**하면서 MST를 만드는 알고리즘 + 1. 간선을 **오름차순으로 정렬**하여 선택한다. + 2. 사이클이 생성되지 않게 매번 **사이클 생성 여부를 판단**하면서 가중치가 가장 낮은 간선을 선택한다. + - 사이클이란 A, B, C 정점이 있을 때 A-B, B-C, A-C로 그래프가 서로 연결되어 있는 상태를 의미 + 3. N-1개의 간선이 선택될 때까지 2번 과정 반복 +- **서로소(union-find) 알고리즘**과 **그리디 알고리즘 방법** 이용 + +- 의사코드 + + ```groovy + MST-KRUSKAL(G, w) + FOR vertex v int G.V //G.V: 그래프의 정점 집합 + Make_Set(v) //G.E: 그래프의 간섡 집합 + + G.E에 포함된 간선들을 가중치 w에 의해 오름차순 정렬 + + FOR 가중치가 가장 낮은 간선 (u, v) ∈ G.E 선택 (n-1개만큼) + IF Find_Set(u) != Find_Set(v) // 사이클 생성 여부 판단 + A = A ∪ {(u, v)} + Union(u, v) // 간선 연결 + ``` + +- 시간복잡도 + - 사실상 정렬 알고리즘과 Union-Find 알고리즘의 합이기 때문에 정렬 알고리즘의 시간 복잡도와 동일하다고 판단 가능 + - 가중치순으로 정렬하는데 E * logE 만큼의 시간이 소요되었으므로
**시간복잡도는 O(ElogE)** + +## 프림 알고리즘 + +- **하나의 정점**에서 연결된 간선들 중에 하나씩 선택하면서 MST를 만들어 가는 방식 + + 1. 임의의 정점 하나 선택 + 2. 선택한 정점과 인접하는 선택되지 않은 정점들 중 **가중치가 최소인 간선**으로 연결된 정점을 새로 선택 + 3. 모든 정점이 선택될 때까지 2번 과정 반복 + +- 이미 선택된 정점을 다시 선택하지 않기 때문에, 사이클 생성 여부 판단하지 않음 + +- 의사코드 + + ```groovy + MST_PRIM(G, r) //G: 그래프, r: 시작 정점 + result = 0, cnt = 0; //result: 신장트리 최소비용, cnt:처리한 정점수 + FOR u in G.V + miniEdge[u] = MAX_VALUE // miniEdge[]: 각 정점기준으로 다른 정점과의 간선 중 최소비용 + miniEdge[r] = 0 //시작 정점 r의 최소 비용 0처리 + WHILE true + u = Extract_MIN( ) //방문하지 않은(최소신장트리에 포함되지 않는 정점) 최소비용 정점 찾기 + visited[u] = true + result = result + miniEdge[u]; //비용 누적 + if(++cnt == N) break; + FOR v in G.Adj[u] //u의 인접 정점들 + IF visited[v] == false AND w(u, v) < miniEdge[v] //u에서 v로의 비용이 v의 최소비용보다 작다면 갱신 + miniEdge[v] = w(u, v) + return result + end MST_PRIM + ``` + +- 시간복잡도 + + - 우선순위 큐를 어떻게 구현하느냐에 따라 다르지만
일반적으로 **binary heap**으로 구현했을 경우 **O(ElogV)**
**unsorted arrary**로 구현헀을경우 **O(|V²|)** + +## 크루스칼 vs 프림 알고리즘 차이점 + +**크루스칼 알고리즘**은 정렬을 반드시 동반하기 때문에 **간선의 개수가 증가**하먼 정렬 소요 시간이 증가한다. + +> 즉, **크루스칼 알고리즘은 간선의 개수가 많지 않은 경우에 적합하며, 간선의 개수가 많을 때는 프림 알고리즘을 사용한다.** + From 87636bb7234446e9ee82acb8714e0dc55128f70d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EC=A0=95=EC=9C=A4?= Date: Sun, 23 Jan 2022 12:43:17 +0900 Subject: [PATCH 4/4] create: [Network] WebSocket (#42) --- Network/WebSocket.md | 73 ++++++++++++++++++ ...1\353\217\231\354\233\220\353\246\254.jpg" | Bin 0 -> 28924 bytes 2 files changed, 73 insertions(+) create mode 100644 Network/WebSocket.md create mode 100644 "Network/img/\354\233\271\354\206\214\354\274\223_\354\236\221\353\217\231\354\233\220\353\246\254.jpg" diff --git a/Network/WebSocket.md b/Network/WebSocket.md new file mode 100644 index 0000000..e533b09 --- /dev/null +++ b/Network/WebSocket.md @@ -0,0 +1,73 @@ +# WebSocket + +## 요약 + +> 웹소켓이란 서버와 클라이언트 간의 효율적인 양방향 통신이 가능한 방법으로, 기본적으로 stateful protocol 방식이다. +> +> 정보를 실시간 교류할 수 있디 때문에 채팅, 주식과 같은 즉각적인 변화를 감지해야 하는 서비스에 좋다. +> +> 그러나 개발이 복잡하고 서버와 클라이언트 간의 소켓 연결을 유지하는 것 자체가 비용이 크기 때문에 트래픽 양이 많은 서버의 경우 CPU에 부담을 줄 수 있다. 또한 HTML5 이전 브라우저에서는 지원되지 않아 작동하지 않는다. 마지막 문제를 해결하기 위해 나온 기술 중 하나가 node.js 기반으로 만들어진 socket.io라는 프레임워크이다. + +## Socket이란? + +- 프로그램이 네트워크 상에서 데이터를 송신과 수신을 하기 위한 연결부 (통신을 위한 일종의 통로) +- 일반적으로 TCP/IP (또는 UDP) 프로토콜을 이용하거나, WebSocket을 이용한다. + - TCP/IP: **연결형 소켓**. 신뢰할 수 있는 통신 + - UDP: **비연결형 소켓**. 몇가지 신뢰도는 포기하되 좀더 직접적인 통신을 한다 + +## WebSocket이란? + +- HTML5의 표준 기술 +- Transport protocol의 일종으로 서버와 클라이언트 간의 효율적인 **양방향 통신**을 실현하기 위한 구조 + +- 단순한 API로 구성 +- 웹소켓을 이용하면 **하나의 HTTP 접속**으로 **양방향 메시지**를 자유롭게 주고받을 수 있다. + +> 웹소켓 이전의 기존 HTTP 통신은 단방향 통신으로, 클라이언트의 요청이 없다면 서버로부터 응답을 받을 수 없는 구조였다.
이 문제를 극복하기 위해 등장한 것이 WebSocket!! + +## 특징 + +- **양방향 통신(Full-Duplex)** + - 데이터 송수신을 동시에 처리할 수 있는 통신 방법 + - 클라이언트와 서버가 서로에게 원할 때 데이터를 주고 받는다 +- **실시간 통신/성능(Real Time-Networking)** + - 웹 환경에서 연속된 데이터를 빠르게 노출한다. + - 여러 단말기에 데이터를 빠르게 교환한다. + - ex) 채팅, 주식, 비디오 데이터 + +## 작동 원리 + +- 웹소켓 연결은 HTTP 프로토콜을 통해 이루어짐 +- handshake 과정이 성공적으로 끝나면 HTTP를 웹소켓 프로토콜로 바꾸는 protocol switching 과정이 진행됨 +- 이후 웹소켓을 위한 새로운 소켓이 만들어지고 이 소켓을 이요해 통신한다. + +![웹소켓_작동원리](img/웹소켓_작동원리.jpg) + +> 웹소켓 주소는 ws나 wss로 시작하는데 ws는 일반 웹소켓, wss는 SSL이 적용된 웹소켓 + +## 문제점 + +- 프로그램 구현에 보다 많은 복잡성 초래 +- Stateful Protocol 특성 + - 웹소켓은 HTTP와 다르게 **항상 클라이언트와 서버 간의 연결을 유지**해야 함 + - 비정상적으로 연결이 끊어졌을 경우에 대한 대응 필요 +- 서버와 클라이언트 간의 Socket 연결을 유지하는 것 자체가 자원 소모 (특히 트래픽 양이 많은 서버의 경우) +- HTML5의 기술이기 때문에 이전 버전의 웹 브라우저에서 지원이 되지 않는다. + - 이 문제를 해결하기 위해 나온 기술 중 하나가 바로 `Socket.io` 라는 웹소켓 프레임워크 + - 웹페이지가 열리는 브라우저가 웹 소켓을 지원하면 웹 소켓 방식으로 동작하고, 지원하지 않는다면 일반 HTTP를 이용하여 실시간 통신을 흉내 내는 것 + +## 대표적인 사용 예 + +- 페이스북, 인스타와 같은 SNS APP +- 위치 기반 APP +- 화상 채팅 APP +- 증권 거래 정보 사이트 및 APP +- 구글 Doc 같이 여러 명이 동시 접속해서 수정할 수 있는 Tool +- LOL 같은 멀티플레이어 Game + +## 참고 + +- https://choseongho93.tistory.com/266 +- https://kyleyj.tistory.com/59 +- https://d2.naver.com/helloworld/1336 +- https://dailyscat.gitbook.io/twis/network/undefined \ No newline at end of file diff --git "a/Network/img/\354\233\271\354\206\214\354\274\223_\354\236\221\353\217\231\354\233\220\353\246\254.jpg" "b/Network/img/\354\233\271\354\206\214\354\274\223_\354\236\221\353\217\231\354\233\220\353\246\254.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..cb7f47803927a4b2418d9a5607ceb63c3babf54e GIT binary patch literal 28924 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 E01|