[OS] 프로세서(processor), 프로그램(program)과 프로세스(process), 스레드(Thread)
개요
이번 포스팅에서 정리할 내용은 아래와 같은 구조를 머릿속에 넣고, 이해하는 것이 좋다.
프로그래밍을 하면서 자주 들었지만, 확실하게 잡지 않으면 헷갈리는 개념. 그러나 너무 중요한 기본 개념을 이번 포스팅을 통해 정리하고 자주 들여다보자!
OS 과목을 수강한 컴퓨터공학 관련 학부생이라면 프로세스와 스레드에 대한 개념은 익히 들어왔을 것이다. 여기서 컴퓨터 구조 관련 강의를 같이 들으면 좋은데.. 컴퓨터구조에서는 HW 측면에서 스레드에 대해 다루기 때문이다.
이처럼, 우리가 중요하게 다루는 Thread라는 개념은 SW/HW 측면 두 가지에서 정의할 수 있다.
먼저, HW 측면에서 컴퓨터가 작업을 어떻게 처리하는지, 무엇으로 정의하는지 알아보자.
프로세서(processor)
CPU는 컴퓨터 자원을 처리 및 가공하는 대표적인 프로세서(processor)다.
- 듀얼 프로세서: CPU 2개 운용
- 멀티 프로세서: 다중 cpu 운용
CPU core는 cpu가 연산하는 핵심적인 부분으로, CPU의 성능을 판단하는 중요한 기준 중 하나다.
CPU의 스레드(Thread)
cpu 내부에서 연산을 수행하는 가장 작은 작업 단위다.
- cpu core는 기본적으로 1개의 스레드를 보유한다.
- intel의 하이퍼스레딩 기술이 도입됨에따라 2개 이상의 스레드를 지원할 수 있다.
프로그램
쉽게 말해서 노트북에 저장된 소스코드 파일들을 말한다.
실행되지 않은 상태에서는 단순히 파일이 저장장치에만 존재한다.
프로세스
- 실행중인 프로그램의 인스턴스다.
- 프로그램이 실행되면 OS의 커널이 프로세스를 생성하고, PID라는 고유 식별자와 메모리공간, 프로그램 리소스가 할당된다.
프로세스의 구조
- Stack: 지역변수, 함수 호출 담당
- Heap: 런타임단계에서 할당되고, 사용자에 의해 할당/해제되는 관리가능한 영역이다. ⇒ 동적 메모리 할당
- Data: 컴파일 단계에서 할당. bss와 data, 정적 및 전역 변수
- .bss: 초기화없이 선언만 되어있는 전역변수가 저장되는 공간
- .data: 초기화된 전역변수/전역상수가 저장되는 공간
- Text: 소스 코드들을 기계어로 변환한 값들이 저장되는 공간이다.
*컴파일 타임: 소스파일이 실행파일로 만들어지는 시간 ⇒ build 명령어 + jar로 만들기
*런타임: 실행파일이 실행되어 종료되기까지의 시간 ⇒ jar 파일을 배포해서 사용
왜 스택에 지역변수가 저장되는가?
지역변수의 생명주기는 함수에 종속된다. 함수가 호출될 때, 이 함수가 실행될 동안 지역변수는 존재하고 함수가 종료되면 메모리에서 없어진다.
함수는 왜 스택을 사용하는가?
재귀 함수의 구조를 떠올려보자. 함수는 호출된 역순으로 돌아가야 하므로 stack의 자료구조를 활용하면 용이하다.
프로세스를 실행했을 때, 프로세스 구조(stack-heap-data-text)의 변화는 ?
*구두로 설명해보기
PCB(Process Control Block)
프로세스의 상태를 기록하는 커널의 자료구조다.
프로세스의 ID, 상태, PC counter, 스케줄링 정보 등이 담겨있다. TCB(Task Control Block, 작업 제어 블록)이라고도 한다.
프로세스의 상태
커널 내에는 준비 큐, 대기 큐, 실행 큐 등의 자료구조가 있으며, 커널은 이것들을 이용하여 프로세스의 상태를 관리한다.
프로세스가 만들어지고 시스템에 존재하는 동안, 여러 사건들에 의해 프로세스는 상태 변화를 거친다.
- 실행(Running): 프로세스가 프로세서를 차지하여 명령어들을 실행
- 준비(Ready): 프로세스가 프로세서를 사용하고 있지 않지만, 언제든지 사용할 수 있는 상태
- event wait: 외부 리소스를 기다리거나, I/O 작업이 필요할 때
- event occurs: 프로세스는 생성되면 CPU Schedular라는 Queue에 들어가서, 실행이 될 때까지 기다린다.'
프로세스간 통신
프로세스는 고유의 메로리를 갖고 있기에, 서로 공유 자원을 통해 작업을 하려면 통신이 필요하다.
크게 두 가지로 나뉜다.
- IPC(Inter Process Commucation): 같은 시스템 내 프로세스 간의 통신
- RPC(Remote Procedure Calls: 다른 시스템이고, 네트워크를 통해 연결된 프로세스 간의 통신
Thread
하나의 프로세스 내에서 실제로 작업을 수행하는 단위다. 모든 프로세스는 하나 이상의 스레드를 갖는다. 프로세스의 시작과 동시에 생성 및 실행되는 스레드를 main thread라고 한다. (To-Do: user-level-thread와 Kernel-level-thread 내용 추가)
스레드는 자신만의 고유한 스레드 ID, 프로그램 카운터, 레지스터 집합, 스택을 가진다. 코드, 데이터, 파일 등 기타 자원은 프로세스 내의 다른 스레드와 공유한다. 이렇게 프로세스의 자원을 공유하면서 프로세스 실행 흐름의 일부가 되어, 전체 프로세스 실행을 하게된다. CPU 작업의 최소 단위는 바로 이 쓰레드다.
OS 관점에서의 작업의 최소 단위는 프로세스다. 프로그램이 실행되면 실행을 위해 리소스 할당하고, 메모리에 적재하는 등의 작업을 한다.
CPU 관점에서의 작업의 최소 단위는 쓰레드다. 쓰레드를 가동해서 일해야하니까. 쓰레드를 최소 단위로 잡고 전체 프로세스를 운영하게 된다.
멀티 프로세스와 멀티 스레드의 내용은 이 포스팅에서 다룬다. 여기서는 스레드 그 자체에 대해 이해하도록 하자.
스레드가 서로 공유하는 자원과 그렇지 않은 자원(프로세스 자원)
공유하는 것
- 주소 공간, 프로그램 코드
- heap, code(전역 변수)
- OS 자원(파일, I/O 장치)
⇒ 하나의 프로세스 내에서 스레드들이 공유하는 영역이 존재하기에, 시분할 부담이 적어진다.
⇒ 자원 공유로 인한 동기화 문제가 발생하기도 한다.
공유하지 않고, 자체적으로 갖는 것
- 레지스터, PC Counter
- 스레드는 cpu를 할당 받았다가 스케줄러에 의해 다시 선점 당한다. 그러므로 실행이 어디까지 되었는지 기억할 필요가 있다. 이러한 내용을 레지스터에 저장한다.
- 스택, SP(Stack Pointer) → 프로세스의 영역 중 stack만 독립적으로 할당 받는다.
- 스택은 지역변수와 함수 호출을 관리한다. 스레드는 자체적으로 함수를 호출하고, 그에 따른 독립적은 실행을 하기 위해서 최소한의 조건으로 스택을 갖는다.