티스토리 뷰
프로세스란?
프로세스란 현재 메모리에서 실행중인 프로그램 또는 작업을 의미합니다.
💡 프로세스의 메모리 레이아웃
- 프로세스의 메모리 레이아웃은 스택, 힙, 데이터, 텍스트 세그먼트로 분활되어 있습니다.
- 텍스트 세그먼트는 명령 및 상수와 같은 프로그램이 실행할 수 있도록 하는 코드가 포함되어 있으며, 코드 세그먼트라고도 합니다.
- 데이터 세그먼트는 초기화되어있거나 초기화되어 있지 않은 전역 변수 및 정적 변수가 포함되어 있습니다.
- 힙 세그먼트는 런타임 시 동적으로 할당되는 메모리입니다.
- 스택 세그먼트는 함수를 호출할 때 지역 변수, 함수 호출이 끝난 뒤 복귀 주소, 함수의 매개변수 및 함수 호출 프레임을 저장하는데 사용되는 메모리입니다.
덧붙이자면 텍스트 세그먼트와 데이터 세그먼트는 크기가 고정되어 있기 때문에 프로그램 실행 시간동안 크기가 변하지 않습니다. 반면 스택과 힙 세그먼트는 프로그램 실행 도중 동적으로 메모리가 변할 수 있습니다.
🤔 자바에서 스택 세그먼트란 무엇인가?
- 스택은 지역 변수와 함수 호출 프레임을 저장하는데 어떠한 함수가 호출되면 맨 위에 프레임이 추가되고 함수가 반환되면 프레임이 스택의 맨 위에서 제거됩니다. 이러한 후입선출(LIFO) 동작으로 인해 스택이 아래쪽으로 커지고 새로운 프레임은 더 낮은 메모리 주소에 추가됩니다.
아래와 같은 코드가 있을 경우 main 함수는 methodA를 호출하고 순차적으로 다른 메서드를 호출하게 됩니다. 이때 자바의 Call Stack에 어떻게 저장이 되는지 알 필요성이 있습니다.
public class Application {
public static void main(String[] args) {
Application application = new Application();
application.methodA();
}
public void methodA() {
methodB();
}
public void methodB() {
methodC();
}
public void methodC() {
System.out.println("The End.");
}
}
Java에서는 메서드가 호출될때마다 새로운 프레임이 호출 스택에 추가됩니다. 호출 스택은 위에서 언급한거처럼 지역 변수, 매개변수, 반환 주소를 가집니다. 메서드가 반환되면 해당 프레임이 호출 스택에서 제가됩니다. 만약 어떠한 메서드가 종료 조건 없이 자신을 재귀적으로 호출하거나 메서드가 순환 방식으로 서로 재귀적으로 호출하는 경우 스택이 너무 깊어져 스택 오버 플로우가 발생할 수 있습니다.
🤔 자바에서 힙 세그먼트란 무엇인가?
- 자바에서 객체나 배열은 힙 세그먼트에 저장됩니다. 힙 세그먼트는 모든 스레드에서 접근이 가능하고, 사용되는 공유 메모리 영역입니다.
- GC는 힙 세그먼트에서 사용되지 않는 객체를 식별하고 제거하여 메모리를 확보합니다.
💡 프로세스의 상태
- 프로세스는 실행시간 동안 계속하여 그 상태가 변합니다.
new 상태
- 프로세스가 생성중인 상태입니다. 이 단계에서는 만들어질 프로세스에 대한 메모리 할당과 메모리의 정보를 담고 있는 PCB를 만들어야 하므로 해당 상태에 처음 머물러야합니다.
- 또한 new 상태에서 ready 상태로 진입하기 위해서는 승인을 받아야하는데 승인을 받는 이유는 메모리 공간은 한정적이기 때문에 승인이 필요합니다. 또한 CPU는 시분할을 통해 동시에 진행하는 것처럼 보이므로 실행시키고자 하는 프로그램이 많아질수록 시간이 오래걸리고 성능적 문제가 발생할 수 있습니다.
ready 상태
- 실행을 하기위해 기다리는 상태입니다. 언제든지 실행할 수 있고 CPU가 자원을 할당해주면 바로 실행될 수 있습니다.
- 스케줄러 디스패치가 대기중인 프로세스들 중 적절한 프로세스를 찾고 실행상태로 옮깁니다.
running 상태
- 프로세스가 CPU를 차치하고 실행중인 상태입니다.
- running 상태에서 프로그램이 정상적으로 종료하게 되면 terminated 상태로 옮깁니다.
- running 상태에서 ready 상태로도 갈 수 있습니다. CPU는 시분할을 통해 프로세스들을 실행시키므로 프로세스가 길면 timeout이 걸려 ready 상태로 옮깁니다.
- running 상태에서 waiting 상태로도 갈 수 있습니다. 만약 프로그램 실행도중 비밀번호 입력등의 이벤트들로 인해 waiting 상태로 옮겨질 수 있습니다.
waiting 상태
- 프로그램 실행도중 비밀번호 입력 등과 같은 이벤트들로 인해 waiting 상태로 옮겨질 수 있으며 이벤트가 완료되면 다시 ready 상태로 옮겨집니다.
💡 프로세스 제어 블록(PCB)
- 각 프로세스는 운영체제에서 프로세스 제어 블록(Process Control Block)에 의해 표현됩니다.
- PCB란 특정 프로세스에 대한 정보를 관리하기 위해 운영체제에서 사용하는 데이터 구조이빈다.
- PCB는 프로세스가 생성되고 종료하면 소멸됩니다. 운영체제는 PCB에 저장된 정보를 사용하여 프로세스 실행을 관리하고 올바르게 실행하는데 필요한 자원에 접근할 수 있는지 확인합니다.
프로세스 상태
- 프로세스의 상태 정보를 가지고 있습니다.(new, ready, waiting, running, terminated)
프로세스 카운터
- 프로그램 카운터는 프로세스가 다음에 실행될 명령어의 주소를 가리킵니다.
CPU 레지스터들
- CPU 레지스터는 컴퓨터의 구조에 따라 다양한 수와 유형을 가집니다. 레지스터에는 누산기, 인덱스 레지스터, 스택 레지스터, 범용 레지스터들과 상태 코드 정보가 포함됩니다. 프로그램 카운터와 함께 나중에 프로세스가 다시 스케줄될 때 올바르게 실행되도록 하기 위해 인터럽트 발생 시 저장되어야 합니다.
CPU 스케줄링 정보
- 이 정보는 프러세스 우선순위, 스케줄 큐에 대한 포인터와 다른 스케줄 매개변수를 포함합니다.
메모리 관리 정보
- 운영체제에 의해 사용되는 메모리 시스템에 따라 기준 레지스터와 한계 레지스터의 값, 운영체제가 사용하는 메모리 시스템에 따라 페이지 테이블 또는 세그먼트 테이블과 같은 정보를 포함합니다.
회계 정보
- CPU 사용시간과 경과된 실시간, 시간 제한, 계정 번호, 프로세스 정보등을 포함합니다.
프로세스 스케줄링
비싼 CPU 사용을 효율적으로 하기 위해서는 항상 어떠한 프로세스가 실행되도록 해야합니다. 이러한 목적을 달성하기 위해 프로세스 스케줄러는 코어에서 실행가능한 여러 프로세스들 중 하나를 선택합니다. 단일 CPU 환경에서는 한번에 하나의 프로세스를 실행할 수 있지만 멀티 CPU 환경에서는 CPU의 수만큼 프로세스를 실행할 수 있습니다. 만약 CPU core보다 많은 수의 프로세스가 있는 경우 초과 프로세스는 core가 사용가능해질 때까지 기다려야 합니다.
💡 스케줄링 큐
준비 큐
- 준비 큐는 프로세스 또는 스레드가 메모리에 적재되어 실행되기를 기다리고 있는 프로세스 및 스레드 입니다.
- 프로세스나 스레드가 생성되면 CPU에 의해 실행될 수 있을때까지 준비큐에 담기게 됩니다.
- 준비 큐는 일반적으로 Linked List로 저장되며, 준비 큐의 헤더에는 리스트의 첫 번째 PCB에 대한 카운터 포인터가 저당되고 그 다음에는 다음의 PCB를 가리키는 카운터 포인터 필드가 포함됩니다.
대기 큐
- 프로그램 실행도중 비밀번호 입력과 같은 이벤트들로 인해 waiting 상태가 된 프로세스 또는 스레드는 대기 큐에 담기게 됩니다.
- 대기 큐는 여러 프로세스 또는 스레드가 서로 간섭하지 않고 동시에 실행될 수 있도록 하기 때문에 운영체제에서 스케줄링 대기 큐는 필수적인 부분입니다.
- 이벤트나 특정 리스소를 기다리는 프로세스나 스레드를 차단함으로써 운영 체제는 CPU 시간이 효율적으로 사용되고 프로세스나 스레드가 이벤트나 리소스를 폴링하여 CPU 주기를 낭비하지 않도록 할 수 있습니다.
💡 CPU 스케줄링
- CPU 스케줄러는 준비 큐에 있는 프로세스들 중 하나의 프로세스에 CPU 자원을 할당하는 것입니다.
- 실행 중에 프로세스 또는 스레드가 I/O 같은 이벤트를 기다려야 하는 경우 프로세스 또는 스레드는 대기 큐에 담기게 됩니다. 그리고 이벤트가 완료되면 다시 준비 큐로 이동하게 됩니다.
- 일반적인 스케줄링 알고리즘에는 우선 순위 스케줄링, 라운드 로빈, SJF, FCFS가 있습니다.
🤔 cpu 스케줄링의 한 형태인 스와핑은 무엇인가?
- CPU에서 프로세스를 일시적으로 제거하고 디스크에 저장하여 다른 프로세스가 메모리를 사용할 수 있도록 하는 것입니다.
- 스와핑은 일반적으로 현재 실행중인 모든 프로세스를 보유할 수 있는 물리적인 메모리가 충분하지 않은 경우에 사용됩니다.
- 프로세스가 교체되면 PCB 등의 정보가 디스크에 저장되고, 다른 프로세스를 로드할 수 있습니다. 이때 원래 프로세스를 다시 실행해야 하는 경우 운영체제는 프로세스를 다시 메모리에 적재하고 교체합니다.
- 스와핑은 기본적으로 디스크에 읽고 씀으로 메모리에 접근하는 것보다 느립니다. 따라서 스와핑은 메모리를 확보하기 위한 다른 수단이 없는 경우에만 사용하는 것이 좋습니다.
💡 문맥 교환: context switch
- 문맥 교환은 운영체제가 현재 실행중인 프로세스의 상태를 저장하여 나중에 다시 실행할 수 있도록하는 작업입니다.
- 일반적으로 커널 모드이건 사용자 모드인건 CPU의 현재 상태(PCB)를 저장하는 작업을 수행하고, 나중에 다시 실행할 수 있도록 복구 작업을 수행합니다.
🤔 context switch가 필요한 이유가 뭘까?
- 운영체제가 공정한 방식으로 여러 프로세스에 CPU 시간을 효율적으로 할당하여 단일 프로세스가 CPU를 독점하는 것을 방지하기 위해 필요합니다.
🤔 context switch의 장점과 단점이 뭘까?
장점
- 멀티 태스킹입니다. 문맥 교환을 통해 운영체제는 여러 프로세스 또는 스레드를 동시에 실행할 수 있습니다. 이를 통해 사용자는 동시에 여러 작업을 수행할 수 있기 때문에 생산성 및 효율성이 증가합니다.
- 리소스 공유입니다. 문맥 교환을 통해 여러 프로세스 또는 스레드가 CPU, 메모리 및 I/O 장치와 같은 시스템 리소스를 공유할 수 있습니다. 이것은 자원 낭비를 줄이고 시스템 성능을 향상시킬 수 있습니다.
- 공정성입니다. 문맥 교환은 프로세스가 독점적으로 CPU를 가지는 것을 방지하여 기아 상탤를 방지합니다.
단점
- 오버헤드가 발생할 수 있습니다. 문맥 교환은 시스템 리소스 측면에서 오버헤드를 발생시킵니다. 운영체제는 시간을 들여 프로세스를 저장하고 복원해야 하는데 이러한 작업으로 인해 성능이 느려질 수 있습니다.
- 캐시 미스가 발생할 수 있습니다. 문맥 교환은 프로세스가 CPU 캐시에 저장한 데이터를 잃을 때 발생하는 캐시 미스를 유발할 수 있는데 만약 있어야할 데이터가 없다면 프로세스가 실행을 재개할 때 메모리에서 데이터를 다시 로드해야 하므로 성능이 느려질 수 있습니다.
프로세스 연산
대부분 시스템 내의 프로세스들은 병행 실행될 수 있으며, 반드시 동적으로 생성되고 제거되어야 합니다.
💡 프로세스 생성
- 생성하는 프로세스를 부모 프로세스라 부르고, 새로운 프로세스는 자식 프로세스라 부릅니다. 이러한 프로세스는 트리 구조를 가지게 됩니다.
- 일반적으로 프로세스가 자식 프로세스를 생성할 때, 그 자식 프로세스는 자신의 임무를 달성하기 위해 자원이 필요합니다. 이러한 자원은 운영체제로부터 직접적으로 얻거나, 부모 프로세스가 가진 자원의 부분 집합만을 사용할 수 있도록 제한할 수 있습니다.
- 부모 프로세스는 자원을 분할하여 자식 프로세스에게 나누어 주거나 메모리 및 파일과 같은 몇몇 자원들은 자식 프로세스들이 같이 사용할 수도 있습니다. 또한 부모 프로세스는 자식 프로세스를 과도하게 생성하는 것을 방지할 수 있으며 시스템이 과부화 상태로 빠지는 것을 방지할 수 있습니다.
💡 프로세스 종료
- 자원을 할당받은 프로세스는 자신의 임무가 끝나면 종료를 할 수 있습니다.
- 부모 프로세스는 자식 프로세스를 종료시키기 위해 PID를 알아야합니다. 그러므로 한 프로세스가 새로운 프로세스를 만들 때 새롭게 만들어진 프로세스의 PID는 부모에게 전달됩니다.
- 몇몇 시스템에서는 부모 프로세스가 종료된 이후에 자식 프로세스가 존재할 수 없습니다. 그러한 시스템에서는 부모 프로세스가 종료되면 모든 자식 프로세스들 또한 종료되어야 합니다. 이것을 연쇄적 종료라 하며 이 작업은 운영체제가 시행합니다.
부모는 다음과 같은 이유로 자식 프로세스를 종료시킬 수 있습니다.
- 자식 프로세스가 자신에게 할당된 자원을 초과하여 사용할 때, 이때는 부모가 자식들의 상태를 검사할 수 있는 방편이 주어져야 합니다.
- 자식에게 할당된 작업이 더 이상 필요없을 때입니다.
- 부모가 exit하는데, 운영체제는 부모가 exit한 후에 자식이 실행을 계속하는 것을 허용하지 않을때 입니다.
🤔 좀비 프로세스란 무엇인가?
- Unix 및 Unix와 비슷한 운영체제에서 좀비 프로세스 또는 소멸된 프로세스는 exit 시스템 호출을 통해 종료했지만 여전히 프로세스 테이블에 남아있는 프로세스입니다. 즉 "종료된 상태" 에 머물러 있는 프로세스입니다.
- 프로세스가 종료되면 메모리에서 즉시 제거되는게 아닌 아주 짧은 시간 동안 남아있게 됩니다. 그런다음 부모 프로세스는 wait 시스템 호출을 하여 좀비 프로세스의 식별자와 프로세스 테이블을 읽은 다음 이러한 정보들을 사용하여 자식 프로세스를 정리하고 메모리 및 프로세스 디스크립터를 해제하게 됩니다.
🤔 고아 프로세스란 무엇인가?
- 좀비 프로세스와 고아 프로세스는 다른 프로세스입니다. 고아 프로세스는 아직 실행중이지만 부모 프로세스가 죽은 프로세스 입니다.
부모가 죽어 고아가된 프로세스는 init 프로세스가 주기적으로 wait 시스템을 호출하여 새로운 부모 프로세스를 지정해줍니다.
프로세스간 통신
운영체제 내에서 실행되는 프로세스들은 독립적이거나 또는 협력적인 프로세스일 수 있습니다.
만약 프로세스가 시스템에서 실행중인 다른 프로세스들과 데이터를 공유하지 않은다면 독립적입니다. 반면 프로세스가 시스템에서 실행중인 다른 프로세스에 영행을 주고 받는다면 협력적인 프로세스 입니다.
프로세스간 협력을 허용하는 환경을 제공하는 이유
- 정보 공유 - 여러 응용 프로그램이 동일한 정보(복사 붙여넣기)에 흥미를 느낄 수 있으므로, 그러한 정보를 병행적으로 접근할 수 있는 환경을 제공해야 합니다.
- 계산 가속화 - 만일 우리가 특정 태스크를 빨리 실행하고자 한다면 우리는 그것을 서브 태스크로 나누어 각각이 다른 서브 태스크들과 병렬로 실행되게 해야합니다. 이러한 가속화는 복수 개의 처리 코어를 가진 경우에만 할 수 있습니다.
- 모듈성 - 운영체제 구조 중 모듈 구조로 시스템 기능을 별도의 프로세스 또는 스레드들로 나누어 모듈식 형태로 시스템을 구성하기를 원할 수 있습니다.
💡 공유 메모리 시스템에서의 프로세스간 통신
- 공유 메모리 시스템이란 여러 프로세스 또는 스레드가 공통 메모리 영역에 접근할 수 있는 시스템입니다.
- 공유 메모리 시스템에서는 shared memory segment라는 것을 사용합니다. 이 공유 메모리 세그먼트는 보통 다른 프로세스나 스레드와 데이터를 공유하려는 프로세스나 스레드에 의해 생성됩니다. 프로세스 또는 스레드는 먼저 운영체제에서 제공하는 함수 및 라이브러리를 호출하여 공유 메모리 세그먼트를 만든 다음 공유 메모리 세그먼트에 연결하여 사용합니다.
- 일반적으로 운영체제는 한 프로세스가 다른 프로세스의 메모리에 접근하는 것을 금지하는데, 공유 메모리는 둘 이상의 프로세스나 스레드가 이 제약 조건을 제거하는데 동의하는 것을 필요로 합니다. 그 후 공유 메모리를 읽고 씀으로써 정보를 교환할 수 있습니다.
🤔 공유 메모리 사용시 주의점
- race condition이 발생할 수 있습니다. 여러 프로세스나 스레드가 공유 메모리에 동시에 접근하는 경우 작업 순서가 최종 결과에 영향을 미칠 수 있습니다.
- 동기화 문제가 발생할 수 있습니다.
- 캐시 일관성이 깨질 수 있습니다. 트래픽이 많이 발생하여 캐시를 적용했는데 프로세스나 스레드가 동시에 접근하는 경우 캐시 일관성 프로토콜이 제대로 구현되어있지 않다면 잘못된 데이터를 읽을 수 있습니다.
- 메모리 공간이 부족해질 수 있습니다. 여러 프로세스나 스레드가 메모리를 공유하면서 전체적인 메모리 공간이 증가할 수 있습니다.
이때 사용 가능한 메모리에 제한이 있거나 사용량이 제대로 관리가 되지 않은 경우 문제가 발생할 수 있습니다.
💡 메시지 전달 시스템에서의 프로세스간 통신
- 메시지 전달 시스템은 프로세스나 스레드가 메시지를 교환하여 서로 통신하는 시스템입니다.
- 메시지 전달 시스템에서 각 프로세스나 스레드는 자체 메모리 공간을 가지며, 프로세스 또는 스레드 간의 통신은 통신 채널을 통해 메시지를 주고 받습니다. 이러한 메시지 전달은 동기 및 비동기 방식을 통해 이루어질 수 있습니다.
🤔 해당 챕터를 읽으며 생각해볼 수 있는 질문들
- 자바에서 스택 세그먼트란 무엇이며, 스택 세그먼트에서 발생할 수 있는 예외는 어떤게 있을까?
- 자바에서 힙 세그먼트는 어떻게 구성되어 있으며, 어떻게 동작할까?
- 프로세스 상태 중 new 상태와 ready 상태가 따로 구분되어 있는데 왜 구분되어 있을까?
- CPU 스케줄링의 한 형태인 스와핑은 무엇일까?
- context switch가 필요한 이유가 무엇일까?
- context switch의 장점과 단점이 무엇일까?
- 프로세스 종료 중 좀비 프로세스가 무엇일까?
- 프로세스 종료 중 고아 프로세스가 무엇일까?
- 공유 메모리 시스템이란 무엇일까?
- 공유 메모리 시스템에서 주의해야할 점이 무엇일까?
- 동기, 비동기는 어떻게 동작되는가?
- 질문에 대한 답변은 깃허브에 있습니다. -> 깃 허브로 이동
참고
- https://www.geekbits.io/understanding-zombie-processes-in-linux/
- https://medium.com/coding-in-simple-english/the-fear-of-zombie-processes-8d2f00449795
- 운영체제 3장 - 프로세스 관리
- Total
- Today
- Yesterday
- 서비스 기반 아키텍처
- spring boot excel download oom
- space based architecture
- spring boot redisson sorted set
- JDK Dynamic Proxy와 CGLIB의 차이
- java ThreadLocal
- transactional outbox pattern spring boot
- redis 대기열 구현
- redis sorted set으로 대기열 구현
- 트랜잭셔널 아웃박스 패턴 스프링부트
- spring boot 엑셀 다운로드
- java userThread와 DaemonThread
- spring boot redis 대기열 구현
- spring boot poi excel download
- 트랜잭셔널 아웃박스 패턴 스프링 부트 예제
- polling publisher spring boot
- 레이어드 아키텍처란
- redis sorted set
- spring boot excel download paging
- 람다 표현식
- service based architecture
- pipe and filter architecture
- spring boot redisson destributed lock
- @ControllerAdvice
- spring boot redisson 분산락 구현
- 공간 기반 아키텍처
- 자바 백엔드 개발자 추천 도서
- transactional outbox pattern
- pipeline architecture
- microkernel architecture
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |