🧁
운영체제와 정보기술의 원리 - CH5. 프로세스 관리
October 13, 2021
다음은 반효경 교수님의 ‘운영체제와 정보기술의 원리’ CH5. 프로세스 관리를 읽고 정리한 내용입니다 🙌
🌩 1. 프로세스의 개념
- 프로세스란 실행 중인 프로그램이다.
- 프로세스는 CPU를 획득해서 코드를 수행하고 CPU를 반환하고 입출력 작업을 수행하기도 한다.
- 프로세스 문맥 (context) - 프로세스가 현재 어떤 상태에서 수행되고 있는 규명하기 위해 필요한 정보
- 여러 프로세스가 CPU를 사용하면서 중간에 CPU를 다른 프로세스에게 넘겨야 한다.
- 이때 다시 이어서하기 위한 필요 정보가 있는데 그것을 프로세스 문맥이라고 한다.
- 프로세스의 주소 공간, 레지스터의 값, 시스템 콜을 통해 커널에서 수행한 일의 상태, 프로세스에 대해 커널이 관리하고 있는 여러 정보들을 포함한다.
- 프로세스 문맥은 3가지로 나뉜다.
- 하드웨어 문맥
- CPU의 수행 상태를 나타낸다.
- 프로그램 카운터 값, 각종 레지스터에 저장하고 있는 값들이다.
- 프로세스의 주소 공간
- 코드, 데이터, 스택으로 이루어진 프로세스의 독자적인 주소 공간이다.
- 커널상의 문맥
- PCB 와 커널스택이 프로세스에 대한 커널에 위치하는 자료구조이다.
- 하드웨어 문맥
🌩 2. 프로세스의 상태
- 실행(running), 준비(ready), 봉쇄(blocked, wait, sleep)
- 실행 - 프로세스가 CPU를 봉하고 기계어 명령을 실행하고 있는 상태
- 실제로 실행 상태에 있는 프로세스는 매 시점 하나이다.
- 준비 - 프로세스가 CPU만 보유하면 명령을 실행할 수 있지만 CPU를 획득하지 못한 상태
- 봉쇄 - CPU를 할당 받더라도 명령을 실행할 수 없는 프로세스의 상태
- 입출력 작업이 진행 중인 경우
- 프로세스의 상태를 나누는 이유는 컴퓨터의 자원을 효율적으로 관리하기 위해서다.
- 이외에도 시작과 종료 상태가 있다.
- 시작 - 프로세스에 대한 자료구조는 생성 되었지만 메모리 획득을 승인받지 못한 상태
- 종료 - 프로세스가 종료되었으나 운영체제가 관련된 자료구조를 완전히 정리하지 못한 상태
- 프로세스는 앞의 상태 중 하나에 머물러 있으며, 시간의 흐름에 따라서 변한다.
프로세스의 상태 흐름
- 프로세스의 문맥이 교환되는 것을 Context switching이라고 한다.
- 한 프로세스가 진행 중일 때 타이머 인터럽트가 발생한다.
- 타이머 인터럽트 처리루틴에 따라서 현재 진행중이던 프로세스의 문맥을 저장하고 준비 상태의 프로세스 중 하나를 선택한다.
- 본래 수행 중이던 프로세스를 준비 상태로 내리고 새로운 프로세스가 실행 상태가 된다.
- 실행할 프로세스에 대한 문맥을 세팅한다.
- CPU 디스패치(dispatch) - 준비 상태에 있는 프로세스 중 CPU를 할당받을 프로세스를 선택하고 제어권을 넘겨받는 과정
입출력을 요청한 프로세스의 상태변화
- 디스크 입출력은 오랜 시간이 걸리기 때문에 이 시간동안 해당 프로세스는 봉쇄 상태가 된다.
- 그 동안 준비 상태의 프로세스 들을 CPU 스캐줄러가 선정해 CPU를 할당하고 해당 프로세스는 실행 상태로 변경이 된다.
- 입출력 요청 프로세스는 디스크 입출력 큐에 대기하다가 디스크 컨트롤러부터 서비스를 받는다.
- 완료 후 디스크 컨트롤러가 CPU에게 인터럽트로 입출력 완료를 알린다.
- CPU는 인터럽에 대한 루틴을 수행한다.
- 이때 당시에 CPU에서 진행중이던 프로세스가 사용자모드에서 커널 모드로 바뀐다.
- 관련이 없는 프로세스지만 해당 프로세스 중 인터럽트가 발생했기 때문에 해당 프로세스가 커널 모드로 진입했다고 판단하도록 한다.
- 봉쇄 상태의 프로세스는 준비 상태로 바뀌고, 로컬버퍼에 있는 내용을 메모리로 이동시키는 업무를 수행한다.
- 인터럽트 처리 루틴이 완료되면 직전 프로세스가 다시 수행되거나 입출력 완료 프로세스의 우선순위가 높다면 해당 프로세스가 수행된다.
🌩 3. 프로세스 제어블록
- Process Control Block - 운영체제가 시스템 내의 프로세스들을 관리하기 위해 프로세스마다 유지하는 정보들을 담는 커널 내 자료구조
- 커널 메모리의 데이터 영역에 위치한다.
- 다음 요소들로 구성되어 있다.
- 프로세스의 상태
- CPU를 할당해도 되는지 여부를 결정
- 프로세스 카운터 값
- 다음 수행할 명령어 위치 가리킴
- CPU 레지스터 값
- CPU 연산을 위해서 현 시점에서 레지스터에 특정 값을 저장
- CPU 스캐줄링 정보
- 스캐줄링에 필요한 정보
- 메모리 관리 정보
- 메모리 할당에 필요한 정보
- 자원 사용 정보
- 사용자에게 자원 사용 요금을 계산하여 청구
- 입출력 상태 정보
- 프로세스가 오픈한 파일 정보 등 프로세스의 입출력 관련 상태 정보
- 프로세스의 상태
🌩 4. 문맥교환
- Context Switch - 하나의 사용자 프로세스로부터 다른 사용자 프로세스로 CPU의 제어권이 이양되는 과정
- 타이머 인터럽트가 발생하면 직전 수행 프로세스의 문맥을 저장하고 새로운 프로세스에게 CPU를 이양한다.
- 기존에 보유하고 있던 프로세스의 문맥 저장
- PC 값 등을 자신의 PCB에 저장
- 새로 할당받은 프로세스
- 저장했던 문맥을 PCB에서 하드웨어로 복원
- 타이머 인터럽트 외에도 실행 중이던 프로세스가 입출력 요청이나 다른 조건을 충족하지 못해서 CPU를 뺏기고 봉쇄상태가 될 때도 문맥교환이 발생한다.
- 프로세스 실행 상태 중 인터럽트나 시스템 콜로 인해 CPU의 제어권이 운영체제로 넘어가면 실행 중이던 프로세스의 문맥을 일부 PCB에 저장하지만 이 과정은 문맥교환이라고 하지 않는다.
- 단순히 해당 프로세스의 모드가 사용자모드에서 커널모드로 바뀌는 것 뿐이다.
- 모드변경보다 문맥교환이 훨씬 많은 오버헤드가 발생한다. 따라서 타이머의 단위가 작아 문맥교환이 지나치게 자주 일어나면 오버헤드가 커진다.
- 하지만 단위가 너무 크면 시분할 시스템의 의미가 퇴색되므로 적절한 시간 할당이 중요하다.
🌩 5. 프로세스를 스케줄링하기 위한 큐
- 운영체제는 준비상태에 있는 프로세스들을 ready queue에 두고 줄 앞에 프로세스에게 CPU를 할당한다.
- 줄을 세우는 방식은 CPU 스캐줄링 방식에 따라서 달라진다.
- 운영체제 하드웨어 자원을 기다리는 프로세스를 위한 자원별 장치 큐 device queue가 있다.
- ex. 디스크 입출력 큐 disk I/O queue, 키보드 입출력 큐 등등
- 소프트웨어 자원을 기다리기 위한 자원 큐도 있다.
- 어떤 공유 데이터에 대한 접근 권한 등등
- 일관성을 위해 해당 공유 데이터에 접근 중인 프로세스가 다 사용하고 반납할 때까지 접근 권한을 주면 안된다.
- 이 관리를 자원 큐를 통해서 한다.
- 이 모든 큐들은 커널의 데이터 영역에 둔다.
- 프로세스의 CPU 대기, 입출력 대기 등의 정보를 커널이 총체적으로 관리한다.
- 작업 큐 (job queue) - 시스템 내의 모든 프로세스를 관리하기 위한 큐로 프로세스의 상태와 무관하게 현재 시스템 내에 있는 모든 프로세스가 작업 큐에 속한다.
- 작업 큐에 있다고 반드시 메모리가 있는 것은 아니다.
- 작업 큐가 가장 넓은 개념이고 준비 큐와 장치큐이 있는 프로세스는 모두 작업 큐에 속해있다.
- 큐는 각 프로세스의 PCB를 연결 리스크 형태로 관리하고 포인터로 순서를 정한다.
🌩 6. 스케줄러
- 스캐줄러 - 어떤 프로세스에게 자원을 할당할지 결정하는 운영체제 커널의 코드
- 장기 스캐줄러와 단기 스케줄러
- 장기 스캐줄러 (long term scheduler) - 작업 스캐줄러 (job scheduler) 이며 어떤 프로세스를 준비 큐에 진입시킬지 결정
- CPU에 실행되기 위해서는 프로세스가 메모리를 보유해야하므로 장기 스캐줄러는 프로세스에 메모리 보유 문제에 관여한다.
- 수십 초 내지 수 분 단위로 가끔 호출되므로 상대적으로 느린 것이 허용된다.
- 메모리에 동시에 올라가 있는 프로세스의 수 (degree of multiprogramming)을 조절한다.
- 하지만 현대의 시분할 시스템은 메모리가 훨씬 커서 장기 스케줄러 없어 바로 프로세스에 메모리를 할당해 준비큐에 넣어준다.
- 단기 스캐줄러 (short term scheduler) - 준비 프로세스 중 어떤 프로세스를 다음에 실행상태로 만들지 결정
- 준비 큐에 있는 것들 중 어떤 프로세스에게 CPU를 할당할지 결정하는 것
- 타이머 인터럽트 발생시 단기 스캐줄러가 호출된다.
- 밀리초 단위로 빈번하게 호출이 되므로 수행 속도가 빨라야 한다.
- 중기 스캐줄러 (medium term scheduling) - 메모리에 적재된 프로세스의 수를 동적으로 조절
- 너무 많은 프로세스가 메모리에 적재되어 시스템 효율이 떨어지는 것을 관리한다.
- 메모리에 당장 필요한 프로세스의 주소 공간도 모자라면 디스크 입출력이 수시로 발생하여 시스템의 성능이 저하된다.
- 중기 스캐줄러는 이 경우 메모리의 프로세스 중 일부를 선정 해 메모리를 뺏고 해당 내용을 스왑 영역에 저장한다 ⇒ swap out
- 프로세스당 보유 메모리가 지나치게 적다면 일부 프로세스를 메모리에게 디스크로 스왑 아웃시키는 역할을 수행한다.
- 봉쇄 상태에 있는 프로세스들이 가장 먼저 스왑 아웃된다. 그럼에도 부족하다면 타이머 인터럽트 발생 후 준비 큐로 이동하는 프로세스들을 추가적으로 스왑 아웃한다.
- 다시 CPU를 할당 받을 때까지 시간이 걸리기 때문이다.
- 프로세스의 중지(suspended, stopped) 상태
- 외부적인 이유로 프로세스의 수행이 정지된 상태
- 디스크로 스왑 아웃된 프로세스의 상태이다.
- 중지준비 상태 - 준비 상태의 프로세스가 디스크로 스왑 아웃된 것
- 중지봉쇄 상태 - 봉쇄 상태의 프로세스가 디스크로 스왑 아웃된 것
- 중지봉쇄 상태에서 해당 작업이 끝나면 중지준비 상태로 변경된다.
- 이 경우들은 프로세스가 메모리를 보유하지 않고 통째로 디스크로 스왑 아웃 된 상태이다.
🌩 7. 프로세스의 생성
- 시스템 부팅된 후 최초 프로세스는 운영체제가 직접 생성한다.
- 이후부터는 이미 존재하는 프로세스가 다른 프로세스를 복제 생성한다.
- 생성하는 프로세스를 부모 프로세스, 생성되는 프로세스를 자식 프로세스라고 한다.
- 자식 프로세스가 먼저 죽고 부모 프로세스가 이에 대한 처리를 한다.
- 부모 프로세스가 종료되기 위해서는 생성된 자식 프로세스가 모두 종료된 후에야 종료될 수 있다.
- 프로세스의 자원
- 운영체제와 자원의 종료에 따라 획득하는 방식이 다르다.
- 운영체제로 직접 자원 할당
- 부모 프로세스와 자원을 공유하여 사용
- 운영체제와 자원의 종료에 따라 획득하는 방식이 다르다.
- 프로세스 수행 모델
- 부모와 자식이 공존하며 수행
- 부모와 자식이 CPU를 획득하기 위해 경쟁함
- 자식이 종료(terminated) 될 때까지 부모가 기다리는(wait) 모델
- 자식이 종료될 때까지 부모 프로세스는 봉쇄 상태에 머물다가 자식 종료 후 부모 프로세스가 준비 상태가 되어 CPU를 획득할 수 있음
- 부모와 자식이 공존하며 수행
- 프로세스가 생성될 때 독자적인 주소 공간을 갖는다.
- 자식 프로세스가 생성될 때 부모 프로세스의 주소 공간을 복사하여 별도의 주소 공간을 생성하고 새로운 프로그램 내용을 덮어씌워 실행한다.
- 유닉스에서
fork()
시 자식 프로세스가 생성되고 부모와 똑같은 커널 내 정보와 주소 공간 정보를 가진 상태로 복사된다. (프로세스 id는 다르다) - 이후
exec()
시 새로운 주소 공간을 덮어씌운다.
- 유닉스에서
- 자식 프로세스가 생성될 때 부모 프로세스의 주소 공간을 복사하여 별도의 주소 공간을 생성하고 새로운 프로그램 내용을 덮어씌워 실행한다.
프로세스의 종료
- 자발적 종료
- 코드의 마지막에
exit()
라는 시스템 콜을 통해 (없다면 컴파일러가 자동으로 삽입) 종료하고 운영체제는 해당 프로세스로부터 자원을 회수한다.
- 코드의 마지막에
- 비자발적 종료
- 부모 프로세스가 자식 프로세스의 수행을 강제로 종료하며
abort()
로 이루어진다.
- 자식 프로세스가 할당 자원의 한계 이상의 자원을 요구할 때
- 자식 프로세스에게 할당된 작업이 필요하지 않을 때
- 부모 프로세스가 종료(exit) 되는 경우에 발생한다.
- 부모 프로세스가 자식 프로세스의 수행을 강제로 종료하며
- 종료되는 프로세스는 자식 프로세스를 계속 실행하기 위해서 종료되지 않을 다른 프로세스의 양자로 보내어 계속 수행할 수 있도록 할 수 있다.
자식 프로세스 생성
fork()
시스템 콜로 CPU제어권을 커널로 넘겨 fork() 호출 프로세스를 복제해 자식 프로세스를 생성- 부모와 모든 문맥(주소 공간, PC, 레지스터 상태, PCB, 커널스택 등)을 동일하게 가진 자식 프로세스 생성한다.
- 따라서 자식 프로세스는 부모 프로세스의 현재 수행 시점부터 수행하게 된다. (PC 등의 값을 그대로 복제하므로)
- 식별자는 부모 프로세스와 다르다.
- 함수의 결과값은 자식은 0, 부모는 양수이다. 이 값으로 자식과 부모 프로세스를 분기할 수 있다. 하지만 여전히 분기문을 가진 코드 또한 동일한 것을 지닌 상태이다.
- 부모와 모든 문맥(주소 공간, PC, 레지스터 상태, PCB, 커널스택 등)을 동일하게 가진 자식 프로세스 생성한다.
- 자식에게 독자적인 프로그램 수행이 가능하도록 유닉스에서 새로운 주소 공간에 새로운 프로그램을
exec()
를 통해 덮어씌울 수 있도록 한다. fork()
,exec()
,exit()
,wait()
는 모두 특권명령이다.wait()
은 자식 프로세스가 종료될 때까지 부모 프로세스를 봉쇄 상태에 머무르게 하는 것이다.- 이것으로 자식과 부모의 동기화 (synchronization)이 가능하다.
- 자식 프로세스가 종료되면 다시 준비 큐에 삽입되어 CPU 할당 받을 수 있다.
🌩 8. 프로세스 간의 협력
- 부모 프로세스와 자식 프로세스는 독자적인 메모리 구조를 가지므로 독립적인 관계가 된다.
- 프로세스간 협력할 때 서로 주소 공간을 참조하지 않으면서 정보를 주고받을 수 있는 매커니즘이 필요하다.
- IPC(Inter-Process Communication) - 운영체제가 제공하는 하나의 컴퓨터 안에서 실행 중인 프로세스 간 협력 매커니즘
- 프로세스간의 통신(communication)과 함께 공유 데이터의 일관성을 위한 동기화를 보장해주어야 한다.
- 메세지 전달(message passing)과 공유메모리(shared memory) 방식이 있다.
- 차이는 shared data가 있는 것과 없는 것이다.
메세지 전달
- 프로세스간 공유 데이터가 없이 메세지를 주고받으며 통신한다. 메세지 전달은 직접하지 못하고 커널이 전달한다.
- 커널이 제공하는 send(), receive() 연산으로 시스템 콜 방식으로 요청해 메세지를 전달한다.
- 메세지를 전달하는 연산은 특권명령이다.
- 통신하기 원하는 두 프로세스는 communication link를 생성하고 send(), receive()를 통해 메세지를 주고 받는다.
- communication link는 물리적인 방법, 논리적인 방법 두 가지로 구현할 수 있다.
- 직접 프로세스에게 전달하는 방식과 메일 박스를 통해 간접적으로 전달하는 방식으로 나뉜다.
- 직접 통신 (direct communication)
- 통신하려는 프로세스를 직접 명시하고 받는 프로세스도 직접 명시한다.
- 커뮤니케이션 링크는 자동으로 생성되고 하나의 링크는 한 쌍의 프로세스에게 할당된다.
- 대부분의 링크는 양방향이며 단 하나의 링크만 서로 존재한다.
- 간접 통신 (indirect communication)
- 메일박스 또는 포트로 메시지를 전달받는다. 메일박스는 고유의 id가 있어서 해당 메일박스를 공유하는 프로세스들끼리만 통신을 할 수 있다.
- 커뮤니케이션 링크는 메일박스를 공유하는 경우에만 생성된다.
- 하나의 링크가 여러 프로세스에게 할당될 수 있고, 각 프로세스 쌍은 여러 링크를 공유할 수 있다.
- 링크는 단방향, 양방향일 수 있다.
- 새로운 메일박스를 생성하는 연산, 메세지 send(), receive() 연산, 메일박스 삭제 연산을 할 수 있다.
- 간접통신에서 메세지 대상 및 수신자는 A라는 메일박스로 통일된다.
- 메일박스 공유로 수신 대상의 혼란을 제어하기 위해 2개의 프로세스에게만 링크를 할당할 수 있다.
- 또는 링크의 receive() 연산을 매 시점 하나의 프로세스만 수행할 수 있도록 한다.
- 시스템이 메세지 수신자를 임의로 결정해 누가 받았는지 송신자에게 통신해준다.
- 직접 통신 (direct communication)
공유메모리 shared memory
- 프로세스들의 메모리 주소 공간 일부를 공유한다.
- 각 프로세스는 독립된 주소 공간을 가지고 있다. 이 주소 공간(가상 메모리)가 물리 메모리로 매핑될 때 공유메모리 주소 영역은 동일한 물리 메모리 영역으로 매핑된다.
- 통신이 쉬운 인터페이스이지만 데이터 일관성 문제가 발생할 수 있다. 이 문제는 커널이 책임지지 않으며 프로세스들끼리 직접 동기화 문제를 해결해야 한다.