프로세스가 어떠한 리소스를 사용 중인지(할당받았는지)
할당받지 못했다면, 어떠한 리소스를 요청 중인지
프로세스의 State는 프로세스와 리소스 간의 Interaction에 의해 결정된다.
앱을 사용자가 터치 혹은 클릭하여 실행이 되면,
시스템 바운더리에 들어오게 된다.
커널에 등록되면서 프로세스가 "생성"되고, 커널 안에 프로세스를 위한 PCB가 생기고 초기값이 PCB에 저장된다.
즉 User의 Job/command 요청이 커널이 등록되는 상태이며, 프로세스가 생성되고, PCB가 할당된다.
이때 커널의 역할은 메모리 공간이 있는지 확인한다.
UNIX, 리눅스 시스템 기준에서 프로세스가 생성되는 것은 fork() 시스템 콜(새로운 프로세스를 생성하는 시스템 콜 함수)에 의해서 생성된다.
부모 프로세스가 자녀 프로세스를 fork 시스템 콜로 생성한다. 그 자녀가 자녀의 자녀를 시스템 콜로 생성한다. 따라서 프로세스의 계층 구조가 트리 형태로 형성된다.
프로세스가 생성되면서 컴퓨터 시스템에 제일 먼저 요청하는 자원은 '메모리 공간'이다. 하드디스크나 Storage에 가지고 있는 실행 파일을 메모리에 옮겨 놔야, CPU에서 메모리에 접근하면서 실행할 수 있기 때문이다. 실행코드와 데이터를 메모리로 옮긴 후, Heap이나 스택을 set up 시켜야 한다.
메모리 자원의 요청은 explit 하게 되지 않고, implicit하게 이뤄진다. 생성되자마자 커널이 '메모리부터 할당'해야 한다는 것을 인지 하는 것이다. 커널은 주기억장치의 빈 공간 메모리 공간이 있는지 확인 한다. 그리고 메모리 공간이 존재하면, 그 프로세스의 상태를 'create'상태에서 'ready' 상태로 옮긴다.
즉 프로세스 상태가 'ready'인 것은 메모리를 할당받았음을 의미한다. 이와 동시에 프로세스의 실행 코드와 데이터들이 메모리에 옮겨진다.
프로세스가 CPU를 제외한 모든 자원을 할당받고 있는 상태
CPU 자원이 할당되기를 기다리고 있는 상태. CPU 자원 할당되면 바로 실행 가능한 상태
Schedule(=dispatch)를 통해 ready에서 running 상태로 transition 될 수 있다.
만약 프로세스가 생성되었음에도 불구하고 메모리 공간이 부족해서 할당을 하지못하면, 그 프로세스는 생성되자마자 'suspended ready'상태가 된다. 이것은 메모리할당을 받지 못한 프로세스임을 의미한다.
즉 ready와 suspended ready의 차이점은 '프로세스가 메모리 할당을 받았는가'의 여부이다.
ready 상태에 있음에도 불구하고 커널에 의해 메모리를 빼앗기는 경우도 있다. 이러한 경우에도 ready에서 suspended ready 상태가 된다. (swap-out, suspended 된다.)
만약 suspended 상태였던 프로세스가 메모리를 할당 받으면, ready상태가 된다.(= resume = swap-in 된다.)
메모리를 할당받은 후 프로세스가 원하는 것은 'cpu자원'이다. CPU가 할당되면, 프로세스는 'running' 상태가 된다. 프로세스가 직접 cpu에서 자신의 프로그램을 실행중인 상태를 'running' 상태라고 한다.
만약 cpu에서 실행 중인 프로세스의 연산 양이 너무 많아서 10시간 정도 소요된다면, 다른 프로세스도 많은데 한 프로세스가 독점하면 다른 프로세스는 모두 기다려야 한다. 이는 시스템 성능상 좋지 않기 때문에, 한 프로세스가 cpu를 사용할 수 있는 시간에 제한을 둔다. (='Time Slice = Time Quantum)
따라서 사용 시간이 다 되어서 반납을 하는 과정을 'time runout', preemption(선점) 이라고 한다. preemption은 현재 running중인 프로세스로부터 cpu를 빼앗는 것을 의미한다. 이때 다시 cpu에서 할당되면 running 상태가 되고, 또 빼앗기면 ready 상태가 된다.
프로세스가 CPU까지 할당 받고 있는 상태. CPU에서 해당 프로세스 프로그램 코드가 실행중인 상태.
모든 자원을 갖고 있는 상태
Time quantum으로 인해/더 높은 우선순위의 프로세스가 ready 상태에 나타났을 때, Running 상태에서 Ready 상태로 쫓겨나는 preemption이 일어날 수 있다.
Running 상태에서 스스로 I/O 요청 등으로 인해 Asleep 상태로 Transition 될 수 있다.
프로세스가 CPU를 사용하던 도중 입출력을 하고 싶을 때 입출력 장치에 가야 하므로 (키보드, 마우스 등) 입출력을 위해 프로세스가 먼저 CPU를 두고 나온다.
이 때 CPU를 반납하고, 입출력장치를 사용하거나 요청(I/O system call)한 상태 = asleep (blocked) 상태가 된다. running에서 asleep 상태가 되는 과정을 'sleep(block)'이라고 한다. 입출력장치 외에 다른 경우일 수도 있지만 대부분 입출력장치와 관련된 경우들이다.
running 에서 ready로 가는 것은 '비자발적'이고, running에서 asleep은 '자발적'이다.
입출력 과정이 모두 끝나면 I/O 디바이스가 CPU에 인터럽트를 건다(하드웨어적으로) 소프트웨어적으로 보면 즉 I/O 디바이스 컨트롤러에서 커널에 인터럽트를 거는 것이다. 그리고 인터럽트 핸들링이 진행된다.
인터럽트 핸들링 과정에서, 입출력이 끝나면 asleep 상태에서 ready 상태로 가서 기다리고, cpu가 할당되기까지 기다리게 할 수 있다.
asleep에서 바로 running으로 가는 transition은 허락되지 않는다. cpu를 할당하는 스케줄링은 ready 상태들의 프로세스들을 대상으로 하는 것이지, sleep 상태의 프로세스들을 대상으로 하지 않기 때문이다.
프로세스가 CPU가 아닌 다른 자원을 요청하고, 그 자원의 사용이 끝나기를 기다리고 있는 상태.
CPU 자원은 내놓고, 다른 자원의 사용이 마무리되기를 기다리고 있는 상태(입출력이 끝났다는 Signal(=event)자원이 오기를, 입출력 자원이 할당되기를)
다른 자원의 요청은 시스템 콜로 이루어짐
자원의 사용이 모두 끝나면, Wakeup 되어 asleep상태에서 ready 상태가 된다.
ready 상태에서와 마찬가지로, asleep 상태도 메모리를 할당받고 있는 상태인데, 커널이 메모리 공간 확보를 위해서 메모리에서 쫓겨낼 수 있따. 이 경우 swap-out 되어서, suspended-blocked 상태가 된다.
다시 메모리를 돌려 받으면 swap-in이 되어 asleep 상태로 돌아온다.
suspended blocked 상태에서 입출력이 끝나게 되면, 입출력이 끝났는데 메모리를 뻇긴 상태이기 때문에 wakeup이 되어서, suspended blocked -> suspended ready 상태가 된다. suspended blocked에서 바로 ready 상태가 될 수는 없다 (메모리가 없기 때문에)
프로세스가 running을 하다가 종료되면, exit을 하여 'terminated' 종료 상태가 된다. 이렇게 되면 할당 받은 모든 자원들을 반납한다.(메모리, 오픈했던 파일들, 디바이스, 소프트웨어 하드웨어 자원들) 단, PCB의 일부 정보만 남긴다. PCB의 일부 정보까지 커널이 Accounting 목적으로 활용하고 나면 PCB 정보도 사라지면서 완전히 사라진다.
created와 terminated 상태는 오래 지속되지 않는 (잠깐 지나가는) 상태로, transient 상태이다.
프로세스는 종료된 상태
모든 자원들은 반납된 상태
PCB의 일부 정보만 가지고 있는 상태
Running 상태에서 프로세스가 exit() system call을 하면, 프로세스가 terminated 상태가 된다. (Main 함수에서 return을 하게 되면)
[참고]
컴퓨터 시스템은 하드디스크 등 storage 일부를 swap device로 설정해 두고, 이 영역을 메모리에서 쫓겨나는 프로세스들의 프로그램 코드/스택/힙 등 데이터를 저장하는 용도로 사용한다.