프로세스의 메모리 구조
운영체제는 프로세스에 적당한 메모리를 할당. 구성 요소: 스택, 힙, 데이터영역, 코드 영역
1. 스택(Stack)
- 지역변수, 매개변수, 함수
- 컴파일 시 크기가 결정되지만, 함수 호출 등으로 런타임에 크기가 동적으로 변경 가능
- 메모리의 상위 주소에 할당
2. 힙(Heap)
- 동적 메모리 할당에 사용
- 런타임 시 크기가 결정
- 메모리의 하위 주소에 할당
3. 데이터영역(Data segment, BSS segment)
- 정적 변수 할당
- Data segment: 0이 아닌 값으로 초기화된 전역 변수 및 정적 변수 저장
- BSS segment: 0으로 초기화 또는 초기화되지 않은 전역/정적 변수 저장
4. 코드 영역(code segment)
정적 할당
- 컴파일 단계에서 메모리 할당이 이루어지며, Data segment, BSS segment, code/text segment로 구분
동적 할당
- 런타임 단계에서 이루어지며, 스택과 힙으로 나뉨
- stack: 함수 호출 시 정보 저장으로 늘어나거나 줄어들음
- heap: 동적으로 할당되는 변수들이 저장되며, 동적 자료구조의 경우 이 영역을 사용 (vector)
PCB와 컨텍스트 스위칭
PCB
Process Controll Block
- 정의: 각 프로세스의 메타 데이터(데이터에 대한 정보를 제공하는 구조화된 데이터)를 저장하는 데이터 블로, 커널 스택(가상메모리의 윗 부분에 위치하며 커널 모드에서만 접근 가능)에 저장된다
- 생성 및 제거: 프로세스의 생성/종료시 생성/제거
- 구성 요소:
- 프로세스 상태: ex 대기중, 실행 중
- 프로세스 번호(PID)
- 프로그램 카운터(PC): 다음에 실행될 명령어의 주소를 가리키는 포인터
- 레지스터 정보: 프로세스의 레지스터 상태
- 메모리 제한: 프로세스의 메모리 범위
- 열린 파일 정보: 프로세스에 의해 열린 파일 목록
컨텍스트 스위칭
-
정의: 프로세스(또는 스레드)의 상태를 저장하고 복원하는 과정. 프로세스의 중단, 재시작, 인터럽트 발생 시 수행
-
비용
- 유후시간 발생: 컨텍스트 스위칭으로 인해 CPU 가용성이 감소하는 시간 발생
- 캐시미스: TLB 캐시를 클리어하는 과정에서 캐시 미스 발생
-
스레드의 컨텍스트 스위칭: 스레드는 스택을 제외한 대부분의 메모리를 공유하므로, 비용 시간 프로세스에 비해 적게 든다
프로세스 상태
프로세스의 라이프 사이클. 운영체제가 프로세스 상태를 관리하여 시스템의 자원 효과적으로 활용
생성 상태 (create/new)
- 프로세스의 생성
fork()
(부모 프로세스의 주소 공간 복사해 자식 프로세스 생성)또는 exec()
(새 프로세스 생성)함수를 통해 프로세스가 생성
- PCB 할당
대기 상태 (ready)
- 프로세스가 준비 큐에 들어가서 대기중 상태
- CPU 스케쥴러로부터 CPU 실행 권한 대기
대기 중단 상태 (ready suspended)
- 메모리 부족 등의 이유로 준비 큐에서 일시 중단된 상태(준비 큐 full)
실행 상태 (running)
- CPU와 메모리를 할당받아 명령어를 실행하는 상태
중단 상태 (blocked)
- 특정 이벤트 (I/O로) 인해 프로세스 실행이 일시적으로 중단된 상태
일시중단 상태 (blocked suspended)
- 중단 상태에서 메모리 부족으로 인해 프로세스가 일시적으로 중단된 상태
종료 상태 (terminated/exit)
- 프로세스 실행 완료, 자원 반납
- 자연스러운 종료 또는 강제 종료(abort)
멀티 프로세싱과 멀티 스레딩
멀티 프로세싱
- 정의: 여러 개의 프로세스를 사용하여 동시에 여러 작업을 수행
장점:
- 병렬 처리 가능: 똑같은 또는 다른 작업을 동시에 수행
- 격리성 및 신뢰성: 하나의 프로세스에 문제가 생겨도 다른 프로세스에 영향 X
- 적용: 고신뢰성이 요구되는 시스템이나, 병렬 처리가 필요한 경우에 유용
멀티 스레딩
- 정의: 하나의 프로세스 내에서 여러 스레드를 사용하여 작업을 수행하는 기법
- 장점:
- 효율성: 스레드는 프로세스보다 가볍고 자원을 공유하기 때문에 더 효율적
- 단점:
- 상호 의존성: 한 스레드에 문제가 발생하면 같은 프로세스 내의 다른 스레드에 영향 ㅇ
- 적용: 자원의 효율적 사용이 중요한 경우나 빠른 응답 시간이 요구되는 시스템에 적합
Java 멀티 스레딩 예시
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.lang.ProcessHandle;
public class MultiProcessingExample {
public static void main(String[] args) {
Runnable task1 = () -> processTask("프로세스 1");
Runnable task2 = () -> processTask("프로세스 2");
Thread thread1 = new Thread(task1);
Thread thread2 = new Thread(task2);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void processTask(String name) {
System.out.println("pid of parent: " + ProcessHandle.current().parent().orElseThrow().pid());
System.out.println("pid of " + name + " : " + ProcessHandle.current().pid());
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://w3schools.com/python/demopage.htm"))
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
IPC
Inter-Process Communication, 프로세스 간 데이터를 주고받기 위한 매커니즘
1. 공유 메모리
- 여러 프로세스가 동일한 메모리 영역을 공유하여 통신
- 데이터 복사 오버헤드가 없어 가장 빠른 통신 방법
- 동기화가 필요
2. 파일
- 디스크에 저장된 파일을 통해 프로세스 간 통신
3. 소켓
- 네트워크 인터페이스(TCP, UDP, HTTP 등)를 이용한 통신
4. 파이프
- 익명 파이프: FIFO 기반의 통신 채널을 만들어 통신하는 것으로 파이프 하나 당 단방향 통신이기에 양방향 통신을 하려면 2개의 익명 파이프 필요 주로 부모-자식 프로세스 간 통신에 적합, 다른 네트웨커 상에는 사용 불가
- 명명 파이프: 익명 파이프의 확장 형태로, 서로 다른 네트워크 상의 다양한 프로세스 간 통신 가능. 서버, 클라이언트용 파이프를 구분해서 동작
5. 메시지 큐
- 메시지를 큐 형태로 관리하며 프로세스 간 통신
- 보내는 프로세스(sender)는 메시지를 큐에 넣고, 받는 프로세스(receiver)는 큐에서 메시지를 받음
REF