✔️ 프로세스란 ?
- 메모리 영역에 올려 실행 중인 프로그램의 인스턴스(독립적인 개체)
- 컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램
- 하나의 프로세스는 반드시 하나 이상의 스레드를 가진다.
- 운영체제로 부터 시스템 자원을 할당받는 작업의 단위
- 시스템 자원
1) CPU 시간
2) 운영되기 위해 필요한 주소 공간
3) Code, Data, Stack, Heap의 구조로 되어 있는 독립된 메모리 영역
- 시스템 자원
✔️ 프로세스의 특징
- 프로세스는 각각 독립된 영역(Code, Data, Stack, Heap의 구조)을 할당 받는다.
- 기본적으로 프로세스당 최소 1개의 스레드(메인 스레드)를 가지고 있다.
- 각 프로세스는 별도의 주소 공간에서 실행되며, 한 프로세스는 다른 프로세스의 변수나 자료 구조에 접근할 수 없다.
- 한 프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간의 통신(IPC, Inter-Process Communication)을 사용해야 한다.
- 파이프, 파일, 소켓 등을 이용하는 방법
✔️ 프로세스의 메모리 영역
- Code 영역(Text 영역)
실행할 프로그램의 코드나 명령어들이 기계어 형태로 저장되는 영역이다.
CPU는 코드 영역에 저장된 명령어들을 하나씩 처리한다. 프로그램이 시작되고 끝날 때까지 메모리 영역에 유지
- Data 영역
코드에서 선언한 전역 변수와 정적 변수가 저장되는 영역
프로그램이 실행되면서 할당되고 종료되면서 해제한다.- 초기화된 데이터는 data 영역(ROM에 저장)
- 초기화되지 않은 데이터는 bss 영역 (RAM에 저장)
- Stack 영역
프로그램에 의해 사용되는 임시 데이터 영역
함수 안에서 선언된 지역변수, 매개변수, 리턴 값등이 저장된다. 함수 호출 시 기록되고 종료되면 해제된다.
메모리 주소는 높은 곳에서 낮은 곳의 방향으로 할당된다. - Heap 영역
프로그래머에 의해 할당되고 해제되는 영역
메모리를 동적으로 할당하고자 할 때 사용되는 메모리 영역
스택과 반대로 메모리 주소가 낮은 곳에서 높은 곳의 방향으로 할당된다.
구역을 나누어 저장하는 이유 ? 효율적인 메모리 사용을 위해
- 코드 Segment : 프로그램 소스 코드 저장
- 데이터 Segment : 전역 변수 저장
- 스택 Segment : 함수, 지역 변수 저장
데이터를 최대한 공유하여 메모리 사용량을 줄여야한다.
Code는 같은 프로그램 자체에서는 모두 같은 내용이기 때문에 따로 관리하여 공유한다.
Stack과 Data를 나눈 이유는 스택 구조의 특성과 전역 변수의 활용성을 위한 것이다.
프로그램의 함수, 지역변수는 스택에서 실행된다. 따라서 이 함수들 안에서 공통으로 사용하는 "전역 함수"는 따로 지정해두면 메모리를 아낄 수 있다.
✔️ 프로그램의 실행 순서
✔️ 프로세스에서 스레드로 (출현 배경)
스레드는 프로세스의 단점을 보완하기 위해 출현한 개념이다.
프로세스의 단점
1. 프로세스 간 Context Switching overhead
하나의 프로그램을 실행할 때는 여러개의 프로세스가 실행된다.
우리 눈에는 여러 프로세스가 동시에 실행되는 것처럼 보이지만 실제로 CPU는 프로세스 n개를 Context Switching 이라는 개념을 사용해 조금씩 번갈아가며 진행한다.
이렇게 반복이 많아지게 되면 CPU의 부담이 늘어나고 중복된 자원들이 비효율적으로 관리된다.
2. 프로세스 사이 통신의 어려움
프로세스들은 독립된 주소 공간을 가지므로 단순한 방법으로 서로의 메모리 공간을 접근할 수 없어 공유 메모리, 소켓 등을 이용해 접근해야 한다.
📌 Context Switching이란 ?
프로세스의 상태 정보를 저장하고 복원하는 일련의 과정
즉, 동작 중인 프로세스가 대기하면서 해당 프로세스의 상태를 보관하고, 대기하고 있던 다음 순번의 프로세스가 동작하면서 이전에 보관했던 프로세스 상태를 복구하는 과정을 말함
→ 프로세스는 각 독립된 메모리 영역을 할당받아 사용되므로, 캐시 메모리 초기화와 같은 무거운 작업이 진행되었을 때 오버헤드가 발생할 문제가 존재함
✔️ 스레드란 ?
- 프로세스 내에서 실행되는 여러 흐름의 단위
- 프로세스의 특정한 수행 경로
- 프로세스가 할당받은 자원을 이용하는 실행의 단위
- CPU 입장에서의 최소 작업 단위
✔️ 스레드의 특징
- 한 프로세스 내에서 별도의 Register와 Stack만 따로 할당받고 Code, Data, Heap 영역은 공유한다.
💡 다른 자원들은 공유하나 Stack만 분리해 사용하는 이유는 ?
LIFO (후입 선출)라는 스택의 특정과 연관된다.
Code와 Data, Heap 영역을 공유하는 것에는 큰 문제가 없지만, 프로세스가 섞인채 나오는 것을 방지하고 원활한 실행 흐름을 위해 Stack은 독립적으로 존재하게 된다.
- 기본적으로 하나의 프로세스가 생성되면 하나의 스레드가 같이 생성되며 이를 메인 스레드라고 한다. 스레드를 추가하지 않는 이상 모든 프로그램 코드는 메인 스레드에서 실행된다.
- 한 스레드가 프로세스 자원을 변경하면 다른 이웃 스레드(Sibiling thread)도 그 변경 결과를 즉시 볼 수 있다.
- 스레드 ID, PC(Program Counter), 레지스터 집합, 스택을 독립적으로 보유한다.
✔️ 멀티 프로세스와 멀티 스레드
멀티 프로세스란 ?
- 하나의 컴퓨터에 여러개의 CPU를 장착 -> 하나 이상의 프로세스들을 동시에 처리(병렬)
- 여러개의 프로세스가 같은 프로그램을 동시에 병렬처리 하는 것
장점
- 독립된 구조이기 때문에 안정성이 높다. (메모리 침범 문제를 OS 차원에서 해결한다.)
- 여러프로세스가 같이 작업하고 있기에 하나의 프로세스가 죽는다고 해도 문제가 확산되지 않는다.
- 구현이 비교적 간단하다.
단점
- Context Switching에서의 오버헤드
프로세스는 각각의 독립된 영역을 할당받기 때문에 프로세스 사이에서 공유하는 메모리가 없어 Context Switching이 발생하게 되면 캐시에 있는 모든 데이터를 모두 리셋하고 다시 캐시 정보를 불러와야 한다. - 프로세스 사이의 어렵고 복잡한 통신 기법(IPC)
프로세스는 각각의 독립된 메모리 영역을 할당받았기 때문에 하나의 프로그램에 속하는 프로세스들 사이의 변수를 공유할 수 없어 파이프, 소켓 등을 이용해야 한다. - 프로세스마다 각각의 독립된 메모리 공간을 할당해야 하므로 불필요한 메모리 사용량이 많다.
멀티 스레드란 ?
- 하나의 응용프로그램을 여러개의 스레드로 구성하고 각 스레드가 하나의 작업을 처리하도록 하는 것이다.
- 만약 단일 스레드로 네트워크나 데이터베이스 통신과 같은 긴 작업을 수행하는 경우 다른 작업을 처리할 수 없어 여러개의 스레드를 사용한다.
- Window, Linux 등 많은 OS들이 멀티 프로세싱을 지원하지만 멀티 스레딩을 기본으로 하고 있다.
장점
- 응답성이 좋다. 자식 스레드 중 하나가 오류 또는 긴 작업으로 중단되어도 프로그램이 계속적으로 동작한다.
- 시스템 자원 소모 감소 (자원의 효율성 증대)
프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리할 수 있다. - 시스템 처리량 증가 (처리 비용 감소)
스레드 간 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 줄어들게 된다.
스레드 사이의 작업량이 작아 Context Switching이 빠르다. - 간단한 통신 방법으로 인한 프로그램 응답 시간 단축
스레드는 프로세스 내의 Stack 영역을 제외한 모든 메모리를 공유하기 때문에 통신의 부담이 적다.
단점
- 스레드들은 부모 프로세스의 메모리 공간을 공유하는데 여러 스레드가 동일한 메모리 공간을 접근하면서 동기화 문제가 발생한다.
- 구현, 테스트, 디버깅이 어렵다.
- 스레드들 간의 별도 동기화 작업이 필요하며 교착상태가 발생하지 않도록 주의해야 한다.
- 자식 스레드 중 하나에 문제가 생기면 전체 프로세스에 영향을 미칠 수 있다.
- 다른 프로세스에서 스레드를 제어할 수 없다. (프로세스 밖에서 스레드 각각을 제어할 수 없다.)
멀티스레드의 동기화 (임계영역 문제)
스레드들은 부모 프로세스의 메모리 공간을 공유하는데 여러 스레드가 동일한 메모리 공간을 접근하면서 동기화 문제가 발생한다.
스레드들 간에 한번에 하나의 스레드만 공유자원에 접근하게 함으로써 동기화(임계영역) 문제를 해결할 수 있다.
임계영역 문제를 해결하기 위한 조건
1. 상호배제(Mutual Exclusion)
- 어떤 프로세스가 임계영역에서 실행중이라면 다른 프로세스들은 임계영역에서 실행될 수 없다.
2. 진행(Progress)
- 임계영역에서 실행 중인 프로세스가 없고 들어가야 하는 프로세스가 여러개있다면 어느 것이 들어갈지 적절히 선택해주어야 한다.
3. 한정된 대기(Bounded Waiting)
- 다른 프로세스의 기아 방지를 위해 한 번 임계 구역에 들어간 프로세스는 다음 임계구역에 들어갈 때 제한을 두어야 한다.
임계영역 문제의 해결책
1. Lock
- 하나의 스레드나 프로세스가 자원을 사용하고 있는 동안 잠궈서 다른 프로세스나 스레드가 접근을 못하게 하는 방식
- 하드웨어 기반의 해결책으로 임계영역에 접근하는 프로세스는 Lock을 획득하고 임계영역에서 빠져나오면서 Lock을 방출하는 방법으로 임계영역에 동시에 접근할 수 없게 한다.
2. Semaphore
- 소프트웨어 상에서 임계영역 문제를 해결하기위한 동기화 도구
- Computing Semaphore
- 공유자원의 개수를 나타낸다.
- 자원을 사용하면 세마포어가 감소하고 임계구역에서 빠져나오면 세마포어가 증가한다.
- Binary Semaphore(Mutex) : 0과 1의 값만 가능한 세마포어
3. Monitor
- 세마포어와 유사하지만 세마포어는 운영체제 단계에서 사용되는 반면 모니터는 프로그래밍 언어 수준에서 사용된다.
- 락의 설정, 해제를 알아서 처리해준다.
🔗참고
'CS > 운영체제' 카테고리의 다른 글
[운영체제] Process Management (0) | 2022.03.17 |
---|---|
[운영체제] PCB(Process Control Block) & Context Switching (0) | 2022.03.17 |
[운영체제] System Call (0) | 2022.03.14 |
[운영체제] 인터럽트(Interrupt) (0) | 2022.03.14 |
[운영체제] 운영체제란..? (0) | 2022.02.16 |
영차영차 성장 블로그
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!