본 글은 (KOCW) 운영체제, 이화여자대학교 반효경 교수님의 강의를 듣고 내용을 요약 및 정리했습니다.
스터디를 진행하는 것에 목적이 있으며, 자세한 사항은 여기를 참고하시면 됩니다.
Process의 개념
프로세스란 실행 중인 프로그램을 의미(Process is a program in execution)
프로세스와 관련된 중요 개념으로 프로세스의 문맥(Context)이 있다
- 프로그램 실행 시 Address Space가 형성된 후 프로세스가 CPU 제어권을 갖게 되면 CPU는 매 클럭 사이클마다 PC 레지스터가 참조하고 있는 Address space의 한 부분을 읽어서 실행한다
- 실행 정보를 레지스터(R1, R2, …)에 대입한 뒤 산술 논리 연산 장치(ALU)에서 연산을 하고, 그 결과를 다시 레지스터에 저장하거나 프로세스의 Address space에 저장
- 이때 실행 정보를 프로세스의 문맥이라고 하며 컨텍스트라고 한다
실행 정보들을 담고 있는 컨텍스트에는 3가지 관점에서 볼 수 있다
- CPU의 수행 상태를 나타내는 하드웨어 문맥
- Program Counter가 가리키는 instruction의 위치
→ 어디까지 실행했는가 - 각종 레지스터가 담고 있는 데이터
→ 어떤 정보들을 담고 있는가
- Program Counter가 가리키는 instruction의 위치
- 메모리 관점에서 프로세스의 Address space가 담고 있는 정보
- code, data, stack
- 커널 Address space 관점에서 프로세스 관련 커널 자료 구조
- 실행 중인 프로세스의 PCB(Process Control Block) 정보
- 실행 중인 프로세스의 Kernel stack 정보
커널의 코드는 모든 프로세스가 공유하기 때문에 프로세스마다 별도의 kernel stack을 두고 있다. 프로세스의 현재 상태를 규명하기 위해서는 해당 프로세스의 kernel stack 정보가 필요하다
그렇다면 이러한 정보들을 수집해서 프로세스가 특정 시점에 어떤 상태에 있는지 정확하게 알아야 하는 이유는 무엇일까?
현대의 컴퓨터 시스템은 time sharing, multi-tasking 환경이기 때문이다
즉, 여러 개의 프로세스들이 번갈아가면서 실행되면서 CPU 제어권이 프로세스 사이를 오가기 때문에 특정 시점의 프로세스 실행 정보를 백업해놓지 않으면 프로세스를 ‘이어서’ 실행할 수 없다
프로세스의 상태(Process State)
CPU가 하나밖에 없는 환경을 가정했을 때 CPU 제어권을 가지고 있는 프로세스는 매 순간 하나밖에 존재하지 않는다
프로세스는 상태(state)가 변경되며 수행
- Running
- CPU 제어권을 가지고 instruction을 수행 중인 상태
- Ready
- CPU를 기다리는 상태 (실행을 위한 instruction이 메모리상에 올라와 있어서 CPU 제어권만 있으면 바로 실행할 수 있는 상태)
- Ready 상태에 있는 프로세스들이 CPU 제어권을 주고받으면서 instruction을 수행함
- Blocked(waiting, sleep)
- CPU 제어권을 주어도 당장 instruction을 수행할 수 없는 상태
- 프로세스 자신이 요청한 이벤트(I/O)가 즉시 만족되지 않아 이를 기다리는 상태
- ex. 디스크에서 파일을 읽어와야 하는 경우
- 이벤트가 완료되면 Ready 상태로 이동
- New
- 프로세스가 생성 중인 상태
- 생성되면 Ready 상태에 들어감
- Terminated
- execution(수행)이 끝난 상태
- Ready queue에 대기하고 있다가 CPU 제어권을 얻어 instruction을 실행
- 필요에 따라 I/O 작업 또는 공유데이터를 사용하기 위해 blocked 상태로 전환된 뒤 I/O queue 또는 Resource queue에 대기
- 해당 작업이 끝나면 다시 CPU에 인터럽트를 걸고 운영체제가 CPU제어권을 획득하여 완료된 처리의 메모리 자원을 처리한 후 Ready queue에 다시 작업을 넣는다
- 공유데이터에 누군가 이미 접근하고 있으면 동시에 접근하면 안 되기 때문에 Resource queue를 통해 줄을 서서 접근할 수 있게 함
- 커널이 자신의 data영역에 queue라는 자료구조를 만들어 놓고 각 프로세스의 상태를 바꿔가면서 CPU 제어권 분배를 운영
PCB (Process Control Block)
- 운영체제가 각 프로세스를 관리하기 위해 프로세스당 유지하는 정보
- 다음과 같은 요소들로 이루어져 있다. (구조체로 유지)
- OS가 관리상 사용하는 정보: Process state, Process ID, scheduling information, priority (Ready queue에서 대기 순서가 아닌 우선순위가 높은 프로세스가 먼저 CPU 제어권을 얻는다)
- CPU 수행 관련 하드웨어 값: Program counter, registers
- 메모리 관련: code, data, stack의 메모리 위치 정보
- 파일 관련: open file descriptors, …
문맥 교환 (Context Switch)
- CPU를 한 프로세스에서 다른 프로세스로 넘겨주는 과정
- CPU가 다른 프로세스에게 넘어갈 때 운영체제는 다음의 두 가지를 수행
- CPU를 내어주는 프로세스의 상태를 그 프로세스의 PCB에 저장
- CPU를 새롭게 얻는 프로세스의 상태를 PCB에서 읽어옴
PCB 정보는 메모리상에서 커널의 data 영역에 저장된다.
system call이나 하드웨어 인터럽트가 발생했을 때 반드시 context switch가 일어나는 것은 아님
(1) 일반적인 하드웨어 인터럽트나 system call의 경우 context switch 없이 kernel mode에서 user mode로의 전환만 발생한다.
(2) Timer interrupt(CPU 제어권을 다른 프로세스에 넘기려고 하는 의도를 가진 인터럽트)나 I/O처리를 위한 system call(시간이 오래 걸리는 작업이기 때문에 프로세스의 상태를 blocked로 바꾸고 바로 작업 가능한 ready 상태의 다른 프로세스로 CPU 제어권을 옮기는 경우) context switch가 발생한다.
(1)의 경우에도 CPU 수행 정보 등 context의 일부를 PCB에 저장해야 하지만 문맥교환을 하는 (2)의 경우 overhead가 훨씬 크다. (e.g. cache memory flush)
프로세스를 스케줄링하기 위한 큐
- Job queue ─ 현재 시스템 내에 있는 모든 프로세스의 집합
- Ready queue ─ 현재 메모리 내에 있으면서 CPU를 잡아서 실행되기를 기다리는 프로세스의 집합
- Device queues ─ I/O device의 처리를 기다리는 프로세스의 집합
-> 프로세스들은 각 큐들을 오가며 수행된다
맨 위에 있는 Ready queue와 나머지 device queue들의 자료구조를 나타낸 그림이다. PCB의 포인터를 통해 PCB를 줄 세움
스케줄러 (Scheduler)
: 메모리에 올려둘 프로세스의 수를 관리하는 방식
- Long-term scheduler (장기 스케줄러 or job scheduler)
- new 상태인 프로세스 중 어떤 것들을 ready queue로 보낼지 결정
- 프로세스에 memory 및 각종 자원 분배 결정
- degree of Multiprogramming을 제어
- 메모리에 올라가 있는 프로세스의 수를 조절 (10개의 프로세스를 모두 메모리에 올리고 있다면 degree of Multiprogramming이 10)
- 몇 개를 메모리에 올려놓을지가 중요
- 프로그램이 너무 적어도, 너무 많아도 CPU의 성능이 저하된다
- 너무 적은 경우에는 CPU가 대기하는 시간이 길어지기 때문(사용률)
- 메모리에 올라가 있는 프로세스의 수를 조절 (10개의 프로세스를 모두 메모리에 올리고 있다면 degree of Multiprogramming이 10)
- 현대의 time sharing system에는 보통 장기 스케줄러가 없음 (무조건 ready 상태로 생성)
- Short-term scheduler (단기 스케줄러 or CPU scheduler)
- 어떤 프로세스를 다음에 running 시킬지 결정
- 프로세스에 CPU를 주는 문제
- 충분히 빨라야 함 (millisecond 단위)
- Medium-term scheduler (중기 스케줄러 or Swapper)
- 여유 공간 마련을 위해 프로세스를 통째로 메모리에서 디스크로 쫓아냄
- 프로세스에게서 memory를 뺏는 문제
- time sharing system(시분할)에서는 중기 스케줄러를 통해 degree of Multiprogramming을 제어함
요약하면, 장기 스케줄러 방식은 애초에 프로그램에게 메모리를 줄지 말지 결정해서 메모리상의 프로세스의 수를 관리한다 하지만 현대의 time sharing system은 장기 스케줄러 방식이 아니라 중기 스케줄러 방식을 쓴다. 일단 실행 중인 모든 프로그램에 메모리를 주고 우선순위가 떨어지는 프로그램을 디스크로 쫓아낸다
프로세스의 상태 (Suspended 상태 포함)
현대의 운영체제에서는 중기 스케줄러에 의해 메모리를 통째로 빼앗긴 프로세스가 존재하고 이러한 상태를 표현하기 위해 Suspended (stopped)라는 프로세스 상태가 추가됐다
따라서 현대의 운영체제는 프로세스의 상태를 다음과 같이 구분한다고 할 수 있다.
- Running
- CPU 제어권을 가지고 instruction을 수행 중인 상태
- Ready
- CPU를 기다리는 상태 (메모리 등 다른 조건을 모두 만족)
- Blocked (wait, sleep)
- I/O 등의 event를 (스스로) 기다리는 상태
- ex. 디스크에서 파일을 읽어와야 하는 경우
- Suspended (stopped)
- 중기 스케줄러 / 사용자에 의해 프로세스의 수행이 정지된 상태
- 프로세스는 통째로 디스크에 swap out 된다
- ex. 사용자가 프로그램을 일시 정지 시킨 경우(break key)
- ex. 시스템이 여러 이유로 프로세스를 잠시 중단시킨다. (메모리에 너무 많은 프로세스가 올라와 있을 때)
Blocked 상태의 프로세스는 자신이 요청한 event가 만족되면 Ready 상태로 전환된다
Suspended Blocked 상태는 외부에서 프로세스를 재개시켜야 다시 Active 한 상태(Suspended Ready)가 된다
사용자 프로세스의 상태도
Running 상태를 프로세스가 user mode에서 자신의 코드를 실행하는 경우와 kernel mode에서 운영체제의 도움을 받는 경우로 나누어서 표현하고 있다. 이때 주의할 점은 Running, Block, Ready 등의 상태는 운영체제의 상태가 아니라 사용자 프로세스의 상태라는 점이다. 운영체제가 Running 하는 것이 아니다
System call이나 interrupt가 발생하면 운영체제의 코드를 실행시켜야 하므로 운영체제의 Running을 표현하였음
Suspended 상태에서도 진행 중이던 작업이 있었을 경우 작업이 완료되면 Suspended Ready 상태로 전환된다. (Active 한 상태로 갈 수 있다는 의미)
Thread
thread란 프로세스의 실행 단위 / CPU 수행 단위이다.
동일한 작업을 하는 프로세스가 여러 개인 경우 프로세스의 Address space는 하나만 생성하고 여러 개의 thread를 둠으로써 메모리의 낭비를 줄이고 프로세스마다 다른 부분의 코드를 실행할 수 있다. (lightweight process 경량 프로세스, 스레드 1개의 전통적인 방식 heavyweight process)
thread는 다음의 CPU 수행 정보들로 구성되어 있으며
- program counter(PC)
- register set
- stack
Thread들이 공유하는 부분 (code section, data section, OS resources)을 task라고 한다.
- Address space의 data, code 영역을 공유하되 stack은 별도로 할당받는다.
- PCB에서는 program counter(PC)와 register set(각 스레드마다 가지고 있음)을 제외한 프로세스 관련 정보 및 자원들을 모두 공유한다.
Thread의 장점
Responsiveness - 응답성
- 다중 스레드로 구성된 태스크 구조에서는 하나의 서버 스레드가 blocked(waiting) 상태인 동안에도 동일한 태스크 내의 다른 스레스가 실행(running)되어 빠른 처리를 할 수 있다
- ex. 웹브라우저(프로그램)가 스레드를 여러 개 가지고 있다면
- 하나의 스레드가 이미지를 비롯한 추가 데이터를 받기 위해 서버에 요청을 걸어놓고 blocked 상태가 됐을 때 다른 스레드가 이미 받아놓은 HTML 텍스트를 우선적으로 화면에 출력(다중 스레드가 협력하여 높은 처리율 throughput)할 수 있다 -> 비동기식 입출력을 통해 사용자의 답답함을 줄이고 응답성을 높일 수 있다
- 스레드를 사용하면 병렬성을 높일 수 있다
- ex. 웹브라우저(프로그램)가 스레드를 여러 개 가지고 있다면
Resource Sharing
- 하나의 프로세스 안에 CPU 수행 단위(스레드)를 여러 개 두고 code, data, resource 자원을 공유함으로써 보다 효율적으로 자원을 활용할 수 있다.
Economy - 경제성
- 하나의 프로세스를 만드는 것보다 하나의 스레드를 만드는 overhead 가 적다
- 동일한 일을 수행하는 다중 스레드가 협력하여 높은 처리율(throughput)과 성능 향상을 얻을 수 있다.
- CPU switch 역시 프로세스 단위로 교환이 일어나는 것보다 프로세스 안에서 스레드끼리 교환이 일어나는 게 overhead가 적다.
- Solaris의 경우 위 두 가지 overhead가 각각 30배, 5배
Utilization of MP Architectures (MP: MultiProcessor)
- 각각의 스레드가 서로 다른 CPU를 가지고 병렬적으로 작업을 진행해서 훨씬 효율적으로 작업을 수행할 수 있다.
Thread의 실행
스레드는 실행 방법에 따라 다음의 두 가지 타입으로 나눌 수 있다.
- Kernel Threads ─ 운영체제가 스레드가 여러 개인 것을 알고 있어서 스레드 간의 CPU 교환을 ‘커널이’ CPU 스케줄링을 하듯이 관리한다.
- User Threads ─ 운영체제는 스레드가 여러 개인 것을 모르는 상태에서 사용자 프로그램이 라이브러리의 지원을 받아 스스로 여러 개의 스레드들을 관리한다. 커널이 스레드의 존재를 모르기 때문에 구현에 제약이 있을 수 있다.
(그밖에 real-time 스레드들도 존재한다.)
프로세스가 무엇인가요?
- 프로그램과 프로세스, 스레드의 차이에 대해 설명해 주세요
- 프로그램은 디스크에 저장되어있는 실행파일을 말하고, 프로세스는 실행 중인 프로그램의 인스턴스로 실행 단위를 의미합니다. 스레드는 하나의 프로세스의 작업 단위를 말합니다.
- 메모리에 적재되지 않은 프로그램을 실행하여 메모리에 적재되면 프로세스가 되며 그 내부에서 실제 작업을 처리하는 단위가 스레드가 됩니다
- PCB가 무엇인가요?
- PCB란 프로세스 컨트롤블럭으로, 운영체제가 프로세스를 관리하기 위한 정보를 담고 있습니다
- 프로세스의 상태, id, 스케쥴링, 우선순위 등의 정보를 가지고 OS가 프로세스를 관리하는데 사용하며, CPU 수행과 관련된 PC, Register 정보, 메모리와 관련된 code, data, stack의 메모리 위치 정보, 프로세스가 열어놓은 파일과 관련된 open file descripter 정보 등이 포함됩니다.
- 그렇다면, 스레드는 PCB를 갖고 있을까요?
- 네, 프로세스 사이 컨텍스트 스위칭이나 처리를 할 때 운영체제는 PCB 정보를 활용하는데, 스레드도 마찬가지로 스레드 사이 컨텍스트 스위칭이 발생합니다. 이 때 필요한 정보를 TCB에 저장하여 운영체제가 처리할 수 있도록 합니다 TCB에는 어떤 프로세스에 속해있는지에 대한 포인터 PC, 스레드에만 필요한 정보를 registers에 저장하여 담고있다 (프로세스에 종속되어 필요정보들을 담고 있으므로..)
프로세스 주소공간에 대해 설명해 주세요
프로세스 주소공간(Address Space)은 Code 영역, Data영역, Stack영역, Heap영역으로 나뉘며 Code 영역에는 실행가능한 명령어들이 저장되는 공간, Data 영역에는 전역 변수와 정적 변수의 값이 저장되는 공간입니다. Stack 영역은 프로세스의 함수 호출, 지역변수를 관리하며 Heap 영역에 동적으로 할당되는 메모리를 저장하는 데 사용되며 런타임에 크기가 결정되는 영역입니다.
- 초기화 하지 않은 변수들은 어디에 저장될까요?
- Data영역의 BSS(Block Started by Symbol) 섹션에 저장되며 BSS 섹션은 초기화되지 않은 변수를 프로그램이 실행될 때 0 또는 null으로 초기화, 초기화되지 않은 변수들을 따로 저장하여 메모리를 효율적으로 활용할 수 있습니다.
- 일반적인 주소공간 그림처럼, Stack과 Heap의 크기는 매우 크다고 할 수 있을까요? 그렇지 않다면, 그 크기는 언제 결정될까요?
- Stack 영역에 함수 호출이나 지역변수를 관리한다고 했는데, 자바를 예시로 들면 Stack 영역의 변수들은 Heap 영역에 위치한 실제 Object의 참조를 가지고 있기 때문에 Heap 영역의 크기가 더 크고 Stack 영역의 크기가 작으며 Stack 영역의 크기는 생성과 동시에 결정되고 Heap은 동적으로 늘어나거나 줄어들 수 있습니다
- Stack과 Heap 공간에 대해, 접근 속도가 더 빠른 공간은 어디일까요?
- 다음과 같이 공간을 분할하는 이유가 있을까요?
- 스택 및 힙 영역의 분리는 동적 메모리 할당 및 해제를 관리하는데 도움을 주고, 메모리 영역을 효율적으로 사용할 수 있게됩니다
- 스레드의 주소공간은 어떻게 구성되어 있을까요?
- 스레드의 주소공간에는 Stack으로만 구성되어있습니다 나머지 공간은 프로세스의 값을 함께 쓰고 있기 때문이며 이는 동기화문제를 고려해야 한다는 것을 알 수 있습니다
컨텍스트 스위칭 시에는 어떤 일들이 일어나나요?
- 프로세스와 스레드는 컨텍스트 스위칭이 발생했을 때 어떤 차이가 있을까요?
- 프로세스는 독립적인 메모리 공간을 가지기 때문에 프로세스 간의 컨텍스트 스위칭은 사용했던 메모리 전체를 교체하므로 오버헤드가 더 큽니다. 하지만 스레드 간의 스위칭은 프로세스 내의 공유 되는 메모리보다 작은 각 스레드가 독립적으로 가지고 있는 register만 교체하면 되기 때문에 오버헤드가 훨씬 적게 된다
- 컨텍스트 스위칭이 발생할 때, 기존의 프로세스 정보는 커널스택에 어떠한 형식으로 저장되나요?
- 커널 스택에는 기존 프로세스 상태 정보, 레지스터 상태, 커널 스택의 위치를 나타내는 포인터가 저장되며 기존 프로세스가 다시 running 상태로 돌아갈 때 해당 정보를 사용해 프로세스 간의 전환이 가능합니다.
- 컨텍스트 스위칭은 언제 일어날까요?
- CPU 스케쥴링, Timer에 의해 처리할 프로세스가 교체되는 경우, I/O 처리를 위한 시스템 콜이 발생했을 경우 현재 프로세스를 blocked 시키고 ready상태의 프로세스를 처리할 때 컨텍스트 스위칭이 발생하게 됩니다
'CS' 카테고리의 다른 글
OS - CPU Scheduling (0) | 2023.10.19 |
---|---|
OS - Program Management (0) | 2023.10.18 |
OS - System Structure & Program Execution (0) | 2023.10.15 |
운영체제란? (0) | 2023.10.15 |
라우팅 (0) | 2023.10.12 |