프로세스와 스레드
프로세스란?
운영체제에서 프로세스는 하나의 작업 단위이다.
예) 사용자가 마우스를 더블클릭하여 프로그램을 실행하면 그 프로그램은 프로세스가 된다.
또 실행을 위해 메모리에 올라온 동적인 상태이기도 하다.
프로그램에서 프로세스로의 전환
프로그램과 프로세스의 관계
프로그램이 프로세스가 되었단 것은 운영체제로부터 프로세스 제어 블록(PCB)을 받았다는 의미이다.
프로세스가 종료된다는 것은 해당 프로세스 제어 블록이 폐기된다는 뜻이다.
프로세스 = 프로그램 + 프로세스 제어 블록
프로그램 = 프로세스 - 프로세스 제어 블록
프로세스의 상태
운영체제에서는 여러 가지의 이유로 프로세스의 상태가 변한다.
프로세스가 네 가지 상태

생성 상태: 프로세스가 메모리에 올라와 실행 준지를 완료한 상태이다.
준비 상태: 생성된 프로세스가 CPU를 얻을 때까지 기다리는 상태이다.
실행 상태: 준비 상태에 있는 프로세스 중 하나가 CPU를 얻어 실제 작업을 수행하는 상태이다.
완료 상태: 실행 상태의 프로세스가 주어진 시간 동안 작업을 마치면 진입하는 상태이다.
(프로세스 제어블록이 사라진 상태)
디스패치: 준비 상태의 프로세스 중 하나를 골라 실행 상태로 바꾸는 CPU 스케줄러의 작업이다.
타임아웃: 프로세스가 자신에게 주어진 하나의 타임 슬라이스 동안 작업을 끝내지 못하면
다시 준비 상태로 돌아가는 것이다.
프로세스의 다섯 가지 상태
프로세스는 생성, 준비, 실행, 완료라는 네 가지 상태만으로도 작업을 진행하는 데 큰 문자가 없으나, 운영체제의 효율성을 고려하여 한 가지 상태를 더 만들었다.

생성 상태
- 프로그램이 메모리에 올라오고 운영체제로부터 PCB를 할당받은 상태이다.
- 생성된 프로세스는 바로 실행되는 것이 아니라 준비 상태에서 자기 순서를 기다리며, PCB 도 같이 준비 상태로 옮겨진다.
준비 상태
- 실행 대기 중인 모든 프로세스가 자기 순서를 기다리는 상태이다.
- PCB는 준비 큐에서 기다리며 CPU 스케줄러에 의해 관리됨
- CPU 스케줄러가 어떤 프로세스 제어 블록을 선택하는 작업은 디스패치 명령으로 처리한다.
- CPU 스케줄러가 디스패치를 실행하면 해당 프로세스가 준비 상태에서 실행 상태로 바뀌어 작업이 이루어진다
실행 상태
- 프로세스가 CPU를 할당받아 실행되는 상태이다.
- 실행 상태에 있는 프로세스는 자신에게 주어진 시간, 즉 타임 슬라이스 동안만 작업할 수 있다.
- 그 시간을 다 사용하면 timeout(PID)가 실행되어 실행 상태에서 준비 상태로 옮겨진다.
- 실행 상태 동안 작업이 완료되면 exit(PID)가 실행되어 프로세스가 정상 종료된다.
- 실행 상태에 있는 프로세스가 입출력을 요청하면 CPU는 입출력 관리자에게 입출력을 요청하고 block(PID)를 실행한다.
- block(PID)는 입출력이 완료될 때까지 작업을 진행할 수 없기 때문에 해당 프로세스를 대기 상태로 옮기고 CPU 스케줄러는 새로운 프로세스를 실행 상태로 가져온다.
대기 상태
- 실행 상태에 있는 프로세스가 입출력을 요청하면 입출력이 완료될 때까지 기다리는 상태이다.
- 대기 상태의 프로세스는 입출력장치별로 마련된 큐에서 기다리다가 완료되면 인터럽트가 발생하고, 대기 상태에 있는 여러 프로세스 중 해당 인터럽트로 깨어날 프로세스를 찾는데 이것이 wakeup(PID)이다.
- wakeup(PID)로 해당 프로세스의 프로세스 제어 블록이 준비 상태로 이동한다.
완료 상태
- 프로세스가 종료되는 상태이다.
- 코드와 사용했던 데이터를 메모리에서 삭제하고 프로세스 제어 블록을 폐기한다.
- 정상적인 종료는 간단히 exit( )로 처리한다.
- 오류나 다른 프로세스에 의해 비정상적으로 종료되는 강제 종료를 만나면 디버깅하기 위해 종료 직전의 메모리 상태를 저장장치로 옮기는데 이를 코어 덤프(core dump)라고 한다.

휴식 상태와 보류 상태
프로세스의 상태는 활성 상태(생성, ㅈ누비, 실행, 대기, 완료) 외에 휴식 상태와 보류 상태라는 조금 특별한 경우도 존재한다.
휴식 상태
- 프로세스가 작업을 일시적으로 쉬고 있는 상태이다.
- 유닉스에서 프로그램을 실행하는 동중에 [Ctrl]+[Z] 키를 누르면 볼 수 있다.
- 종료 상태가 아니기 때문에 원할 때 다시 시작할 수 있는 상태이다.
보류 상태
- 프로세스가 메모리에서 잠시 쫓겨난 상태
- 프로세스는 다음과 같은 경우에 보류 상태가 됨
- 메모리가 꽉 차서 일부 프로세스를 메모리 밖으로 내보낼 때
- 프로그램에 오류가 있어서 실행을 미루어야 할 때
- 바이러스와 같이 악의적인 공격을 하는 프로세스라고 판단될 때
- 매우 긴 주기로 반복되는 프로세스라 메모리 밖으로 쫓아내도 큰 문제가 없을 때
- 입출력을 기다리는 프로세스의 입출력이 계속 지연될 때

프로세스 제어 블록
프로세스를 실행하는 데 필요한 중요한 정보를 보관하는 자료 구조이다.
프로세스는 고유의 프로세스 제어 블록을 가진다.
프로세스 생성 시 만들어져서 프로세스가 실행을 완료하면 폐기한다.

프로세스 제어 블록 구성
포인터: 준비 상태나 대기 상태의 큐를 구현할 때 사용
프로세스 상태: 프로세스가 현재 어떤 상태에 있는지를 나타내는 정보( 생성, 준비, 실행, 대기..)
프로세스 구분자: 운영체제 내에 있는 여러 프로세스를 구현하기 위한 구분자 ->pid
프로그램 카운터: 다음에 실행될 명령어의 위치를 가리키는 프로그램 카운터의 값
프로세스 우선순위: 프로세스의 실행 순서를 결정하는 우선순위
각종 레지스터 정보: 프로세스가 실행되는 중에 사용하던 레지스터의 값
메모리 관리 정보: 프로세스가 메모리의 어디에 있는지 나타내는 메모리 위치 정보, 메모리 보호를 위해 사용하는
경계 레지스터 값과 한계 레지스터 값 등
할당된 자원 정보: 프로세스를 실행하기 위해 사용하는 입출력 자원이나 오픈 파일 등에 대한 정보
계정 정보: 계정 번호, CPU 할당 시간, CPU 사용 시간 등
부모 프로세스 구분자와 자식 프로세스 구분자: 부모 프로세스를 가리키는 PPID와 자식 프로세스를 가리키는 CPID 정보
문맥 교환
의미
CPU를 차지하던 프로세스가 나가고 새로운 프로세스를 받아들이는 작업이다.
실행 상태에서 나가는 프로세스 제어 블록에는 지금까지의 작업 내용을 저장하고, 반대로 실행 상태로 들어오는 프로세스 제어 블록의 내용으로 CPU가 다시 세팅한다.
절차

프로세스의 구조
코드 영역 | - 프로그램의 본문이 기술된 곳 - 프로그래머가 작성한 코드가 탑재되며 탑재된 코드는 읽기 전용으로 처리됨 |
데이터 영역 | - 코드가 실행되면서 사용하는 변수나 파일 등의 각종 데이터를 모아놓은 곳 - 데이터는 변하는 값이기 때문에 이곳의 내용은 기본적으로 읽기와 쓰기가 가능 |
스택 영역 | - 운영체제가 프로세스를 실행하기 위해 부수적으로 필요한 데이터를 모아놓은 곳 - 프로세스 내에서 함수를 호출하면 함수를 수행하고 원래 프로그램으로 되돌아올 위치를 이 영역에 저장 - 운영체제가 사용자의 프로세스를 작동하기 위해 유지하는 영역이므로 사용자에게는 보이지 않음 |
프로세스의 생성과 복사
fork() 시스템 호출의 개념
실행 중인 프로세스로부터 새로운 프로세스를 복사하는 함수이다.
실행 중인 프로세스와 똑같은 프로세스가 하나 더 만들어진다.
fork() 시스템 호출의 동작 과정
fork( ) 시스템 호출을 하면 프로세스 제어 블록을 포함한 부모 프로세스 영역의 대부분이 자식 프로세스에 복사되어 똑같은 프로세스가 만들어진다.
단, 프로세스 제어 블록의 내용 중 다음이 변경된다
- 프로세스 구분자
- 메모리 관련 정보-프로세스의 저장 위치
- 부모 프로세스 구분자와 자식 프로세스 구분자
fork() 시스템 호출의 장점
프로세스의 생성 속도가 빠르다.
추가 작업 없이 자원을 상속할 수 있다.
시스템 관리를 효율적으로 할 수 있다.
exec() 시스템 호출의 개념
기존의 프로세스를 새로운 프로세스로 전환(재사용)하는 함수이다.
- fork( ): 새로운 프로세스를 복사하는 시스템 호출
- exec( ): 프로세스는 그대로 둔 채 내용만 바꾸는 시스템 호출
exec() 시스템 호출의 동작 과정
- exec( ) 시스템 호출을 하면 코드 영역에 있는 기존의 내용을 지우고 새로운 코드로 바꿔버린다.
- 데이터 영역이 새로운 변수로 채워지고 스택 영역이 리셋한다.
- 프로세스 제어 블록의 내용 중 프로세스 구분자, 부모 프로세스 구분자, 자식 프로세스 구분자, 메모리 관련 사항 등은 변하지 않지만 프로그램 카운터 레지스터 값을 비롯한 각종 레지스터와 사용한 파일 정보가 모두 리셋된다.
프로세스의 계층 구조
고아 프로세스
프로세스가 종료된 후에도 비정상적으로 남아 있는 프로세스 중 부모 프로세스가 자식보다 먼저 죽는 경우 발생한다.
좀비 프로세스
자식 프로세스가 종료되었는데도 부모 프로세스가 뒤처리를 하지 않을 때 발생한다.
고아 프로세스나 좀비 프로세스가 많아지면 자원이 낭비되기 때문에 효율적인 운영에 방해가 된다. 따라서 운영체제는 주기적으로 반환되지 못한 자원을 회수해야 한다.
C 언어의 exit( ) 또는 return( ) 문은 자식 프로세스가 작업이 끝났음을 부모 프로세스에 알려줌으로써 부모 프로세스는 미루어 왔던 자원을 정리하거나 자식 프로세스와 동기화를 할 수 있다.
스레드의 정의
CPU 스케줄러가 CPU에 전달하는 일 하나
CPU가 처리하는 작업의 단위는 프로세스로부터 전달받은 스레드
- 운영체제 입장에서의 작업 단위는 프로세스
- CPU 입장에서의 작업 단위는 스레드
프로세스와 스레드의 차이
프로세스끼리는 약하게 연결되어 있는 반면 스레드끼리는 강하게 연결되어 있다
멀티 스레드
프로세스 내 작업을 여러 개의 스레드로 분할함으로써 작업의 부담을 줄이는 프로세스 운영 기법
멀티 태스킹
운영체제가 CPU에 작업을 줄 때 시간을 잘게 나누어 배분하는 기법
멀티 프로세싱
CPU를 여러 개 사용하여 여러 개의 스레드를 동시에 처리하는 작업 환경
CPU 멀티 스레드
한 번에 하나씩 처리해야 하는 스레드를 파이프라인 기법을 이용하여 동시에 여러 스레드를 처리하도록 만든 병렬 처리 기법
멀티 스레드의 구조와 예
멀티태스킹의 낭비 요소
fork( ) 시스템 호출로 프로세스를 복사하면 코드 영역과 데이터 영역의 일부가 메모리에 중복되어 존재하며, 부모-자식 관계이지만 서로 독립적인 프로세스이므로 이러한 낭비 요소를 제거할 수 없다.
멀티태스킹과 멀티스레드의 차이
fork( ) 시스템 호출로 여러 개의 프로세스를 만들면 필요 없는 정적 영역이 여러 개가 된다.
멀티스레드는 코드, 파일 등의 자원을 공유함으로써 자원의 낭비를 막고 효율성 향상한다.
멀티 스레드의 장단점
멀티 스레드의 장점
- 응답성 향상
- 자원 공유
- 효율성 향상
- 다중 CPU 지원
멀티스레드의 단점
모든 스레드가 자원을 공유하기 때문에 한 스레드에 문제가 생기면 전체 프로세스에 영향을 미친다.
인터넷 익스플로러에서 여러 개의 화면을 동시에 띄웠는데 그중 하나에 문제가 생기면 인터넷 익스플로러 전체가 종료된다.
멀티스레드 모델
커널 스레드와 사용자 스레드가 있다.
- 커널 스레드 : 커널이 직접 생성하고 관리하는 스레드
- 사용자 스레드 : 라이브러리에 의해 구현된 일반적인 스레드