📌 파일 디스크립터 (file descriptor)
프로세스가 파일이나 입출력 장치에 접근할 떄 사용하는 일종의 "핸들"
(여기서 핸들은 실제 자원과 프로세스 간의 연결을 추상화한 정수 값)
1. 파일 열기
open()
open() 함수로 시스템 호출을 사용한다.
호출이 성공하면 운영체제는 파일 테이블에 새 항목을 추가하고,
참조할 수 있는 파일 디스크립터(정수)를 반환한다.
예를들어 파일을 열때 파일 디스크립터로 3이라는 숫자를 반환 받으면,
프로세스는 3을 사용해서 그 파일에 접근
(보통 0,1,2는 기본적으로 표준 입력, 출력, 오류에 할당되어 3부터 시작됨)
2. 파일 읽기와 쓰기
파일 디스크립터를 이용해
아래와 같은 시스템 호출을 통해 데이터를 읽거나 쓸 수 있다.
read(fd, buffer, size)
write(fd, buffer, size)
fd는 파일 디스크립터로 어떤 파일에 접근해야 하는지 알려주고,
파일의 현재 읽기 쓰기 위치를 내부적으로 유지한다.
(buffer는 데이터를 저장할 메모리 공간, size는 읽거나 쓸 데이터의 크기)
3. 파일 닫기
사용이 끝난 파일 디스크립터는 close() 시스템 호출을 통해 닫는다.
close()
close() 호출을 통해 파일 디스크립터를 파일 테이블에서 제거하고,
그와 열결된 자원을 해제한다.
운영체제 내부 구조
1. 프로세스 파일 디스크립터 테이블
- 각 프로세스는 자신만의 파일 디스크립터 테이블을 가진다.
- 테이블의 각 항목은 정수 값인 파일 디스크립터로 식별된다.
- 파일이 열릴 때마다 새로운 파일 디스크립터가 테이블에 추가된다.
- 커널 영역에 존재함 (커널 영역은 모든 프로세스들이 공유함)
2. 파일 테이블
- 시스템 전역에서 열린 모든 파일의 정보를 관리한다.
- 파일 참조 횟수, 파일 포인터, 파일의 상태 등을 포함
3. V-노드 테이블
- 파일 시스템의 특정 파일에 대한 메타데이터 관리하는 구조체
- 파일 테이블의 각 항목은 V-노드 테이블을 참조
- 해당 테이블에 파일의 크기, 소유자, 권한,위치 등의 정보 가짐
파일 디스크립터의 예시
int fd = open("example.txt", O_RDONLY); // 읽기 전용 모드
return 값으로 정수값 (예: 3)을 할당
이제 프로세스는 변환된 fd 값 3을 통해 파일에 접근한다.
char buffer[100];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
해당 파일 디스크립터에서 buffer에 저장 후 buffer의 크기만큼 데이터를 읽는다.
close(fd);
이후 파일 테이블에서 해당 항목을 해제한다.
📌 네트워크 계층 ( OSI7 Layer, TCP/IP Layer)
OSI 7 계층
1. 물리 계층
- 전기적, 물리적 신호를 전송하는 계층
- 비트 단위(데이터를 0과 1의 전기 신호로 변환)의 데이터 전송
- 케이블, 전압, 신호 유형 등 물리적 매체 정의
- 주로 허브,리피터, 케이블 등 물리적 매체를 정의
- 허브,리피터,케이블 같은 장치를 사용
2. 데이터 링크 계층
- 물리 계층에서 발생할 수 있는 오류를 감지하고 수정하여 신뢰성 보장
- MAC(Media Access Control) 주소 기반
- 데이터 프레임 전송하고 오류 검출 및 흐름 제어
- 스위치, 브리지 같은 장치 사용
- Ethernet, PPP(Point-to-Point Protocol)
3. 네트워크 계층
- 데이터를 최적의 경로를 통해 목적지에 전달
- IP 주소를 기반으로 논리적 주소,라우팅, 경로 선택
- IP(IPv4, IPv6), ICMP, ARP 프로토콜
- 라우터 장치 사용
- 출발지에서 목적지까지 패킷을 전송
4. 전송 계층
- 통신의 신뢰성과 데이터 전달을 보장
- 패킷을 세그먼트로 나누어 전송하고, 세그먼트 간의 오류 제어와 흐름 제어
- 연결 지향 또는 비연결 지향 통신 수행
- TCP, UDP 프로토콜 사용
5. 세션 계층
- 통신 세션 관리
- 데이터의 시작과 종료를 담당
- 세션 계층은 세션을 관리하여 데이터를 주고 받는 구조
6. 표현 계층
- 데이터 형식 변환
- 인코딩 및 암호화 등의 기능 수행
- 상위 계층에서 받은 데이터를 네트워크 표준 형식으로 변환
- ex ) JEPG, GIF, 데이터 암호화
7. 응용 계층
- 사용자와 네트워크 간의 인터페이스를 제공
- 사용자 응용 프로그램과 네트워크 서비스 연결
- 이메일, 파일 전송, 원격 로그인, 웹 브라우징 등 다양한 서비스 제공
- HTTP, FTP, SMTP, DNS 등
import json
# 1. 물리 계층 (Physical Layer)
def physical_layer_receive(bit_stream):
"""물리 계층 - 비트 스트림을 문자열로 변환"""
byte_stream = ''.join(chr(int(bit_stream[i:i+8], 2)) for i in range(0, len(bit_stream), 8))
print("Physical Layer - Received byte stream:", byte_stream)
return json.loads(byte_stream) # 다음 계층에 JSON 객체를 전달
# 2. 데이터 링크 계층 (Data Link Layer)
def data_link_layer_receive(frame):
"""데이터 링크 계층 - 프레임을 해제하여 MAC 주소와 데이터 분리"""
print("Data Link Layer - Frame received:", frame)
if frame["dest_mac"] == "AA:BB:CC:DD:EE:FF": # 수신 MAC 주소 확인
return frame["frame_data"]
else:
print("MAC Address does not match.")
return None
# 3. 네트워크 계층 (Network Layer)
def network_layer_receive(packet):
"""네트워크 계층 - 패킷을 해제하여 IP 주소와 데이터 분리"""
print("Network Layer - Packet received:", packet)
if packet["dest_ip"] == "192.168.1.1": # 수신 IP 주소 확인
return packet["packet"]
else:
print("IP Address does not match.")
return None
# 4. 전송 계층 (Transport Layer)
def transport_layer_receive(segment):
"""전송 계층 - 세그먼트를 해제하여 포트 번호와 데이터 분리"""
print("Transport Layer - Segment received:", segment)
if segment["dest_port"] == 80: # 수신 포트 번호 확인
return segment["segment"]
else:
print("Port number does not match.")
return None
# 5. 세션 계층 (Session Layer)
def session_layer_receive(session_data):
"""세션 계층 - 세션 ID 확인 및 데이터 반환"""
print("Session Layer - Session data received:", session_data)
if session_data["session_id"] == "12345": # 세션 ID 확인
return session_data["data"]
else:
print("Session ID does not match.")
return None
# 6. 표현 계층 (Presentation Layer)
def presentation_layer_decode(encoded_data):
"""표현 계층 - 데이터를 디코딩하여 응용 계층 형식으로 변환"""
print("Presentation Layer - Decoding data")
return json.loads(encoded_data)
# 7. 응용 계층 (Application Layer)
def application_layer_display(data):
"""응용 계층 - 최종 데이터를 출력"""
print("Application Layer - Final message:", data["message"])
# 물리 계층부터 시작하는 데이터 예시 (비트 스트림)
bit_stream = ''.join(format(ord(x), '08b') for x in json.dumps({
"dest_mac": "AA:BB:CC:DD:EE:FF",
"src_mac": "FF:EE:DD:CC:BB:AA",
"frame_data": {
"dest_ip": "192.168.1.1",
"src_ip": "192.168.1.2",
"packet": {
"src_port": 1234,
"dest_port": 80,
"segment": {
"session_id": "12345",
"data": json.dumps({"message": "Hello from OSI Layers!"})
}
}
}
}))
# OSI 7계층 순차적 처리
frame = physical_layer_receive(bit_stream)
if frame:
packet = data_link_layer_receive(frame)
if packet:
segment = network_layer_receive(packet)
if segment:
session_data = transport_layer_receive(segment)
if session_data:
encoded_data = session_layer_receive(session_data)
if encoded_data:
app_data = presentation_layer_decode(encoded_data)
application_layer_display(app_data)
변환하려는 데이터
{
"dest_mac": "AA:BB:CC:DD:EE:FF",
"src_mac": "FF:EE:DD:CC:BB:AA",
"frame_data": {
"dest_ip": "192.168.1.1",
"src_ip": "192.168.1.2",
"packet": {
"src_port": 1234,
"dest_port": 80,
"segment": {
"session_id": "12345",
"data": json.dumps({"message": "Hello !!"})
}
바이트 스트림으로 변환된 값
0111101100100010011001000110010101110011011101000101111101101101011000010110001100100010001110100010000000100010010000010100000100111010010000100100001000111010010000110100001100111010010001000100010000111010010001010100010100111010010001100100011000100010001011000010000000100010011100110111001001100011010111110110110101100001011000110010001000111010001000000010001001000110010001100011101001000101010001010011101001000100010001000011101001000011010000110011101001000010010000100011101001000001010000010010001000101100001000000010001001100110011100100110000101101101011001010101111101100100011000010111010001100001001000100011101000100000011110110010001001100100011001010111001101110100010111110110100101110000001000100011101000100000001000100011000100111001001100100010111000110001001101100011100000101110001100010010111000110001001000100010110000100000001000100111001101110010011000110101111101101001011100000010001000111010001000000010001000110001001110010011001000101110001100010011011000111000001011100011000100101110001100100010001000101100001000000010001001110000011000010110001101101011011001010111010000100010001110100010000001111011001000100111001101110010011000110101111101110000011011110111001001110100001000100011101000100000001100010011001000110011001101000010110000100000001000100110010001100101011100110111010001011111011100000110111101110010011101000010001000111010001000000011100000110000001011000010000000100010011100110110010101100111011011010110010101101110011101000010001000111010001000000111101100100010011100110110010101110011011100110110100101101111011011100101111101101001011001000010001000111010001000000010001000110001001100100011001100110100001101010010001000101100001000000010001001100100011000010111010001100001001000100011101000100000001000100111101101011100001000100110110101100101011100110111001101100001011001110110010101011100001000100011101000100000010111000010001001001000011001010110110001101100011011110010000000100001001000010101110000100010011111010010001001111101011111010111110101111101
물리 계층
비트 스트림을 문자열로 변환
Physical Layer - Received byte stream: {"dest_mac": "AA:BB:CC:DD:EE:FF", "src_mac": "FF:EE:DD:CC:BB:AA", "frame_data": {"dest_ip": "192.168.1.1", "src_ip": "192.168.1.2", "packet": {"src_port": 1234, "dest_port": 80, "segment": {"session_id": "12345", "data": "{\"message\": \"Hello !!\"}"}}}}
데이터 링크 계층
프레임을 해제하여 MAC 주소와 데이터 분리
Data Link Layer - Frame received: {'dest_mac': 'AA:BB:CC:DD:EE:FF', 'src_mac': 'FF:EE:DD:CC:BB:AA', 'frame_data': {'dest_ip': '192.168.1.1', 'src_ip': '192.168.1.2', 'packet': {'src_port': 1234, 'dest_port': 80, 'segment': {'session_id': '12345', 'data': '{"message": "Hello !!"}'}}}}
네트워크 계층
패킷을 해제하여 IP 주소와 데이터 분리
Network Layer - Packet received: {'dest_ip': '192.168.1.1', 'src_ip': '192.168.1.2', 'packet': {'src_port': 1234, 'dest_port': 80, 'segment': {'session_id': '12345', 'data': '{"message": "Hello !!"}'}}}
전송 계층
세그먼트를 해제하여 포트 번호와 데이터 분리
Transport Layer - Segment received: {'src_port': 1234, 'dest_port': 80, 'segment': {'session_id': '12345', 'data': '{"message": "Hello !!"}'}}
세션 계층
세션 ID 확인 및 데이터 반환
Session Layer - Session data received: {'session_id': '12345', 'data': '{"message": "Hello !!"}'}
표현 계층
데이터를 디코딩하여 응용 계층 형식으로 변환
Presentation Layer - Decoding data
응용 계층
최종 데이터를 출력
Application Layer - Final message: Hello !!
📌 클라이언트 - 서버 모델
- 네트워크에서 데이터를 주고받는 분산 네트워크 구조
- 주로 웹과 같은 인터넷 서비스에서 널리 사용
- 클라이언트와 서버라는 두 주체가 상호작용하여 데이터 처리하는 구조
- 클라이언트는 서비스를 필요로 할 때 한개의 요청을 서버에 보냄
- 서버는 요청을 해석하고, 자원들을 적절한 방법으로 조작
📌 소켓
- 네트워크 상에서 통신을 위한 양쪽 끝단 (엔드포인트)
- 두 컴퓨터 간에 데이터를 송수신 하기 위해 사용되는 소프트웨어 인터페이스
- 웹 브라우저와 웹 서버는 각각 소켓을 통해 연결
- IP 주소와 포트 번호를 사용하여 네트워크 상의 특정 프로그램 식별
- TCP , UDP 소켓 등의 소켓 유형 존재
네트워크 함수 같은 경우 따로 블로그로 포스팅을 해두었다.
📌 Datagram Socket, Stream Socket
- 데이터 전송 방식과 연결 형태에 따라 나뉜 유형
- Datagram Socket
- UDP (User Datagram Protocol) 기반으로 동작
- 비연결형 통신 지원 (클라이언트와 서버 간의 연결 설정 생략)
- 데이터그램이라는 독립적인 패킷 단위로 데이터 전송
- connect() 와 같은 함수 필요 없음
- 전송 속도가 빨라서 실시간 상황에 효율적
- 데이터가 손실될 수 있으며, 데이터 전송 중 순서가 뒤바뀌거나 중복될 수 있음
- Stream Socket
- TCP(Transmission Control Protocol) 기반으로 동작하는 소켓
- 연결 지향형 통신 지원 ( 클라이언트와 서버 간의 연결 설정)
- 연속적인 데이터 스트림 형태로 데이터 전송
- connect(), listen(), accept() 등의 절차 필요
- 3-way Handshake 과정으로 신뢰성 있는 연결 설정
- TCP 프로토콜로 데이터 순서 보장, 손실 방지, 중복 방지
- 데이터를 바이트 단위로 전송 (데이터 경계 구분 X)
- close() 호출 전까지 데이터 송수신 유지 가능
📌 CGI / WebServer / MIME Type
- Common Gateway Interface
- 웹 서버와 외부 애플리케이션 간의 인터페이스를 정의하는 표준
- CGI는 특정 언어에 의존하지 않고 다양한 언어로 작성 가능
- 웹 서버는 정적파일뿐 아니라 동적인 콘텐츠도 제공 가능
- 클라이언트 요청마다 웹 서버는 CGI 프로그램을 실행하는 별도의 프로세스 생성
- 요청당 별도의 프로세스를 생성하는 구조적 한계
- 성능과 확장성 문제로 FastCGI, SCGI, WSGI, ASP.NET, Servlets, JSP 등 대체 기술 개념
- CGI 동작 원리
1. 클라이언트가 웹 서버에 HTTP 요청을 보내고, 요청은 웹 페이지 내에서 CGI 프로그램을 실행하는 링크나 폼을 통해 발생
2. 웹 서버는 클라이언트 요청을 받고, 요청된 URL이 CGI 스크립트나 프로그램을 가리키는 경우 해당 프로그램 실행
3. CGI 프로그램은 웹 서버로부터 전달된 입력 데이터를 처리하여 동적으로 콘텐츠 생성
4. CGI 프로그램이 생성한 결과를 웹 서버가 받아서 HTTP 응답으로 웹 브라우저에 전달
5. 클라이언트는 이 결과를 웹 페이지에 렌더링
- WebServer
- 클라이언트에게 웹 콘텐츠를 제공
- 웹 서버는 정적 콘텐츠 뿐만 아니라 동적 콘텐츠도 같이 제공 가능
- 정적 콘텐츠 (HTML, CSS, JS, 이미지 파일 등) 같이 미리 준비된 일 요성시 즉시 제공
- 동적 콘텐츠 (CGI, PHP, JSPm, ASP.NET 등 의 기술) 로 실시간으로 생성되는 콘텐츠 제공
- SSL / TSL을 이용한 HTTPS 통신 등으로 보안성 강화
- 많은 요청이 몰릴 때, 부하를 분산시키는 로드 밸런서나 캐싱을 이용
- MIME Type
- Multipurpose Internet Mail Extension Type
- 파일 형식이나 인터넷에서 전송되는 데이터 유형 식별을 위한 표준 포맷
- 콘텐츠 종류를 명확히 지정하여 브라우저가 적절하게 처리
- 웹 브라우저가 서버로부터 파일 수신할 때, MIME 타입을 통해 구분
MIME Type 예시
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
- 위 응답 헤더는 서버가 클라이언트에 HTML 형식의 텍스트 데이터 전송을 의미
📌 HTTP (요청/응답, 헤더, 메소드, 상태 코드, HEAD 메소드)
- Hypertext Transfer Protocol
- 웹에서 클라이언트와 서버 간의 데이터를 주고받기 위해 사용되는 프로토콜
- 텍스트 기반 프로토콜로 Request와 Response의 흐름으로 콘텐츠 주고 받음
- HTTP 요청
- 요청 라인
GET /index.html HTTP/1.1
- 헤더
User-Agent: Mozilla/5.0
Accept: text/html
- 빈줄
헤더와 본문의 구분을 위한 빈 줄 삽입
- 본문
POST, PUT 등의 매서드에서 주로 사용
서버에 전달할 데이터를 포함
- HTTP 응답
- 요청 라인
요청 처리한 후 클라이언트에게 보내는 응답 메시지
응답 첫 줄로 HTTP 버전, 상태 코드, 상태 메시지가 포함
HTTP/1.1 200 OK
- 헤더
Content-Type: text/html
Content-Length: 234
- 빈줄
헤더와 본문 사이의 구분자 역할
- 본문
서버에서 클라이언트에게 전달할 데이터 포함
HTML, 이미지, JSON 등 다양한 콘텐츠 포함
- HTTP 매서드
- GET : 서버로부터 리소스를 요청하여 가져옴
- POST : 서버에 데이터를 전송하는 메서드
- PUT : 서버에 리소스를 업데이트
- DELETE : 서버에 지정된 리소스 삭제
- HEAD : GET과 유사하지만, 본문을 제외한 헤더 정보만 반환
- OPTIONS : 서버가 지원하는 HTTP 메서드 옵션 요청
- PATCH : 리소스의 일부 업데이트에 사용
- HTTP 상태 코드
- 서버는 클라이언트 요청을 처리한 결과를 상태 코드로 반환
- 1xx (정보): 요청을 수신하여 처리 중임을 의미
- 100 Continue: 클라이언트가 요청을 계속할 수 있음을 의미.
- 2xx (성공): 요청이 성공적으로 처리되었음을 의미
- 200 OK: 요청이 성공적으로 수행되었음을 의미.
- 201 Created: 요청이 성공적으로 처리되었고, 리소스가 새로 생성되었음을 의미.
- 3xx (리다이렉션): 요청된 리소스가 이동되었음을 의미하며, 클라이언트가 새로운 URL로 요청
- 301 Moved Permanently: 리소스가 영구적으로 다른 URL로 이동되었음을 의미.
- 302 Found: 리소스가 임시로 다른 URL로 이동되었음을 의미.
- 4xx (클라이언트 오류): 클라이언트의 요청에 오류
- 400 Bad Request: 잘못된 요청 문법으로 서버가 요청을 처리할 수 없음을 의미.
- 401 Unauthorized: 인증이 필요함을 의미.
- 404 Not Found: 요청한 리소스를 찾을 수 없음을 의미.
- 5xx (서버 오류): 서버가 요청을 처리하지 못했음을 의미
- 500 Internal Server Error: 서버 내부 오류로 요청을 처리할 수 없음을 의미.
- 503 Service Unavailable: 서버가 일시적으로 요청을 처리할 수 없음을 의미.
- HTTP 매서드
- GET 매서드와 유사한 방식으로 요청
- 서버가 응답 본문을 반환하지 않고, 오직 헤더만 반환
- 리소스 존재 여부 확인 ( 존재 시 200 OK 상태 코드 반환)
- 콘텐츠 정보 확인 (Content-Type 등의 정보로 콘텐츠 유형 사전 파악)
- 캐시 확인 (클라이언트 측 캐시가 최신 상태인지 확인)
HEAD 매서드 예시
HEAD /index.html HTTP/1.1
Host: www.example.com
서버 응답 예시
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
본문 없이 헤더만 반환된다.
📌 Proxy
- 클라이언트와 서버 사이에 위치
- 요청과 응답을 중계하는 중간 서버
- 클라이언트는 서버에 직접 요청하지 않고 프록시 서버를 통해 요청
- 프록시는 CORS 문제를 해결하기 위한 방법 중 하나
- 익명성 제공
- 클라이언트의 IP 주소 감추고 개인정보 보호 기능 강화
- 보통 VPN(Virtual Private Network) 과 함께 프록시 사용
- 캐싱
- 요청된 웹 리소스를 캐시에 저장해 둠
- 동일한 요청 들어올 때 캐시에서 바로 데이터 반환
- 콘텐츠 필터링
- 특정 웹사이트에 대한 접근 제한
- 로드 밸런싱
- 여러 서버로 들어오는 요청을 효율적으로 분산하여 과부하 방지
- 보안 강화
- 외부에서 내부 네트워크로 직접 접근 못하도록 보호
- SSL / TLS를 사용해 보안 강화
- HTTP 요청을 프록시 서버가 대신 처리하여 클라이언트와 서버 간의 통신 보호
- 정방향 프록시
- 사용자가 접근하려는 서버에 클라이언트 요청을 대신 전달
- 클라이언트와 서버 사이에 클라이언트 측에 위치
- 회사나 학교에서 특정 사이트에 대한 접근을 차단하거나 IP 주소 숨기는데 사용-
- 리버스 프록시
- 원격 서버가 클라이언트에게 직접 응답하는 대신, 프록시 서버가 응답을 대신 전달
- 여러 서버로 들어오는 요청을 받아 특정 서버에 분배하는 로드 밸런서 역할
- 클라이언트와 서버 사이에서 서버 측에 위
- Nginx, Apachem HAProxy 등
- 투명 프록시
- 클라이언트가 별도의 프록시 설정 없음
- 네트워크 환경에 의해 프록시를 경유하도록 강제
- 클라이언트는 프록시 서버를 거친다는 사실을 알 수 없음
- 공유 프록시
- 누구나 사용할 수 있도록 제공
- 인터넷에 공개
- 익명성 또는 IP 차단 우회를 위해 사용
- 웹 프록시
- 웹사이트 형태로 제공
- 웹 브라우저를 통해 웹 페이지를 열음
- 학교나 회사에서 차단된 웹사이트에 접근할 때 사용
+ CORS
- Cross-Origin Resource Sharing
- 웹 브라우저에서 서로 다른 출처(Origin) 간의 리소스 요청을 제어하는 보안 메커니즘
- 서버와 클라이언트가 다른 도메인에 위치해 있는 경우
- 보통 브라우저는 보안상의 이유로 기본적으로 이를 차단
클라이언트가 http://example.com 에서 실행되는 애플리케이션이라면,
https://api.example.com로 API 요청 보낼 경우 CORS 정책에 의해 차단
- 프록시 서버를 사용하면 클라이언트가 요청 보낼 때, CORS 규제 우회 가능
- CORS의 문제는 아래와 같은 응답 헤더 세팅으로도 해결 가능하다.
Access-Control-Allow-Origin': <origin> | *
'CS' 카테고리의 다른 글
Pintos Project1 -키워드 정리 (코드로 이해하기) / 프로세스, 스레드, 멀티 스레딩 문제 (0) | 2024.11.02 |
---|---|
네트워크 소켓 및 함수 정리 (CS:APP) (1) | 2024.10.29 |
정렬 알고리즘 (삽입,선택,버블,셸,퀵,힙,병합 정렬) (0) | 2024.09.11 |
1장. 컴퓨터 시스템 (Computer Systems A Programmer's Perspective) (1) | 2024.09.08 |
인증과 인가 / 쿠키와 세션 / 토큰과 JWT 이란 ? (0) | 2024.09.06 |