Chapter03 프로세스와 스레드
3.1 프로세스의 개요
3.1.1 프로세스의 개념
프로그램은 (보조)저장장치에 저장된 정적인 상태의 코드이며, 프로세스는 메모리에 올라온 동적인 상태 이다.
3.1.3 프로그램에서 프로세스로의 전환.
프로세스 제어 블록(PCB) 커널에서 관리하는, 특정 프로세스에 대한 다양한 정보가 담겨 있는 자료구조. 프로그램이 프로세스가 되러면, 프로그램이 메모리에 올라오면서 커널이 PCB를 생성해야 프로세스가 된다.
- 프로세스 = 프로그램 + PCB
PCB에 저장되는 중요한 정보 세가지는 아래와 같다.
- 프로세스 구분자 : 프로세스의 PID, 부모자식 프로세스 PID
- 메모리 관련 정보 : 프로세스가 메모리의 어느 주소에 올려져 있는지에 대한 정보. 경계/한계 레지스터도 포함.
- 각종 연산 중간값 : 프로그램 카운터(다음실행 명령) 및 연산중인 값들이 저장됨.
- 포인터 : 대시상태 프로세스들의 PCB는 큐 형태로 관리된다. 따라서 다음 PCB를 가르키는 포인터 또한 PCB에 저장된다.
3.1.4 프로세스의 상태
상태
- 생성상태 : 프로세스가 메모리에 올라오고 PCB가 생성된 상태.
- 준비상태 : 프로세스들이 CPU를 사용할수 있을때까지 대기하는 생태. 우선순위가 있다.
- 자기 순서가 되면 실행상태가 된다(dispatch(PID))
- 실행상태 : 일정시간동안 프로세스가 CPU 점유권을 가진 상태. 실행상태의 프로세스 개수는 CPU(코어?)개수와 1:1이다.
- 특정 시간(time slice)이후 다시 준비상태가 된다(timeout(PID)).
- timeout 이전에 프로세스 종료시 완료상태가 된다(exit(PID)).
- I/O 요청 필요 및 인터럽트가 걸리면 대기상태로 전환된다.(block(PID)).
- 대기상태 : I/O 및 인터럽트시 해당 요청이 언제 처리될지 모르므로 대기중으로 옮겨긴다.
- 요청 처리시 인터럽트가 발생하여 다시 준비상태 큐로 이동한다(wakeup(PID)).
- 완료상태 : 코드 및 사용한 데이터를 메모리에서 삭제하고, PCB를 폐기함. 이때 비정상적인 종료(abort)의 경우 강제 종료 직전 메모리상태를 저장장치로 옮김(core dump).
대부분의 프로세스는 위의 5가지 상태를 가지며, 이를 활성상태라고 통칭한다. 이외의 상태는 휴식상태, 보류상태가 있다. 특히 보류상태의 프로세스는 메모리 밖의 스왑영역에 저장된다.
3.2 문맥 교환
이미지 출처 : stack overflow
문맥 교환의 의미와 절차 문맥교환이란 실행상태의 프로세스를 변경하는 것으로, 현재의 상태를 실행중이던 PCB에 저장하고 이를 다음것으로 변경하는 것이다.
위의 사진은 P_0에서 P_1으로 문맥교환이 있어났다가 다시 P_0으로 문맥교환이 일어나는 상황이다.
- P_0이 실행중 타임아웃 등의 인터럽트가 발생한다.
- 문맥전환을 위해 PCB_0에 P_0의 상태를 저장한다.
- 기타 작업 후 PCB_1에서 P_1의 상태를 가지고 온 후 P_1을 실행한다.
- 다시 타임아웃 등의 인터럽트가 발생한다.
- 문맥전환을 위해 PCB_1에 P_1의 상태를 저장한다.
- 기타 작업 후 PCB_0에서 P_0의 상태를 가지고 온 후 P_0을 실행한다.
3.3 프로세스의 연산
3.3.1 프로세스의 구조
이미지 출처 : packtpub
UNIX시스템은 프로세스가 생성할때 각 프로세스에 4GB의 가상 메모리를 할당한다. 이때 User space는 3GB, Kernel space는 1GB가 할당된다.
- code영역 : 프로그램이 동작하는 코드(로직)이 저장되는 공간.
- 데이터영역 : 변수, 상수, 파일 등의 데이터가 저장되는 공간.
- heap영역 : 동적 데이터가 할당되는 영역으로, 런타임시 그 크기가 결정된다. 메모리 주소값에 의해서만 참조된다.
- stack영역 : 지연변수, 매개변수, 리턴값등 함수가 호출되고 종료될때 사용되었다 사라지는 값들이 stack형식으로 쌓여나가는 영역.
3.3.2 프로세스의 생성과 복사
프로그램이 실행될때 운영체제는 프로세스를 새로 생성하거나 복사한다.
프로세스 생성 과정
- 사용자가 프로그램을 실행한다.
- 운영체제는 프로그램을 메모리의 code영역에 넣고 PCB를 생성한다.
- 메모리에서 데이터 영역, 스택영역, 힙 영역 등의 공간(4GB)를 할당 한 후 프로세스를 실행된다.
3.3.2.1 fork() 시스템 호출
fork() 시스템 호출은 실행중인 프로세스로부터 새로운 프로세스를 복사하는 함수이다. fork()를 하면 자식프로세스를 만들어 원본(호출한 프로세스)과 동일한(PCB의 몇 부분을 제외) 프로세스가 복사된다.
바뀌는 부분
- PID
- 메모리 정보(복사하더라도 메모리에 저장된 위치는 다르므로)
- PPIC(Prent PIC), CPID(Child PID) fork 의 장점
- 프로세스 생성 속도가 빠름 : 프로그램을 보조저장장치에서 가져오는게 아니라 메모리 내의 것을 가져와서 복사하므로 빠름
- 추가 작업 없이 자원 상속 가능 : 부모 프로세스에서 사용하던 파일 등을 다시 열 필요 없이 그대로 사용 가능
- 시스템 관리가 효율적 : 자식 프로세스 종료시 부모프로세스가 이를 정리할 수 있다. 운영체제(최상위프로그램)에서 자원을 정리하는것에 비해 효율적이다.
3.3.3 프로세스의 전환
3.3.3.1 exec() 시스템 호출
exec() 시스템 호출은 프로세스의 구조와 관계만 그대로 두고 내용물을 바꾸는 명령. 프로세스간의 관계/표준입출력 등을 제외하고 완전히 다른 프로세스로 전환된다. exec()를 이용하면 이미 만들어진 프로세스 제어블록, 메모리영역, 프로세스간의 관계를 그대로 사용할수 있다.
3.3.4 프로세스의 계층구조
3.3.4.1 UNIX의 프로세스 계층구조
UNIX에서는 커널이 처음 메모리에 올라와서 부팅이 되면 커널 관련 여러 프로세스를 fork한다. 그 중 init프로세스는 전체 프로세스의 출발점이 되는 프로세스이다. 운영체제에 있는 모든 프로세스는 init의 자식이 되어 트리구조를 가지게된다.
3.3.4.2 프로세스 계층구조의 장점
- 계승을 통해 여러 작업을 효율적으로 차리 가능
- 용이한 자원 회수 -> 누가 자원을 회수해야 할지(부모 자식관계) 명확해짐.
3.3.4.3 고아프로세스와 좀비프로세스
- 고아프로세스 : 부모 프로세스가 자식프로세스보다 먼저 종료되는 경우. 자식프로세스가 종료되지 못하거나 자원이 회수되지 못하는 문제가 발생한다. -> wait 필요
- 좀비프로세스 : 자식프로세스가 종료되었음에도 그 자원을 회수하지 못한 경우. 자식이 이상하게 종료되거나, 반환(return, exit)을 하지 않는 경우 발생.