Heap 영역 : 런타임시 동적으로 메모리 할당받는 영역 (new(), malloc() 등)
Stack 영역 : 지역 변수, 매개변수, 리턴 값 등의 임시적인 데이터들 담기는 영역
프로세스 특징
프로세스마다 최소 1개의 스레드를 가지고 있음
각 프로세스는 별도의 주소 공간에서 실행되며, 한 프로세스는 다른 프로세스의 변수에 접근 불가능
스레드(Thread)란?
프로세스 내에서 실행되는 여러 흐름의 단위
프로세스가 할당받은 자원을 이용하는 실행의 단위
프로세스의 특정한 수행 경로
ex: 햄버거를 만드는 프로세스에서는 패티를 굽는 스레드가 진행되는 동안, 빵에 야채를 얹고 소스를 뿌리는 등의 스레드도 동시에 진행될 수 있음
스레드의 특징
스레드는 프로세스 내에서 Stack만 따로 할당받고 Code, Data, Heap 영역은 공유 (프로세스는 Code, Data, Stack, Heap으로 구성)
한 스레드가 프로세스 자원을 변경하면, 다른 이웃 스레드(sibling thread)도 그 변경 결과를 즉시 볼 수 있음
※ 스레드마다 독립적인 Stack을 갖는 이유
스택은 함수 호출시 전달되는 인자, 되돌아갈 주소값 및 함수 내에서 선언하는 변수 등을 저장하기 위해 사용되는 메모리 공간이므로 스택 메모리 공간이독립적이라는것은 독립적인 함수 호출이가능하다는 것이고 이는독립적인 실행 흐름이 추가되는 것이다. 따라서 스레드 정의에 따라 독립적인 실행 흐름을 추가하기 위한 최소 조건으로 독립된 스택을 할당한다.
→ 각 스레드별로 수행하는 업무가 다를 것이기 때문에, 최소한의 독립 조건으로 스레드마다 독립된 Stack을 할당해 주는 것 (구분을 위해)
정리하자면...
프로세스는 컴퓨터의 자원을 분할해서 쓰지만, 스레드는 프로세스마다 주어진 전체 자원을 함께 사용한다.
≒ 프로세스는 각자의 고유 공간을 할당받아 사용하지만, 스레드는 프로세스 내에서 다른 스레드와 공간과 자원을 함께 사용한다.
- 프로그램과 프로그램 수행에 필요한 데이터 및 코드를 저장하는 장치 - 메모리는 크게 내부 기억장치인 주기억장치와 외부 기억장치인 보조 기억장치로 분류됨 ▷ DRAM(RAM, DDR4) 등의 메모리, CPU 안에 있는 레지스터(register)와 캐쉬(cache memory) 등이 주기억장치 ▷SSD, HDD 등이 보조 기억장치
2) 가상 메모리란?
- 메모리가 실제 메모리보다 많아 보이게 하는 기술 - 어떤 프로세스가 실행될때 메모리에 해당 프로세스 전체가 올라가지 않더라도 실행 가능함 - 프로그램 실행에 필요한 일부분만 메모리에 올라가며, 나머지는 디스크에 남음 (즉, 디스크가 RAM의 보조 기억장치처럼 작동 → 가상메모리의 핵심은 보조 기억장치) - 가상 메모리 구현을 위해서는 컴퓨터가 특수 메모리 관리 하드웨어를 갖춰야함 = MMU(Memory Management Unit) - MMU는 가상주소를 물리주소로 변환 & 메모리를 보호하는 기능을 수행
3) (가상) 메모리 관리 기법
- 할당정책, 호출정책, 배치정책, 교체정책 이 존재 ≫ 페이징 기법과 세그먼트 기법은 할당정책에 해당!
4) 메모리 단편화란?
- 메모리의 빈 공간이 여러 조각으로 나뉘는 현상 - 컴퓨터에서 어떤 프로그램을 실행할 때, 메모리의 공간을 연속적인 형태로 할당하여 사용하게 됨 - 이렇게 프로그램이 메모리에 할당되고, 해제되고, 다시 새로운 프로그램이 할당되고를 반복하다보면 메모리 공간이 조각조각 나뉘게 되어 실제로는 사용가능한 메모리가 충분히 존재하지만, 할당이 불가능한 상태가 발생함 > 이를 메모리 단편화 문제라고 함
- 내부단편화, 외부단편화 존재 ▷내부단편화 : 메모리를 할당할때, 프로세스가 필요한 보다 더 큰 메모리가 할당되어 프로세스에서 사용하는 메모리 공간이 낭비되는 상황 ▷외부단편화 : 메모리가 할당되고 해제되는 작업이 반복적으로 발생할때, 중간중간 사용하지 않는 작은 메모리가 생김 / 총 메모리공간은 충분하지만, 실제로는 할당할 수 없는 상황을 외부 단편화라고 함
IPC 란 Inter Process Communication의 약자로, 직역하면 프로세스간의 통신을 의미한다. 프로세스간의 통신이 가능하도록 커널에서는 IPC 통신 설비를 제공해주는데, IPC 설비 종류에도 여러가지가 있고 (PIPE, Message Queue, Socket ...) 이는 필요에 따라 선택해서 사용한다.
이러한 IPC 통신에서 프로세스 간의 데이터를 동기화하고 보호하기 위해 운영체제에서 제공하는 동기화용 커널객체가 있다.
즉, 데이터를 한번에 하나의 프로세스만 접근할 수 있도록 제한을 두는 일종의 프로세스 동기화 메커니즘이 존재한다.
이걸 다른 말로 한번더 설명한다면… 운영체제 상에는 '임계구역' 이라는 것이 존재한다.
임계구역이란, 멀티 프로세스 환경에서 둘 이상의 프로세스가 동시에 접근해서는 안되는 공유자원의 코드 영역이다. 이렇게 임계 구역에 여러 프로세스 및 스레드가 함부로 접근할 수 없도록 관리를 잘 해줘야 하는데, 이를 위해 사용하는 방식에 대표적으로 세마포어(Semaphore)와 뮤텍스(Mutex)가 있다
세마포어 (Semaphore)
멀티 프로그래밍 환경에서 공유된 자원에 대한 접근을 제한하는 방법
뮤텍스 (Mutex)
공유 불가능한 자원의 동시 사용을 피하기 위해 사용하는 방법
→ 접근 제어를 위해 lock과 unlock 사용
- lock: 현재 임계 구역에 들어갈 권한을 얻어옴 - unlock: 현재 임계 구역을 모두 사용했음을 알림
- 현재 공유 자원의 상태를 나타내는 카운터 변수를 사용 - 카운터 변수는 운영체제 혹은 커널에 값으로 저장
- 각 프로세스는 해당 카운터 변수를 확인하고 변경 가능 - 카운터 변수의 값은 1보다 더 큰 숫자도 가질 수 있음 - 해당 변수값이 공유 자원에 접근할 수 있는 프로세스 개수의 임계치 - 이를 조정해 접근 가능한 프로세스 개수 통제
2) 뮤텍스 - 이진 세마포어라고도 불림 (상태가 0,1) - 1개의 프로세스 혹은 스레드만이 공유 자원에 접근 가능함 - lock과 unlock ▷ 뮤텍스는 자원을 점유하고 있는 프로세스가 lock을 할 수 있는 권한을 가져서, 자원을 점유하기 시작할때 lock을 걸어버림 ▷ lock을 가지고 있는 변수만이 unlock을 할 수있고, 다른 프로세스들은 unlock 상태가 될때까지 기다렸다가 나중에 해당 공유 자원에 접근 가능 ▷반면 세마포어는 현재 공유 자원을 사용중인 대상뿐만 아니라 다른 프로세스 및 스레드도 unlock이 가능함
정리하자면...
세마포어는 카운터 변수값만큼 공유 자원에 해당 프로세스(또는 스레드)가 접근 가능
뮤텍스는 오직 하나의 프로세스(또는 스레드)가 접근 가능
세마포어는 현재 수행중인 프로세스가 아닌 다른 프로세스가 unlock이 가능
뮤텍스는 lock을 획득한 프로세스가 반드시 unlock을 해야 다른 프로세스가 접근 가능
- 운영체제로부터 자원을 할당받는 작업의 단위 - 메모리에 적재되어 실행되고 있는 프로그램 → 하나의 프로그램에서는 여러개의 프로세스 실행 가능 ex. 메모장이라는 프로그램을 여러 번 동작시키면, 여러개의 메모장(프로세스)이 실행됨 - 프로세스 메모리 구조 ○ code(text) 영역 : 실행할 프로그램의 코드 ○ data 영역 : 전역 변수, 정적 변수 담기는 영역 ○ stack 영역 : 지역 변수, 매개변수같은 임시적인 데이터들 담기는 영역 ○ heap 영역 : 런타임시 동적으로 메모리 할당받는 영역
2. PCB에 저장되는 프로세스 정보 (Process Metadata)
- Process ID : 프로세스 고유 식별 번호 (PID : Process Identification Number) - Process State : 프로세스의 상태 - 생성(create), 준비(ready), 실행(running), 대기(waiting), 완료(terminated) - Process Priority (프로세스 우선순위) - Program Counter : 프로세스가 다음에 실행할 명령의 주소를 가리킴 (CPU가 해당 값을 통해 프로세스의 명령을 수행) - Process Register : 프로세스의 레지스터 상태를 저장하는 공간 - Pointer : 부모/자식 프로세스에 대한 포인터 - 메모리 관리정보, 프로세스 계정정보, 입출력 상태정보 등등
정리하자면.. 프로그램 실행 → 프로세스 생성 → 프로세스 주소공간(메모리구조)에 코드, 데이터, 스택 생성 → 프로세스의 메타데이터들이 PCB에 저장
*메타데이터란? 데이터에 대한 데이터 (ex. 파일생성날짜, 시간, 파일생성된 위치, 수정일자, 파일크기 등)
3. PCB가 필요한 이유?
CPU에서는 프로세스 상태에 따라 교체작업이 이루어짐 (for 문맥교환 - 아래에서 설명)
→ 프로세스는 CPU가 처리하던 작업의 내용들을 자신의 PCB에 저장하고, 다음에 다시 CPU를 점유하여 작업을 수행해야 할 때 PCB로부터 해당 정보들을 가져와 하던 작업을 마저 진행
4. PCB는 어떻게 관리되는지?
- Linked List (연결리스트) 형태로 관리 - PCB List Head에 PCB들이 생성될때마다 붙게됨 - 주소값으로 연결이 이루어져있는 연결리스트
Running 상태 (수행 중)의 프로세스 정보는 CPU 레지스터에 저장됨
따라서 수행중인 프로세스를 변경할 때, CPU의 레지스터 정보가 변경되는 것을 Context Switching (문맥교환)이라고 함
+레지스터란? - 레지스터(Register)에도 다양한 종류가 있는데, 이 글에 해당하는 건 CPU 레지스터로, CPU 내부에서 처리할 명령어나 연산의 중간 결괏값 등을 일시적으로 저장하는 기억장치를 의미함
- 레지스터는 메모리 계층의 최상위에 위치하며, 간단하게는 가장 빠른 속도로 접근 가능한 메모리 정도로 기억하자.
실제 컴퓨터에서 데이터를 영구적으로 저장하기 위해서는 하드디스크에 저장하고, 임시적으로는 메모리(RAM)에 저장함
메모리(RAM)와 하드디스크에 데이터를 보내기 위해선, 이들에 대한 주소와 명령의 종류를 저장할 수 있는 기억공간이 하나 더 필요
→ 이런 역할들을 하는것이 CPU 옆에 붙어있는 레지스터
Context Switching (문맥교환)
1. 문맥교환이란?
- 현재 CPU가 실행하고 있는 프로세스 정보를 `문맥` 이라고 함 → 이를 교환하는 행위가 문맥 교환(Context Switching)
- 현재 실행 중인 프로세스 정보를 담고 있는 CPU 레지스터의 내용이 다음 실행할 프로세스의 정보로 변경되는 것을 의미
- 위에서 설명했던 PCB가 필요한 이유는 바로 Context Switching (문맥교환)을 위해서
2. Context Switching(문맥교환)이 필요한 이유
만약 컴퓨터가 매번 하나의 Task만 처리할 수 있다면, 다음 Task 처리를 위해 현재 Task가 끝날 때까지 기다려함
→ 반응속도가 매우 느리고 사용하기 불편
컴퓨터가 멀티태스킹을 통해 빠른 반응속도로 응답하며, 다양한 작업들이 실시간으로 처리되는 것처럼 보여지는 이유는 Context Switching이 이루어지고 있기 때문
3. Context Switching 시나리오
EX)
1. 프로세스 A에서 인터럽트 발생
2. A의 현재 상태 정보를 PCB에 저장
3. A를 대기 상태로 돌리고 프로세스 B를 실행 상태로 전환
4. B의 PCB에서 프로세스 상태 정보가 CPU에 재로딩
5. B가 원하는 동작을 모두 수행
6. B의 현재 상태 정보를 PCB에 저장
7. B를 대기 상태로 돌리고 A를 실행 상태로 전환
8. A의 PCB 정보를 기반으로 실행 재개
*인터럽트란?
프로그램을 실행하는 도중 예기치 않은 상황이 발생할 경우 현재 실행중인 작업을 중단하고 발생된 상황을 처리한 후 다시 작업을 복귀하는 것
정리하자면..
문맥교환은 프로세스가 Ready → Running , Running → Ready , Running → Block 등등 처럼 상태 변경 시에 발생하는 것