Operating System

[OS] Process : A Program in Execution

Sara.H 2020. 6. 27. 13:58

Process : A Program in Execution. 

프로세스를 간단히 정의하면 "실행중인 프로그램"이다. 이 정의에서 프로그램과 프로세스의 차이를 짐작할 수 있다. 프로그램은 수동적인 (Passive) 개체이다. 디스크에 저장되어있는 인스트럭션 파일 그 자체를 프로그램이라 부른다. 반면 프로세스는 Active 한 개체이다. Executable File이 메모리에 로드된 상태를 가리킨다. 

 

왜 굳이 프로세스라는 개념을 만들어 낸 것인가?

프로세스는 프로그램 설계, 구현의 단위로도 사용될 수 있고(Design Time Entity), 실행의 단위로도(Runtime Entity) 사용될 수 있다는 점에서 유용한 개념이다. 

 

Runtime Entity 로서의 프로세스 

프로세스는 Text Section (코드 영역)이외에도 다양한 것들을 포함한다. 프로세스에는 현재의 activity가 포함되어 있고, 이는 프로그램 카운터의 값과 프로세서의 레지스터 내용들로 표현된다. 또한 프로세스 스택을 갖고 있어, 이 안에 temporary data (매개변수, 리턴 어드레스, 지역변수 등)를 유지한다. 그리고 Data Section 에는 글로벌 변수들이 있다. Heap 이 있을 수 도 있는데 프로세스 런타임에 동적으로 할당되는 메모리들이다. 

 

1. Memory Context : 코드영역, 데이터영역, 스택영역, 힙영역 

2. Hardware Context : CPU Register, I/O Register 

3. System Context : 프로세스 테이블, 열린 파일 테이블, 페이지 테이블 

 

PCB : 운영체제는 프로세스에 대한 정보를 유지한다 

각 프로세스들은 운영체제에 의해서 Process Control Block 이라는 것으로 표현된다. 운영체제는 PCB에 자원을 할당해 필요한 정보, 프로세스 아이디 등을 유지한다. 여러개의 PCB를 하나의 테이블에 관리하며, 이 테이블을 Process Table 이라 부른다. Linux 시스템 에서는 PCB를 Doubly Linked List 로 구현하며, 현재 Running 중인 프로세스는 Current 라는 포인터로 가리킨다. 

 

PCB에 들어가 있는 정보들 

* Process State : 프로세스가 현재 New, Ready, Running, Waiting, Halted, ... 등 어떤 상태에 있는지에 대한 정보 

* Program Counter : 프로세스가 실행해야 할 다음 명령어의 주소를 가리키는 카운터 

* CPU Registers : 컴퓨터 구조에 따라서 레지스터들의 종류와 숫자가 다양할 수 있다. 레디스터 안에는 accumulator, index register, stack pointer, general-purpose register, condition-code information 등이 있다. 프로그램 카운터와 함께 이 정보들은 인터럽트가 일어나면 반드시 저장되어야 하고, 프로그램 수행이 재개할 때 다시 복원되어야 한다. 

* CPU-scheduling information : 프로세스 우선순위, 스케줄링 큐에 대한 포인터, 그리고 다른 많은 스케줄링 매개변수들을 포함한다. 

* Memory-management information : 운영체제가 사용하는 메모리 관리 시스템에 따라서 페이지 테이블 혹은 심볼테이블의 base, limit register 값들을 갖고 있을 수 있다. 

* Acconting Information : 사용된 CPU 시간과 실제 시간의 양, 시간 제한, 회계 번호, Job 또는 프로세스 넘버 등을 유지한다. 

* I/O status information : 프로세스에 할당된 I/O 디바이스들의 리스트, 열려있는 파일들의 리스트 등을 유지한다. 

 

 

프로세스 State

프로세스는 실행되면서 state 가 변화한다. 프로세스의 state 는 현재 프로세의 활동 상태에 따라서 구분된다. 프로세스는 다음 중 하나의 상태에 처할 수 있다. 

 

* New : 프로세스가 생성되는 중

* Running : 인스트럭션들이 수행되는 중 

* Waiting : 프로세스는 어떠한 이벤트가 일어나기를 기다리는 중이다. (I/O 완료 혹은 시그널 수신 등)

* Ready : 프로세스는 프로세서에 할당되기를 기다리는 중이다. (CPU 할당받는 것 기다리는 중)

* Terminated : 프로세스는 실행을 끝냈다. 

 

프로세스 State Transition 

프로세스의 lifecycle 은 New -> Ready -> Running -> Terminated ... 와 같은 상태의 전환들로 이루어진다. 물론 중간에 Waiting 상태에 처할 수 도 있다. 위의 Lifecycle 을 좀 더 구체적으로 설명해 보겠다. 

1. Ready : 프로세스가 생성이 되고 나면 CPU가 할당되기를 기다린다. 여러 프로세스들이 Ready Queue 에 들어가서 기다리게 되고, 이는 PCB (Process Control Block) 들의 링크드리스트로 구현되어 있다. 만약 프로세스가 이미 Running 상태에 있다가 Ready 상태로 바뀐다면 인터럽트가 발생하여서이다. 

2. Running : 프로세스에 CPU가 할당되면 Running 상태가 된다. 한 번에 하나의 프로세스만이 돌아가는 컴퓨터 에서는 한 시점에 Running 상태인 프로세스가 0개 혹은 1개 뿐이다. 

3. Waiting : Running 중에 wait() 등을 호출하여 어떠한 이벤트 처리를 기다리게 되면 Waiting 상태에 들어간다. 각 프로세스마다 기다리는 이유는 제각각이므로, 이유별로 Queue 를 만들어 대기열을 유지하여 이벤트 처리를 기다린다. 예를 들어 I/O 디바이스별로 큐를 구성하고, 원하는 I/O 이벤트가 발생하면 다시 Ready 상태가 된다. 

4. Terminated : Running 이 끝나면 Terminated 상태가 된다. 

 

시스템별로 더 구체화된 lifecycle 이 있을 수 있다. 예를 들어 리눅스의 경우 Zombie 상태의 프로세스가 존재한다. 

 

Process : A Program that performs a single "thread" of execution 

프로세스가 워드 프로세서 프로그램을 실행시킨다고 했을 때 단일 스레드의 명령어들이(Single thread of instruction) 실행되고 있는 것이다. 이와 같이 단일 스레드를 통한 프로세스의 제어는 (Single Thread of Control) 프로세스가 한 번에 하나의 태스크만을 수행하게끔 한다. 유저는 하나의 프로세스 안에서 글자를 입력함과 동시에 맞춤법 확인기를 실행시킬 수 없다. (두개의 task 를 서로 다른 두개의 프로세스에서 실행시켜야 함)

대부분의 현대 OS는 멀티스레딩을 지원하고, 이로서 한 번에 하나 이상의 task 를 하는 것이 가능해졌다. 멀티코어 시스템 에서는 여러개의 thread 들을 병렬처리 할 수도 있다. 스레드를 지원하는 시스템에서는 PCB에서 스레드에 대한 정보도 유지한다. 

 

리눅스에서의 프로세스 표현 

커널 소스코드 디렉토리 안의 `<linux/sched.h>` 파일에 있는 `task_struct` 로 PCB를 표현한다. 이 스트럭트는 프로세스를 표현하는 데 필요한 모든 정보들을 갖고 있다. 리눅스 커널 안에서는 모든 active 한 프로세스들이 task_struct 들의 이중연결리스트로 유지된다. 그리고 커널은 현재 실행중인 프로세스에 대한 포인터 (current) 를 유지한다. 

만약 커널이 특정 프로세스에 대한 state 를 변경하고 싶으면 `currnt -> state = new_state` 과 같이 상태를 변경할 수 있다.