본문 바로가기
CS

운영체제 - 반효경 #3 Process

by unknownomad 2023. 3. 13.

# 3-1 Process

프로세스의 개념

프로세스

  • 실행 중인 프로그램
  • 실행 시작하면 독자적인 주소 공간 만듦
  • 이 프로세스가 CPU 잡으면 프로그램 카운터라는 레지스터가 이 프로세스의 코드 어느 부분을 가리키고 있고
  • 그럼 매순간 인스트럭션(기계어)를 하나씩 읽어 CPU 안으로 불러들이고
  • 레지스터 안에 어떤 값을 넣고, 연산 후(= ALU), 그 결과를 레지스터에 저장하거나 바깥의 메모리에 저장하는 방식으로 계속 진행
  • 이 프로세스가 어느 시점에 와있는지 규명하는 것
  • 프로세스의 현재 상태를 나타내는 데 필요한 모든 것

 

문맥

  • 전체적인 문장 구조를 이해해야 무슨 의미인지 알 수 있음

프로세스 개념에서의 문맥

  • 실행부터 종료까지 볼 때 이 프로그램을 어떻게 실행하는지, 어느 시점에 있는지 등 이해 가능
  • 특정 시점을 놓고 봤을 때 프로세스가 어디까지 수행했는지

 

PC

  • Program Counter, 프로그램 카운터
  • 이게 어딜 가리키고 있는지, 코드의 어느 부분까지 실행했는지 파악

 

Code

  • 메모리에 어떤 내용을 담고 있는가

 

Stack

  • 함수 등 실행했다면 쌓는 공간

 

Data

  • 변수 등 값을 바꾸는 공간

 

그림 상의 R1, …

  • 레지스터
  • 어떤 값을 넣고 어떤 인스트럭션을 실행했는가

 

CPU 수행 상태 나타내는 프로세스의 문맥

  • 프로세스는 CPU를 잡고 매순간 인스트럭션 실행함
  • 현재 시점에 프로세스가 인스트럭션을 어디까지 실행됐는지 알기 위해 레지스터에 어떤 값을 넣고, 프로그램 카운터가 어디를 가리키고 있는지 등을 파악하는 개념

 

프로세스 주소 공간

  • 어떤 내용이 들어있는가

 

프로세스 관련 커널 자료구조

PCB

  • 운영체제가 프로세스를 관리
  • 프로세스가 하나 시작될 때마다 운영체제는 그 프로세스를 관리하기 위해 자신의 데이터 영역에 자료구조를 둠
  • PCB에 CPU, 메모리를 얼마나 줘야 할지, 얘가 나쁜 짓을 하는지 고려함

 

Kernel stack

  • 각 프로세스가 자기 자신의 코드를 실행할 때 함수호출이 이루어지면, 본인 스택에 함수 호출 후 리턴하고, 관련 정보를 쌓아둠
  • 근데 프로세스가 실행하다 본인이 할 수 없는 일을 운영체제에 대신 요청(시스템콜)하면, 프로그램 카운터가 커널의 어딘가를 가리키며 실행
  • 커널도 함수로 구성되어 있기에 커널에서 함수호출 이루어지면 스택에 관련 정보 쌓음
  • 커널 = 여러 프로세스들이 공유하는 코드라 할 수 있음
  • 어떤 프로세스 간에 운영체제에 요청하면 커널 코드를 실행함
  • 커널이 누구의 부탁을 받고 실행하는지는 매번 다름
  • 커널에서 함수호출이 이루어지면 스택에 정보 쌓고, 그때 어떤 프로세스가 커널을 호출했는지에 따라 스택을 별도로 둠
  • 이렇게 해야 정보가 꼬이는 등의 문제 방지
  • 프로세스의 현재 상태 규명 위해 유저 스텍 말고 커널 스택에 쌓인 정보 필요

 

  • 이런 정보 알면 프로세스가 현재 어떤 상태인지 규명 가능
  • 프로세서 혼자 실행하면 우리가 이런 걸 알 필요 없음
  • 근데 현대 컴퓨터 시스템에서는 타임쉐어링, 멀티태스킹이 번갈아 실행되기에, 하나의 시스템이 CPU 잡고 실행하다 다른 프로세스에 CPU 넘어감
  • 그럼 현재 프로세스가 레지스터에 어떤 값을 넣고 실행 시, 이걸 백업해두지 않으면 = 프로세스의 현재 문맥을 알고 있지 않으면, 다음 CPU 에서 이 프로세스를 잡을 때 어느 부분부터 실행해야 할지 모름
  • 어느 시점까지 실행했는지를 정확히 알고 있어야, 그 다음부터 인스트럭션을 실행할 수 있음

 

프로세스의 상태

Running

  • 컴퓨터 안에 CPU는 하나(이 강의 기준)
  • CPU를 잡고, 인스트럭션을 실행하고 있는 프로세스는 매순간 하나일 거임, 이때의 프로세스 상태 = running

 

Ready

  • CPU가 하나이기에 너도나도 CPU를 쓰겠다 줄 서 있으나 본인 차례를 기다려야 하는 프로세스들의 상태 = ready
  • 프로그램이 실행되려면 CPU가 디스크에 접근 못하니, 물리적 메모리에 올라오고 CPU를 얻었을 때 인스트럭션 실행 가능
  • 프로세스 실행 준비가 다 끝나 있고 CPU만 얻으면 내가 인스트럭션을 열심히 실행할 수 있다 = ready
  • Ready 상태의 프로세스들이 CPU를 잡았다 놨다 하면서 타임쉐어링을 구현하고 있음

 

Blocked, wait, sleep

  • CPU를 줘봤자 인스트럭션을 실행 못하거나, 오래 걸리는 I/O 작업 등의 결과를 디스크에서 읽어와야 다음 작업 실행 가능한 프로세스의 상태 = blocked, wait, sleep
  • 어떤 프로그램의 전체 주소 공간을 물리적 메모리에 올려두고 실행하지 않음, Why? 여럿이 동시에 써야하기 때문
  • 어떤 프로그램의 코드 실행 시 코드 부분이 메모리에 올라와있지 않고 디스크에 내려가있으면, 당장 CPU 줘봤자 실행 불가 = 프로세스 blocked 상태
  • 프로세스 자신이 요청한 이벤트 등을 하고 있기에, 이게 만족되기 전까진 CPU 줘봤자 일 못함

 

New

프로세스가 막 생성 중(실행 전 단계)

 

Terminated

프로세스 자체가 끝나면 이를 정리하는 작업이 필요한데 그 상태를 말함

 

CPU

  • 빠르고 여러 자원이 공유
  • 하나의 프로세스가 CPU에서 running 하다 timer interrupt 들어오면 CPU 뺏기고 맨 뒤로 가서 줄 서고, 그 다음 프로세스가 CPU 얻고
  • CPU 에서 running 되다가 디스크에서 뭔가 읽어와야 하면 이 프로세스의 상태는 running ➡️ blocked 로 되고, 디스크의 서비스를 받는 queue 로 가서 줄 섬
  • 그럼 디바이스 컨트롤러의 지휘 하에 순차적으로 진행되고, 이 작업이 끝나면 컨트롤러가 CPU에 인터럽트 걸고 I/O 작업이 끝났다는 걸 알려줌
  • CPU는 인터럽트가 들어왔으니, 하던 작업 멈추고(라인 단위), CPU 제어권이 운영체제 커널에게 넘어감
  • 운영체제 커널은 I/O 요청했던 프로세스의 I/O 작업이 끝났으니, 그 프로세스의 메모리 영역에 I/O 작업 결과물에 해당하는 데이터를 넘겨주거나, blocked 된 프로세스의 상태를 ready 로 바꾸고 CPU를 사용할 수 있는 자격을 줘서 줄 서 있게 해줌

 

자원

  • 하드웨어 자원도 있으나
  • 소프트웨어 자원도 있음 = 공유데이터

 

  • 여러 프로세스가 공유데이터에 동시 접근하면, 하나의 프로세스가 접근하다 다른 프로세스가 CPU 점유하며 그 공유데이터를 쓰게 되는 경우가 발생하면서, 데이터 정합성이 깨질 수 있음
  • 즉, 다른 프로세스가 접근하려 할 때 이를 막아주는 게 필요
  • Resource queue 에 줄 서서 기다려야 함
  • 오래 기다리는 작업이 필요하면 프로세스는 blocked 되고, 그 이유가 공유데이터 때문인지, 디스크 때문인지, I/O 작업 때문인지 등 확인 후 ➡️ 그 작업이 해당하는 종류의 Queue 로 가서 줄을 선 다음 ➡️ 끝나면 ready queue 로 넘어와 CPU 점유 대기
  • 모든 자원이 놀지 않고 각자의 일을 할 수 있게 배분해주는 것이 중요

 

  • Queue = 운영체제 커널이 본인의 데이터 영역에 자료구조로 큐를 만들고 프로세스 상태를 바꿔가며 ready 상태에게 CPU 주고, blocked된 프로세스에겐 안 줌
  • 운영체제 커널이 각 프로세스마다 그 프로세스 관련 정보(관리 목적)를 두기 위한 PCB 가 있음

 

프로세스 상태도

New

  • 프로세스 생성

 

Ready

  • CPU만 얻으면 실행 가능
  • 여기에선 인스트럭션 실행에 필요한 최소한의 메모리는 가지고 있어야

 

Running

  • CPU를 얻어 실행

 

Blocked

  • 자진해서 CPU를 내어줌(I/O 작업 등 필요하니)

 

Timer interrupt

  • 나는 CPU를 계속 쓰고 싶지만 CPU 사용시간을 나눠 써야함
  • 나에게 할당된 시간을 뺏기면,다시 줄 서야 하는 경우
  • CPU 오래 써야 하는 프로세스는 CPU를 얻었다 뺐겼다 반복

 

Terminated

  • 본인 역할 다 끝날 때

 

Process Control Block

  • 운영체제 커널이 각 프로세스마다 그 프로세스 관련 정보(관리 위한)를 두기 위한 PCB가 있음
  • 프로세스 하나 당 PCB가 있음
  • 프로세스 상태를 나타내고, 프로세스 ID 로 구별
  • 프로세스에게 CPU 주기 위한 스케줄링 정보가 있음

 

라운드 로빙

  • CPU 스케줄링 방식
  • 먼저 온 순서대로 처리하는 게 아니고, 우선순위가 제일 높은 애에게 CPU 넘겨주는 등의 방식

 

문맥 교환

  • 굉장히 중요한 개념
  • 어떤 프로세스가 CPU 장악 후 계속 쓰는 게 아니라, 짧은 간격으로 CPU를 쓰다 뺏겼다 반복
  • CPU를 다시 받아오면 뺏긴 시점을 기억했다 거기서부터 다시 시작하는 거임
  • 사용자 프로세스 하나로부터 다른 프로세스로 넘어가는 과정을 일컫음
  • 어떤 프로세스가 실행 중이면
    • 프로그램 카운터가 어딘가를 가리키고 있고
    • 레지스터에 어떤 값 넣어 실행하고 있고
    • 메모리 맵에 메모리 위치 정보가 있고
    • 이렇게 실행하다 타이머 인터럽트로 CPU 뺏겼다 다시 실행 재개하려면
    • 레지스터에 저장된 값이나 메모리맵이랑 프로그램 카운터 정보도 모두 PCB에 저장해둠
  • CPU 내의 레지스터 등은 하드웨어 자체를 나타냄
  • 문맥 교환될 때는 위 정보들을 저장하는 공간인 커널의 프로세스 PCB에 저장
  • CPU 를 다시 받은 프로세스도 실행을 재개하기 위해 문맥을 찾아야 하는데, 이를 PCB에서 찾아서 하드웨어로 복원시킴

 

메모리 맵

  • 메모리 위치 정보

 

시스템콜

  • 프로세스가 본인이 필요해서 운영체제에게 뭔가 요청할 때

 

인터럽트

  • 하드웨어 인터럽트를 말함
  • 컨트롤러 같은 장치가 CPU에 정보 전달할 목적으로 인터럽트 걺

 

문맥 교환

  • 사용자 프로세스 하나로부터 또다른 사용자 프로세스로 CPU가 넘어가는 과정
  • 시스템콜이나 인터럽트 걸면 사용자 프로세스로부터 운영체제 커널로 CPU가 넘어가는 것이기에, 문맥 교환이 아님
  • 근데 사용자 프로세스가 인터럽트 걸어서 운영체제로 CPU 넘어간 후, 운영체제가 또다른 사용자 프로세스로 CPU를 넘기는 건 문맥 교환이 맞음

 

ISR

  • Interrupt Service Routine

 

타이머 인터럽트

  • CPU를 다른 프로세스에게 넘기기 위한 의도를 가진 인터럽트
  • 타이머 인터럽트가 들어오면 또다른 사용자 프로세스에게 CPU를 넘김 = 문맥 교환

 

  • A 프로세스에서 B 프로세스로 문맥 교환을 해야 하는 경우 오버헤드가 큼
  • Why? 문맥 교환이 일어나면 캐시 메모리를 다 지워야 하기 때문(cache memory flush)
  • 근데 A 프로세스 작업하다 ➡️ 커널로 갔다 ➡️ 다시 A 프로세스로 돌아오면 CPU context 정도만 가지고 있다 save 함

 

 프로세스를 스케줄링하기 위한 큐

 

Ready Queue와 다양한 Device Queue

  • 실제 큐에서 어떻게 관리되고 있는지
  • 디바이스마다 큐가 있고, 큐 헤드와 테일로 구성
  • 큐에는 프로세스를 줄 세운다고 하는데, 운영체제가 프로세스를 관리하는 자료구조, 즉 PCB를 관리
  • PCB에는 포인터가 있는데 그걸 이용해 queue 내의 프로세스들이 연결되는 것(그림의 화살표)

 

프로세스 스케줄링 큐의 모습

  • 프로그램이 시작되면 ready queue 에 줄을 서고
  • 자기 차례가 되면 CPU를 얻고
  • CPU를 점유할 할당 시간이 끝나면
  • 다시 ready queue 에 와서 줄 서야 하고
  • CPU를 점유하다 오래 걸리는 작업 수행해야 하면
  • 그 작업에 해당하는 queue 에 가서 줄 서다 작업 수행하고
  • 그 오래 걸린 작업이 끝나면 CPU 다시 점유해서 마저 실행 후
  • 작업이 다 끝나면 빠져나가기
  • 근데 그림이 좀 잘못됐대
  • 인터럽트 발생 시 CPU를 빼앗기는 것이기에 ready 상태로 그려져 있긴 한데, 정확히는 ready 로 넘어가는 건 아님(다음 강의에서 다룸)
  • 프로세스가 CPU 잡고 있다가 자식 프로세스를 만들 수 있음(프로세스 생성 관련 다음 강의에서 다)

 

스케줄러

  • 순서를 정해줌
  • 시스탬 내의 스케줄러 = 각각의 자원 별로 어떤 일을 할지, 얼마 동안 실행시킬지 등을 정함

 

단기 스케줄러

  • CPU 스케줄러
  • 굉장히 짧은 시간 단위로 스케줄이 이루어짐
  • 스케줄이 이루어지는 단위가 밀리세컨드
  • 굉장히 자주 이루어짐
  • 다음에 어떤 프로세스에 CPU 줄지 정함

 

장기 스케줄러

  • 단기 스케줄러의 반대
  • 어떤 프로세스에게 줄지 결정
  • = Job 스케줄러
  • 프로세스가 시작돼 new 상태였다가 ready 로 넘어가는 과정에서 어떤 일이 일어나느냐, 뭘 admitted 하느냐, 메모리에 올라가는 걸 admit 하는 거임
  • 처음 프로세스가 시작된 후 메모리를 얻지 못하면 아무 일도 발생하지 않기에, 메모리에 올라가는 걸 허락해주면 그때부터 작업 시작할 수 있음
  • 이 스케줄러가 프로세스에 메모리를 줄지 안 줄지를 결정함
  • Degree of multi-programming – 메모리에 여러 프로그램이 동시에 올라갈 때 총 몇 개의 프로그램이 올라가 있는지를 나타내는 것
  • 메모리에 올라가는 프로세스의 수를 제어함
  • 메모리에 너무 많은 프로그램이 동시에 올라가면 컴퓨터 전체의 성능이 안 좋아짐 / 너무 적게 올라가도 안 좋아짐 = 그 프로그램이 CPU 쓰다가 I/O 하러 가면 CPU는 놀게 됨

 

중기 스케줄러

  • 지금 우리가 사용하는 시스템은 degree of multi-programming 을 어떻게 조절할까? 장기 스케줄러 역할 없이 프로그램이 시작되자마자 바로 ready 로 올라가거든
  • 바로 ready 로 올라가면 메모리에 너무 많은 프로그램이 올라가 문제될 수 있는데, 이제 중기 스케줄러가 이를 조절해줌 = swapper
  • 스와퍼가 일부 프로그램을 골라 메모리에서 통째로 쫓아냄, 이렇게 degree of multi-programming 수를 조절해 전체 시스템 성능을 향상시킴
  • 예전엔 장기 스케줄러로 초반부터 메모리에 올라갈 것들을 정해줬지만, 요즘은 시작 때 무조건 다 올려준 다음, 너무 많은 프로그램이 메모리에 있다 싶으면 몇 개는 쫓아내는 시스템

 

Implementation of Threads

 

프로세스의 상태

  • 중기 스케줄러로 인해 프로세스 상태가 추가됨
  • 중기 스케줄러로 인해 메모리를 통째로 뺏긴 경우, 그 상태를 표현할 길이 없어서 생겨남
  • CPU 관점에서의 상태 – running, ready, blocked
  • Running = CPU 잡고 있는 상태
  • Blocked = 프로그램 본인이 CPU를 잡고 일을 하다가 I/O 작업 같은, 오래 걸리는 작업 위해 다른 곳에서 작업하는 상황
  • Suspended = CPU 뿐만 아니라 외부에서 이 프로세스를 강제로 정지시켜놓은 상태, 메모리에서 쫓겨나 디스크로 swap out 된 상태
  • Break key 누르면 프로세스가 끝난 건 아닌데 잠깐 정지시킬 수 있음, 그럴 때도 프로세스는 메모리를 통째 잃고 suspended 상태 됨
  • 사람이 잠시 정지된 프로그램을 재개시켜야 suspended 상태에서 벗어날 수 있음

 

프로세스 상태도

  • 여기서의 그림은 사용자 프로그램의 상태도를 의미하지, 운영체제의 상태도를 말하는 게 아님

 

User mode

  • 프로세스가 CPU 가지고 있으면서 본인 코드 실행시킬 때

 

Monitor mode

  • 본인이 어떤 일을 할 수 없어 운영체제에 요청해 시스템콜을 하면, 실질적으론 운영체제의 코드가 돌고 있을 때
  • 위 상황은 커널 모드에서 러닝하고 있다 != 운영체제가 러닝하고 있다
  • 인터럽트 들어오면 사용자 프로그램이 실행되다 운영체제 커널의 코드가 실행되는데,
    • 이는 interrupt service routine 이 실행되는 거고,
    • 외부의 요인에 의해 인터럽트가 들어오는 거지만 그래도 user mode 가 계속 돌아가고 있다고 간주함
    • 단지 커널 모드(모니터 모드)에서 러닝하고 있다고 부를 뿐
  • 사용자 프로그램의 상태도를 의미하지, 운영체제의 상태도를 말하는 게 아님!

 

Suspended

  • Blocked 에서 suspended 되었는지 / ready 에서 되었는지에 따라 차이가 있음
  • 외부적인 이유로 프로세스가 완전 얼어붙으면 inactive
  • 외부에서 프로세스를 정지시켜 다시 외부에서 재개시켜줘야 active 상태로 돌아갈 수 있음

 

Suspended blocked

  • I/O 같이 오래 걸리는 작업이 끝나면 suspended ready 상태로 바뀔 순 있음
  • suspended 는 기본적으로 메모리를 아예 잃어버리는 swap out 상황으로, CPU 관점에서는 아무 일을 할 수는 없음
  • 근데 I/O 작업 등이 진행 중이었다면 그건 계속 이어갈 수 있기에 suspended ready 상태로 바뀔 수 있다는 의미

# 3-2 Process 2 & 3-3 Process 3

동기식 입출력과 비동기식 입출력

동기식 입출력

  • 프로세스 입장에서 먼저 살펴보기
  • 프로세스가 입출력 요청하면, 이건 운영체제 통해 해야 함, 본인이 직접 못함
  • 프로세스가 운영체제에 입출력 요청하면 이 작업은 오래 걸려서 끝날 때까지 기다려야 함

 

비동기식 입출력

  • 입출력 진행되는 동안 그 프로세스가 곧바로 CPU 잡아 인스트럭션 실행하면 비동기식

 

동기식 입출력 구현 방법

  • 프로세스가 I/O 요청 후, I/O가 완료될 때까지는 일 못함
  • 구현 방법 1 = 그동안 CPU 가지고 있는 상태(CPU를 쓰면서 = 낭비하면서)로 기다림
  • 구현 방법 2 = 그동안 CPU를 다른 프로세스에 넘겨줌(어차피 I/O 요청한 프로세스가 일 못하니까, 더 효율적으로 일하기 위해 다른 프로세스에 CPU 넘겨줌)

 

Thread

쓰레드

  • CPU를 수행하는 단위
  • 쓰레드의 구성 = 각 쓰레드가 독립적으로 가지는 것
  • 쓰레드가 동료 쓰레드와 공유
    • = 쓰레드들 간에 공유하는 것
    • = task
    • = 하나의 프로세스 안에 여러 개의 프로세스가 있고, task 는 한 개로 이루어진 구조
  • Lightweight 프로세스 라고도 부름
  • 프로세스보다 쓰레드를 여러 개 두는 게 훨씬 가볍기에
  • 프로세스 내부의 CPU 수행 단위가 여러 개 있는 것
  • 코드 데이터 stack 으로 구성된 주소공간이 프로세스마다 만들어짐
  • 프로세스 하나를 관리하기 위해 운영체제 내부에 PCB라는 걸 둠으로써 프로세스 상태나 아이디를 나타냄
  • 프로세스가 여러 개 있고, 그걸 별도의 프로세스로 만들면 프로세스마다 별도의 주소공간이 만들어져 메모리 낭비됨
  • 같은 일을 하는 프로세스 여러 개 띄워두고 싶으면 메모리 공간은 하나만 띄우고, 각 프로세스마다 다른 코드를 실행할 수 있게 해주는 게 쓰레드의 개념
  • 프로세스는 하나만 띄워두고 현재 CPU가 코드의 어느 부분을 실행 중인지, 즉 프로그램 카운터만 여러 개 둔다,
  • 즉, 프로세스 하나에 CPU 수행 단위만 여러 개 두고 있는 것을 쓰레드라 부름

 

프로그램 카운터

  • 메모리의 어느 부분을 실행 중인지 가리키는 레지스터
  • 프로세스 하나 주어지면 그 프로세스만의 코드, 데이터, 스택이 만들어지고
  • PCB에서 현재 메모리의 어느 부분을 실행 중인지 프로그램 카운터가 가리키고 있음
  • CPU 수행 위해(= 인스트럭션 실행 위해), 코드의 어느 부분을 실행하는지 가리키는 프로그램 카운터 있어야
  • CPU 에서 실행되면서 메모리의 어떤 레지스터 값을 실행하고 있을 거임
  • CPU 수행 단위마다(= 각 쓰레다마다), 현재 레지스터에 어떤 값을 넣고 프로그램 카운터가 어느 부분을 가리키며 실행하고 있는지를 별도로 유지

 

쓰레드들 간에 공유하는 정보

  • 프로세스 하나에서 공유할 수 있는 건 최대한 공유
  • 메모리 주소 공간 공유
  • 프로세스 상태도 공유
  • 프로세스가 사용하는 각종 자원도 공유

 

쓰레드들 간에 별도로 가지고 있는 정보

  • CPU 수행과 관련된 정보
  • 프로그램 카운터
  • 레지스터
  • 스택 등
  • 쓰레드 하나가 코드 어느 부분을 실행하다 함수 호출 및 리턴하면 그 정보를 스택에 쌓아야
  • CPU 수행 단위가 여러 개면 스택도 별도로 둬야

 

장점1) 하나의 쓰레드가 blocked 일 때 다른 하나는 running = 응답 시간을 빠르게 해줌

  • 네트워크 통해 웹페이지 읽어올 때의 작업도 I/O 작업
  • 웹페이지를 읽어오는 시간은 오래 걸리니, 내 웹브라우저는 blocked 상태가 됨
  • 사용자 입장에서는 웹페이지를 다 읽어오기까지 화면에 아무 것도 나타나지 않기에 답답함
  • 웹브라우저를 여러 개의 쓰레드를 사용해 구성하면 또다른 쓰레드가 이미 읽어온 텍스트라도 화면에 디스플레이해줄 수 있음 = 결과를 보다 빨리 볼 수 있음

장점2) 하나의 프로세스 내에 여러 쓰레드를 두면 자원 절약 효과

  • 같은 일을 하는 작업을 별도의 프로세스로 만들게 되면 각각의 메모리에 프로세스가 올라가기에 메모리 등 자원이 낭비됨
  • 프로세스 하나가 만들어지면 프로세스만의 독자적 주소 공간이 만들어지는데, 이는 메모리를 차지함
  • 각각의 코드 데이터 스택을 메모리에 가지고 올라가기에 메모리 낭비 심함

장점3) CPU가 여러 개 달린 컴퓨터에서 얻을 수 있는 장점 = 병렬성

  • 행과 열을 곱하는 게 독립적 연산인데, CPU가 하나면 순차적으로 실행해야 하지만, 서로 다른 CPU에서 연산 실행 후 합쳐주면 더 빠른 결과가 나올 수 있음
  • 여러 개의 쓰레드 사용 시 각 쓰레드들이 서로 다른 CPU에서 실행되고, 그럼 parallel 하게(병렬적으로) 실행되며, 더 빠른 결과 낼 수 있음

 

PCB

  • 프로세스마다 하나의 PCB가 만들어지는데, 운영체제가 이를 관리함
  • 프로세스가 하나면 PCB는 하나만 만들어짐
  • 근데 이 프로세스 안에 쓰레드가 여러 개면 CPU 수행과 관련된 정보만 각각 쓰레드마다 별도의 카피를 가지게 됨 = 프로그램 카운터, 레지스터 정보 등
  • 쓰레드는 프로세스마다 가지고 있는 정보 중 CPU 관련 정보만 각 쓰레드마다 별도로 가지게 됨

 

프로세스

  • 메모리 주소 공간에 코드, 데이터, 스택이 있고
  • 각 프로세스마다 PCB 있고
  • 이때 쓰레드는 프로세스 안에서 독자적으로 가져야 할 정보만 별도로 가짐 = PCB의 프로그램 카운터, 레지스터
  • 주소 공간에서는 코드와 데이터는 공유하고, 스택 부분만 쓰레드마다 별도로 가짐

 

Single and Multi-threaded Processes

Single threaded

  • 쓰레드 하나
  • 코드, 데이터 등의 자원은 쓰레드들이 공유

 

Multi-threaded

  • 쓰레드 여럿
  • 레지스터 set, 스택 등은 쓰레드마다 별도로 가짐
  • 그림 속 바이너리는 일단 무시하기

 

Benefits of Threads

빠른 응답성

  1. 내가 웹브라우저 띄우고, 포털 사이트 홈페이지 주소를 치면 제일 먼저 그 홈페이지에서 HTML 문서 날아옴
  2. 그 HTML을 웹브라우저 화면에 디스플레이하려 하니 그 문서 안에는 여러 임베디드된 이미지가 있음
  3. 그것들을 웹브라우저가 해석해서 이미지를 웹서버에게 다시 요청
  4. 그 이미지들이 다 도착하면 HTML 화면에 텍스트, 이미지 등 넣어 문서 완성 후 사용자에게 보여줌
  5. 이 과정에서 HTML 문서 읽은 후 그 안의 이미지는 다시 웹서버에 요청 = 오래 걸리는 작업이기에 blocked 시키면 사용자는 답답함
  6. 그래서 이걸 여러 쓰레드로 만들면
    1. HTML 문서 가져와서 그 안의 이미지 파일을 웹서버에 다시 요청하는 순간 원래 그 프로세스는 blocked 되는데
    2. 여러 쓰레드에서 그 요청을 한 쓰레드만 blocked 되고
    3. 다른 쓰레드가 이미 읽어온 HTML 문서라도 화면에 디스플레이해주면 사용자 입장에서는 답답함이 덜함
  7. 이미지 파일을 읽는 동안 = I/O 실행시키는 동안, 이 프로그램을 blocked 시키지 않고 텍스트라도 먼저 가져와 보여줌
  8. 이미지 가져오는 작업과 텍스트 가져오는 작업이 개별적으로 진행됨
    • = 비동기식 작업
    • = 쓰레드 이용한 응답성 향상

 

자원 공유

  • 하나의 프로세스에서 CPU 수행 단위만 여러 개 두면 코드/데이터/각종 자원은 쓰레드들이 공유하며 자원을 효율적으로 쓰는 효과 얻음

 

경제성

  • 프로세스를 하나 만든다 = 오버헤드 상당히 큼
  • 프로세스 내에 쓰레드 추가한다
    • = 오버헤드 그다지 크지 않음
    • = 쓰레드 간 CPU 스위치가 일어나는 건 간단함 
    • = 동일한 주소 공간을 쓰고 있기에 대부분 문맥을 그대로 사용
  • 컨텍스트 스위치 
    • = 하나의 프로세스에서 또다른 프로세스로 CPU가 넘어감 
    • = 오버헤드 상당히 큼 
    • = CPU 관련 정보 저장, 캐시 메모리 플러시 등
  • 같은 일 하는 작업 만들 땐 가능하면 여러 개의 쓰레드를 만드는 게 효율적

 

Multi-processor 아키텍처

  • 프로세스는 하나지만 그 안에 여러 개의 쓰레드를 두면, 각각의 쓰레드가 서로 다른 CPU에서 병렬적으로 일할 수 있음
  • 굉장히 큰 행열을 곱한다던지

 

Implementation of Threads

커널 쓰레드

  • 쓰레드가 여러 개 있다는 사실을 운영체제 커널이 알고 있음
  • 하나의 쓰레드에서 다른 쓰레드로 CPU가 넘어가는 것도 커널이 CPU 스케줄링하듯 넘겨주게 됨

 

유저 쓰레드

  • 라이브러리 통해 지원됨
  • 프로세스 안에 쓰레드가 여러 개 있다는 걸 운영체제는 모름
  • 유저 프로그램이 라이브러리의 지원을 받아, 스스로 여러 개의 쓰레드를 관리
  • 어떻게 보면 커널이 모르고 있고, 커널이 볼 땐 일반적인 프로세스 같지만, 프로세스 본인이 내부에서 CPU 수행 단위를 여러 개 두면서 관리하기에, 약간의 구현 상의 제약점이 있을 수는 있음

댓글