이 글은 반효경 교수님의 운영체제 강의 및 교재를 참고합니다.
📢 들어가며
프로그램이 요구하는 태스크를 운영체제가 어떻게 수행하고 관리하는가?
프로그램, 프로세스를 구분해보자.
CPU가 하나인 싱글 코어 컴퓨터를 가정해보자. 쓰레드의 개념을 적용시키지 않는다면, 특정 시간에 처리할 수 있는 작업은 오직 하나 뿐이다. CPU는 정말 빠르고 성능이 좋지만, 만약 어떤 프로그램이 엄청나게 많은 시간을 잡아먹는 작업을 시작했다고 하자. 그럼 그 시간 동안 다른 작업을 미루어 둔 채 해당 작업에 전념해야만 할까?
물론 그렇지 않을 것이다. 이러한 시간의 간극을 채우기 위해 도입된 개념이 "Process Context"이다. 프로세스의 문맥을 어딘가에 저장해두고, 다른 프로세스로 넘어가면 앞서 말한 간극을 해결할 수 있다. 어차피 CPU가 Device에 직접 접근하는 것이 아니기 때문에 가능한 이야기이다.
특정 시점에서 프로세스가 어디까지 수행을 했는지 나타내기 위해 필요한 요소들을 프로세스의 문맥이라고 지칭한다. 프로세스의 문맥을 저장하기 위해, 프로세스 메모리 구조는 다음의 항목을 포함한다.
stack: 잠시 사용되었다가 사라지는 데이터가 저장됨. 함수 호출 시 할당되고 함수 반환 시 소멸되며, 로드 시 크기가 결정됨.
code: 실행할 프로그램의 코드가 저장됨. CPU는 여기에서 명령어를 하나씩 가져와서 처리함.
data: 전역 변수 및 정적 변수가 저장됨. 프로그램이 시작될 때 할당되고 프로그램 종료 시 소멸됨.
stack, code, data는 컴파일 시 메모리 영역이 결정됨.
heap: 포인터 변수 등이 저장되는 동적 데이터 영역. 메모리 주소 값에 의해서만 참조되고 사용됨. 프로그램 동작 시 크기가 결정됨.
++
Process Context
- CPU 수행 상태를 나타내는 하드웨어 문맥
CPU의 PC가 해당 프로세스의 code 영역 중 어디를 가리키고 있었고/어떤 내용을 얼마나 stack에 쌓아두고 있었는지 등의 정보- 프로세스 주소 공간
stack, data, code의 주소 공간 자체- 프로세스 관련 커널 자료 구조
프로세스가 하나 생길 때마다 운영체제가 커널에 해당 프로세스와 관련하여 생성한 정보(PCB 등). 해당 자료 구조를 통해 커널이 프로세스를 관리함.
프로세스가 System Call을 했을 때 Program Counter는 그 프로세스의 code를 가리키는 것이 아니라, 커널의 code를 가리키면서 커널 스택에 저장한다. 이때 프로세스마다 커널 스택을 달리하게 된다.
이러한 프로세스 문맥을 통해 프로세스들이 번갈아가며 CPU를 점유하기 때문에, 프로세스 상태라는 개념이 등장하게 된다. 기본적으로는 다음과 같은 상태가 있다.
운영체제는 프로세스의 상태를 기반으로 프로세스를 관리하며, 이 때 queue를 사용한다. 다음의 그림을 참고하면 이해가 쉽다.
문맥 교환은 interrupt 혹은 system call에 의해 발생한다. 이에는 두 가지 양상이 존재한다.
- 문맥 교환이 발생하지 않는 경우
- 문맥 교환이 발생하는 경우(1보다 overhead가 훨씬 크다)
참고