Skip to content

Commit

Permalink
Merge pull request #4 from SSUMC-6th/sof/#1
Browse files Browse the repository at this point in the history
[sof] Chapter 1. 서버란 무엇인가(소켓&멀티 프로세스)
  • Loading branch information
ryogaeng authored Apr 11, 2024
2 parents 9331e78 + 4321975 commit 801b4df
Showing 1 changed file with 135 additions and 0 deletions.
135 changes: 135 additions & 0 deletions docs/chapter1/Ch01Keyword.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
## TCP
#### : 데이터를 안정적으로, 순서대로, 에러 없이 전달하기 위해 사용되는 Transport layer(4계층)의 프로토콜
- **연결 지향적** : 통신 전에 미리 연결을 설정
- 연결 설정 : 3-way handshaking (SYN ⭢ SYN-ACK ⭢ ACK)
- 연결 해제( =세션 종료) : 4-way handshaking (FIN ⭢ ACK ⭢ FIN ⭢ ACK)
- **신뢰성 있는 데이터 전송** : 데이터 손실, 순서 뒤바뀜을 방지
- ACK(데이터에 대한 확인 응답)을 받지 못하면 데이터를 재전송함
- **흐름 제어과 혼잡 제어** : 네트워크의 혼잡 상태나 수신자의 처리 능력에 따라 데이터 전송 속도를 조절
- **순서 보장** : 패킷들의 전송 순서를 보장
- 수신된 데이터는 원래 보낸 순서대로 재조립 된다는 말!
#### 따라서 웹 브라우징, 이메일 전송, 파일 전송 등 신뢰성 있는 데이터 전송이 중요한 응용 프로그램에 사용됨
- - -
## UDP
#### : 빠르고 간단한 데이터 전송을 위해 사용되는 Transport layer(4계층)의 프로토콜
- **비연결 지향적** : 초기 연결 설정없이 데이터를 전송한다
- **신뢰서 없는 데이터 전송** : 패킷 손실에 대해 재전송하지 않는다.
- 송신자-수신자간에 패킷이 손실되거나 순서가 뒤바뀌는 경우, UDP는 이를 자체적으로 해결하지 않음
- **흐름제어 및 혼잡 제어 없음** : 네트워크의 혼잡 상태나 수신자의 처리 능력을 고려하지 않고 데이터르 ㄹ전송
- 이는 데이터 전송의 지연을 최소화하지만, 네트워크 과부하의 원인이 될 수 있음
#### 따라서 스트리밍 서비스, 온라인 게임, DNS 조회 등 처리속도와 효율성이 중요하고, 일부 데이터 손실이 허용되는 응용 프로그램에서 주로 사용됨
- - -
## 시스템 콜(System call)
#### : 프로그램이 컴퓨터의 중요원 자원에 직접 접근하는 것은 위험할 수 있다. 예를 들어 파일을 저장하거나 읽어야 할 때, 인터넷을 통해 데이터를 주고받아야 할 때 등이 이에 해당한다. 이 때 프로그램이 OS에게 "이 일 좀 대신 해줘"라고 요청하는 것을 시스템 콜이라고 생각하면 편하다.
#### 즉 프로그램은 시스템 콜을 통해 OS에게 필요한 작업을 요청하고, OS는 그 요청을 받아서 작업을 대신 수행해주는 것이다.
#### 시스템 콜의 동작 과정은 기본적으로 다음과 같은 단계로 이뤄진다.
1. **시스템 콜 요청** : 사용자 모드에서 실행되는 응용 프로그램이 작업을 수행하기 위해 시스템 콜을 호출하는 것으로 일반적으로 라이브러리 함수를 통해 이뤄진다.
- 예를 들어 파일을 열기 위해 프로그램이 open() 함수를 호출하는 경우가 여기에 해당한다.
2. **커널 모드로의 전환** : 시스템 콜이 호출되면 CPU는 사용자 모드에서 커널 모드로 전환한다.
- OS의 핵심 부인 커널은 커널 모드에서만 자원에 접근할 수 있고, 명령을 사용할 수 있다.
3. **시스템 콜 처리** : 커널은 시스템 콜 번호(고유 식별자)와 매개변수를 확인하여 요청된 서비스를 제공한다.
- 예를 들어 파일을 열 때, 커널은 해당 파일이 있는지, 읽기/쓰기 권한이 있는지 등을 확인하고, 파일을 열어 파일 핸들을 반환한다.
4. **커널 모드에서 사용자 모드로의 전환** : 작업이 완료되면 시스템은 다시 사용자 모드로 전환된다.
5. **결과 반환** : 커널은 시스템 콜의 결과를 응용 프로그램에 반환한다.
- 예를 들어 open() 시스템 콜의 결과로 파일 핸들이 반환된다. 실패한 경우 오류 코드가 반환된다.
- - -
## 인터럽트란?
#### : CPU가 프로그램을 실행하고 있을 때, I/O 하드웨어 등의 장치나 예외상황이 발생하여 처리가 필요할 경우에 마이크로프로세서에게 알려 처리할 수 있도록 하는 것
즉 실행 중인 프로그램의 흐름을 일시적으로 중단시키고, 특정 이벤트나 조건에 대한 처리를 위해 CPU의 주의를 요하는 메커니즘이라고 이해하면 좋다. <br> 기본 목적은 **컴퓨터 시스템의 반응성과 효율성 향상**이다.
## 인터럽트의 처리 과정
1. 인터럽트 발생 : H/W, S/W 인터럽트 발생
2. 프로그램 중단 : CPU는 현재 실행 중인 프로그램을 일시 중단 시킴
3. 인터럽트 처리 : CPU는 인터럽트에 대응하는 인터럽트 서비스 루틴(ISR)을 실행
4. 원래 프로그램으로 복귀 : 인터럽트 처리가 완료되면 CPU는 중단되었던 프로그램의 실행을 재개
## 하드웨어 인터럽트
#### : 외부 장치나 H/W로부터 발생하는 신호에 의해 발생한다.
- 예를 들어 키보드의 키 입력, 타이머 신호, 네트워크 카드에서의 데이터 수신 등이 해당된다.
## 소프트웨어 인터럽트
#### : 프로그램 코드 내부에서 발생하는 인터럽트로, 하드웨어 인터럽트와 다르게 프로그램 자체에 의해 발생한다.
- 이는 특정 조건이 충족되거나 특정 명령어가 실행될 때 발생하며, 주로 OS에 서비스를 요청하거나 예외적인 상황을 처리하기 위해 사용된다.
- ex1) 시스템 콜 : 응용 프로그램이 OS의 기능을 사용하려고 할 때 발생하는데, 이 때 가장 대표적인 예가 시스템 콜을 통한 요청이다. 즉 응용 프로그램이 파일을 읽거나 쓰기, 네트워크 통신, 프로세스 관리 등의 요청을 할 때 OS는 이를 소프트웨어 인터럽트로 인식하여 필요한 서비스를 제공하는 것이다.
- ex2) 예외 처리 : 예를 들어 나눗셈에서 0으로 나누는 오류나 메모리 접근 오류 등 프로그램 실행 중 exception이 발생 했을 때, 이러한 예외 상황을 처리하기 위해 소프트웨어 인터럽트가 발생할 수 있다.
- - -
## 리눅스의 파일 개념
#### : 리눅스에서는 모든 것을 파일로 취급한다. 여기에는 텍스트 및 binary data 뿐만 아니라 디렉토리, 하드웨어 장치, 네트워크 연결 등도 포함된다.
### * 리눅스 파일 시스템의 주요 특징
- 계층적 디렉토리 구조 : 파일과 디렉토리는 tree 형태의 구조를 가지고 있다.
- 파일 권한과 소유권 : 사용자, 그룹, 그리고 다른 사용자를 위한 읽기(read), 쓰기(write), 실행(execute) 권한을 가진다.
- 링크 : 하드 링크와 심볼릭 링크라는 두 가지 유형의 링크를 지원하여 같은 파일을 다른 이름이나 위치에서 접근할 수 있게 한다.
## 파일 디스크립터(File Descriptor)
#### : 리눅스에서 열린 파일을 가리키는 정수 값으로 파일 디스크립터를 통해 프로세스는 해당 파일에 접근하고, 파일의 데이터를 읽고 쓸 수 있다.
### * 파일 디스크립터의 주요 특징
- 파일 열기 : 프로세스가 파일을 열면 OS는 사용 가능한 가장 낮은 번호의 파일 디스크립터르 할당한다.
- 기본 파일 디스크립터 : 표준 입력(0), 표준 출력(1), 표준 오류(2)는 각각 프로세스가 시작될 때 기본적으로 열리는 파일 디스크립터이다.
- 사용 : 파일 디스크립터를 사용하여 파일 읽기 쓰기, 위치 변경, 속성 조회 및 수정과 같은 작업을 수행한다.
- 파일 닫기 : 파일 작업이 완료되면 파일 디스크립터는 닫혀야 하며, 이 후 해당 파일 디스크립터 번호는 다른 파일에 재사용될 수 있다.
- - -
## socket() 시스템 콜
#### : 소켓을 생성하는 시스템 콜로 네트워크 상에서 데이터를 주고받기 위한 형태를 잡아두는 것이라고 생각하면 좋다.
- socket(domain, type, protocol);
- domain : IPV4, IPV6중 무엇을 사용할지 결정
- type : stream(TCP), datagram(UDP) 선택
- protocol : 0, 6, 17 중 0을 넣으면 시스템이 프로토콜을 선택하며 6이면 TCP, 17이면 UDP
#### socket()의 리턴 값은 **파일 디스크립터**이다.
- - -
## bind() 시스템 콜
#### : 생성한 소켓에 IP 주소와 Port#을 부여하는 시스템 콜이다.
- bind(sockfd, sockaddr, socklen_t);
- sockfd : 바인딩을 할 소켓의 파일 디스크립터
- sockaddr : 소켓에 바인딩 할 IP 주소, Port#을 담은 구조체
- socklen_t : sockaddr 구조체의 메모리 크기
#### 어떤 소켓에 IP 주소와 Port#을 부여할 소켓을 OS에게 알려주기 위해 소켓의 파일 디스크립터를 파라미터에 포함한다.<br> 또한 클라이언트는 통신 시 Port#가 자동으로 부여되기 때문에 **bind() 시스템 콜은 서버에서만 사용**한다.
- - -
## listen() 시스템 콜
#### : 서버가 TCP 연결을 위한 대기 상태를 유지하여 클라이언트의 연결 요청을 듣고 있음을 시스템에 알리는 시스템 콜이라고 생각하면 좋다.
- listen(sockfd, backlog)
- sockfd : 소켓의 파일 디스크립터
- backlog : 연결 요청을 받아줄 크기 = 연결 대기열의 최대 길이 = **TCP의 backlog queue 크기**
### backlog란?
#### : 서버가 처리하지 않고, 대기열에 둘 수 있는 연결 요청의 최대 수. backlog 값이 작으면 동시에 많은 연결 요청이 들어올 때 일부 요청이 거부될 수 있다.
#### listen() 시스템 콜은 파라미터로 받은 backlog 크기만큼 backlog queue를 만드는 시스템 콜이라고 보면 편하다.
- - -
## accept() 시스템 콜
#### : 간단하게 말하자면 서버가 클라이언트로부터의 연결 요청을 수락하는데 사용되는 시스템 콜이다.
- accept(sockfd, sockaddr, socklen_t);
- sockfd : backlog queue의 요청을 받아들이기 위한 소켓의 파일 디스크립터
- sockaddr : 선입선출로 빼온 연결 요청에서 알아낸 클라이언트의 주소 정보
- socklen_t : sockaddr 구조체의 메모리 크기
- accept() 시스템 콜은 backlog queue에서 SYN을 보내와 대기 중인 요청을 선입선출 방식으로 하나씩 매칭하여 연결 해주는 것이다.
- SYN은 3-way handshaking의 3단계 중 1단계로 클라이언트가 listen 상태인 서버에게 연결 요청을 보내는 것이다. 이 후 accept() 시스템 콜이 이뤄지고, 서버가 클라이언트에게 SYN-ACK를 보내는 2단계가 이뤄진다. 이것이 Established 상태이고, 본격적인 데이터의 송수신이 이뤄지는 것이다.

### 하지만 곧바로 데이터 송수신이 이뤄지는 것은 아니다!! 왜??
#### ⭢ 서버의 성능 향상을 위해 멀티 프로세스, 멀티 스레드를 사용
#### : 클라이언트의 수많은 요청을 받는 상황에서 하나의 프로세스인 서버가 backlog queue의 가장 앞에 있는 클라이언트의 요청을 받고, 응답도 주고 하면 엄청난 병목(bottle neck)이 발생할 것임! <br> 따라서 서버는 **연결 요청을 받는 부분 / 응답을 주는 부분**을 따로 구분함
**_이를 위해 소켓을 만들어서<br>SYN 요청을 보낸 클라이언트 처리와<br> 응답을 동시에 진행!_**

accept() 시스템 콜을 통해 클라이언트의 연결 요청을 수락하고, 새로운 소켓을 생성하여 데이터를 주고받는 과정이 이뤄진다고 생각하면 좋다.
- - -
## 멀티 프로세스
#### : OS에서 하나의 응용 프로그램에 대해 동시에 여러 개의 프로세스를 실행할 수 있게 하는 것
- 멀티 프로세스 구조를 살펴보면 하나의 부모 프로세스가 여러 개의 자식 프로세스를 생성함으로서 다중 프로세스르 구성하는 구조이다.
- 한 프로세스는 실행되는 도중에 프로세스 생성 시스템 콜을 통해 새로운 프로세스들을 생성할 수 있는데, 다른 프로세스를 생성하는 프로세스를 부모 프로세스라 하고, 다른 프로세스에 의해 생성된 프로세스를 자식 프로세스라 한다.
### 멀티 프로세스의 장점
1. 프로그램 안정성
- 멀티 프로세스는 각 프로스세가 독립적인 메모리 공간을 가지므로 한 프로세스가 비정상적으로 종료되어도 다른 프로세스에 영향을 주지 않기 때문에 프로그램 전체의 안정성을 확보할 수 있다.
- 예를 들어 크롬 브라우저에서 여러 개의 탭을 띄우고, 다른 웹사이트를 방문하며 서비스를 이용하던 와중에 어느 한 탭의 웹사이트가 먹통이 됐다고 하자. 이 때 다른 탭은 문제없이 사용 가능하다. 이러한 이유는 자식 프로세스가 여러개 생성되어 메모리에 별도로 관리되기 때문이다.
2. 프로그램 병렬성
- 멀티 프로세스와 여러 개의 CPU 코어를 함께 사용하여, 다중 CPU 시스템에서 각 프로세스를 병렬적으로 실행 ⭢ 성능을 향상 시킬 수 있다.(이는 멀티 스레드의 장점이기도 하다)
3. 시스템 확장성
- 멀티 프로세스는 각 프로세스가 독립적이므로 새로운 기능이나 모듈을 추가하거나 수정할 때 다른 프로세스에 영향을 주지 않는다. 따라서 시스템 규모를 쉽게 확장할 수 있다.
- 분산 서버를 예시로 들 수 있다. 대규모 웹 서비스에서는 수많은 요청을 동시에 처리하기 위해 여러 대의 서버를 두고 로드 밸런서와 같은 장비를 사용하여 클라이언트 요청 트래픽을 분산 시킨다. 이 때 여러대의 서버는 컴퓨터 여려 개를 말하는 것일 수도 있고, 하나의 성능 좋은 컴퓨터에 여러 개의 서버 프로세스를 두는 것을 말하기도 한다.
- 이렇게 멀티 프로세스를 사용하여 여러 대의 서버에 요청을 분산시켜 처리함으로써, 시스템의 규모를 쉽게 확장할 수 있고, 부가적으로 서버의 장애나 다운타임을 최소화할 수 있다.
### 멀티 프로세스의 단점
1. 컨텍스트 스위칭 오버헤드(Context Switching Overhead)
- 멀티 태스킹 구성의 핵심 기술인 컨텍스트 스위칭 과정에서 성능 저하가 올 수 있다.
- 특히 프로세스를 컨텍스트 스위칭 하게 되면, CPU는 다음 프로세스의 정보를 불러오기 위해 메모리를 검색하고, CPU 캐시 메모리를 초기화하며, 프로세스 상태를 저장하고, 불러올 데이터를 준비해야 하기 때문에 빈번한 컨텍스트 스위칭이 일어나게 되고, 비용 오버헤드가 발생할 수 있다.
- 반면 스레드를 컨텍스트 스위칭 하게 되면, 프로세스 컨텍스트 스위칭 보다 가볍고, 빠르다.
2. 자원 공유 비효율성
- 멀티 프로세스는 각 프로세스가 독립적인 메모리 공간을 가지므로, 메모리 사용량이 증가하게 된다.
- 만약 각 프로세스 간에 자원 공유가 필요한 경우, 어렵고 복잡한 통신 기법인 IPC(Inter-Process Communication)를 프로세스 사이에 사용해야 한다.
- IPC란 OS상에서 실행 중인 프로세스 간에 정보를 주고 받는 메커니즘을 말한다. 이를 위해 소켓, 메세지 queue, 파이프 등 다양한 방법이 사용된다.
- IPC 자체로 오버헤드가 발생할 수 있는데, 예를 들어 소켓이나 파이프와 같은 IPC 기법은 데이터를 복사하거나 버퍼링하는 과정에서 성능 저하가 발생할 수 있기 때문이다.
- IPC를 사용하면 소스 코드의 복잡도가 증가한다는 어려움이 있다.
- - -
## 병렬 처리
#### : 멀티 프로세스의 장점 중 프로그램 병렬성의 내용과 같이 프로세스를 병렬적으로 실행함으로써 성능을 향상 시킬 수 있다는 장점이 존재한다.

0 comments on commit 801b4df

Please sign in to comment.