1. Process
- 메모리에 적재되고 CPU 자원을 할당 받아 프로그램이 실행되고 있는 상태
- OS를 통해 여러 Process를 실행하고 관리할 수 있다.
1-1) PCB(Process Control Block)
프로세스 제어블록은 특정한 프로세스를 관리할 피룡가 있는 정보를 포함하는 운영체제 커널의 자료구조이다. PCB가 필요한 이유는 Context Switching 때문이다. CPU가 여러 프로세스를 빠르게 번갈아가면서 작업하기 위해서는 프로세스에 대한 정보 및 상태를 저장/복원 할 필요가 있다.
1-2) Process 상태
new - 프로세스가 생성되는 상태
ready - 프로세스가 CPU에 할당되어, 처리되기를 기다리는 상태
running - 프로세스가 CPU에 할당되어, 명령어들이 실행되는 상태
waiting - 어떤 이벤트의 발생으로 인해 프로세스가 기다리는 상태
terminated - 프로세스가 종료되는 상태
1-3) 메모리 영역
하나의 프로세스는 각각 독립된 메모리 영역(Code, Data, Stack, Heap)을 할당 받는다.
Code - 코드 영역은 실행할 프로그램의 코드 및 매크로 상수가 기계어 형태로 저장되는 영역이다. CPU는 코드영역에 저장된 명령어를 하나씩 처리한다.
Data - 데이터 영역은 코드에서 선언한 전역 변수와 정적변수가 저장되는 영역이다. 데이터 영역은 프로그램의 시작과 함꼐 할당되어 종료될 떄 소멸된다.
Stack - 스택영역은 함수 안에서 선언된 지역변수, 매개변수, 리턴값, 등이 저장되고 함수 호출시 기록하고 종료되면 제거한다. 스택이라는 자료구조 명칭에서도 알 수 있듯이 LIFO 이다.( 흔히 재귀함수를 통해 너무 많은 함수를 호출하게 되는 경우 스택영역이 초과하면서 StackOverFlow가 발생한다.)
Heap - 힙은 동적 메모리 할당 공간이다.
1-4)IPC (Inter-process Communication)
프로세스 간에 통신하여 상호 커뮤니케이션을 하는 기법이다. 프로세스끼리 직접적으로 '대화'하는 방법은 없다. 프로세스들이 서로 공간을 쉽게 접근하면 프로세스의 데이터나 코드가 다른 프로세스에 의해 쉽게 빠귈 수 있기 때문이다. 프로세스는 통신을 직접적으로 할 수가 없고, 서로의 공간을 접글할 수가 없다. 그래도 프로세스 간의 커뮤니케이션은 필요하기 때문에 나온 기법이라 볼 수 있다. (pipe, message queue, shared memory) 등이 있다.
---> 리눅스는 프로세스 공간이 완전히 분리되어 있다. 그리고 어떤 프로세스는 하나 당 4GB 공간을 관리하고 있고, 사용자 공간을 0~3GB 주소까지 지정하고 커널 공간을 3~4GB 주소까지 지정한다. 이는 물리 메모리가 아닌 가상메모리다. 여기서 중요한 것은 모든 프로세스가 커널 공간을 공유하는 것이고 리눅스는 커널 공간에서 프로세스간 공유(통신)이 가능하다.
2. Thread
- 쓰레드란 프로그램 내에서 다른 코드와 독립되어 실행될 수 있는 최소 단위이다.
- 운영체제 입장에서 작업의 최소 단위는 Process이고, CPU입장에서는 Thread가 최소단위이다.
2-1 ) TCB
하나의 Thread를 관리하는데 필요한 정보를 담고 있는 구조체이다. 프로세스의 상태를 관리하는 PC보다 적은 양의 정보가 담겨있다. Thread사이의 context switching 그리고 process 사이의 context switching을 할 때 CPU scheduling을 하는 최소 단위이다.
- Context Switching
CPU의 코어가 1개라면 동시에 단 하나의 프로세스만 실행이 가능하다. CPU scheduling을 통해서 하나의 CPU를 여러 작업들이 공유할 수 있게 cpu시간을 나누어 작업을 수행한다.
이떄, 프로세서가 지금까지 실행되던 프로세스(A)를 중지하고 다른 프로세스(B)의 PCB정보를 바탕으로 프로세스(B)를 실행하는 것을 Process Context Switching이라 한다.
여기서 동일한 프로세스 속에서 하나의 쓰레드(a)를 중지하고 다른 쓰레드 (b)의 TCB 정보를 바탕으로 쓰레드(b)를 실행하는 것을 Thread Context Switching이라 한다. 참고로 Process는 하나 이상의 Thread로 동작하기 때문에 Context Switching의 최소 단위는 TCB이다.
3. 메모리 구조 - 프로세스
프로세스의 메모리
- Stack
:프로그램이 자동으로 사용하는 메모리 영역으로 함수 호출과 관계되는 지역변수와 매개변수가 저장된다.
:함수 호출 시 생성되며, 함수가 끝나면 반환된다.
- Data 영역(BSS, GVAR)
: 전역변수와 정적 변수가 저장된다. 이 변수들은 프로그램이 시작될 때 할당되어 프로그램 종료시 소멸된다.
: BSS에는 초기화되지 않은 전역변수가 저장된다.
- Heap 영역
: 동적 데이터 영역이다. 메모리 주소 값에 의해서만 참조되고 사용되는 영역이다. 따라서 동작시(런타임)에 크기가 결정 된다.
- Code(Text)
: 실행할 프로그램의 코드가 저장된다. CPU는 이 영역에서 명령어를 하나씩 가져와 처리하게 된다.
4. JVM
일반 적인 프로그램은 프로그램 -> 운영체제 -> 하드웨어 순으로 동작하기에 운영체제가 무엇인지에 따라서 프로그램이 작동될 수도 안 될수도 있다. 하지만 자바프로그램은 프로그램 -> JVM -> 운영체제 -> 하드웨어 순이기에 어떠한 운영체제에서도 동일한 결과를 갖는다. 하지만 한 단계 더 걸치기 때문에 속도가 기존 방식보다 뒤처질 수도 있다.
- JVM 동작방식
: Source Code(.java) 파일을 Java Compiler를 통해서 Byte Code(.class) 파일로 변환한다. (컴퓨터가 읽어야해서)
: Byte Code로 변환된 파일을 JVM의 Class Loader로 보낸다.
: Class Loader는 말 그대로 Class 파일을 불러와서 메모리에 저장하는 역할을 한다.
: Execution Engine은 Class Loader에 저장된 Byte Code를 명령어 단위로 분류하여 하나씩 실행하게 하는 엔진이다.
: Garbage Collector는 사용하지 않거나 필요없는 객체들을 메모리에서 소멸시키는 역할을 한다.
: Runtime Data Area(Memory Area)는 JVM이 프로그램을 수행하기 위해 운영체제로부터 할당 받은 메모리 공간이다.
- Runtime Data Area( Memory Area)
: Method Area
-> JVM이 실행되면서 생기는 공간이다.
-> Class 정보, 전역변수, Static 변수 정보가 저장되는 공간이다.
-> 모든 쓰레드에서 정보가 공유된다.
: Heap
-> new 연산자로 생성된 객체, Array와 같은 동적으로 생성된 데이터가 저장되는 공간.
-> Heap에 저장된 데이터는 Garbage Collector가 처리하지 않는 한 소멸되지 않는다.
-> Reference Type 의 데이터가 저장되는 공간
-> 모든 쓰레드에서 정보가 공유된다.
: Stack
-> 지연변수, 메소드의 매개변수와 같이 잠시 사용되고 필요가 없어지는 데이터가 저장되는 공간
-> Last In First Out 나중에 들어온 데이터가 먼저 나간다.
-> 만약 지역 변수이지만 Reference Type일 경우에는 Heap에 저장된 데이터의 주소값을 Stack에 저장해서 사용하게 된다.
-> 쓰레드마다 하나씩 존재한다.(공유하지 않는다)
: PC Register
-> 쓰레드가 생성되면서 생기는 공간
-> 쓰레드가 어느 명령어를 처리하고 있는지 그 주소를 등록한다.
-> JVM이 실행하고 있는 현재 위치를 저장하는 역할
: Native Method Stack
-> Java가 아닌 다른 언어로 구성된 메소드를 실행이 필요할 때 사용되는 공간
참고
https://watermelon-sugar.tistory.com/37
https://velog.io/@redgem92/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-IPC-%EA%B8%B0%EB%B2%95
https://charlezz.medium.com/process%EC%99%80-thread-%EC%9D%B4%EC%95%BC%EA%B8%B0-5b96d0d43e37