프로세스와 스레드

Yeji·2023년 6월 30일
0

운영체제

목록 보기
3/3

1. 프로세스와 스레드

프로세스

[프로세스]
CPU에서 실행되고 있는 프로그램

프로세스는 한정된 시간동안 CPU를 차지하고
타이머 인터럽트가 발생하면 다른 프로세스에게 차례를 넘긴다.

스레드

[스레드]
프로세스를 구성하는 실행 흐름의 단위

스레드에는 스레드 ID, 레지스터 값, 스택 등 실행에 필요한 최소한의 정보가 담겨있다.

PCB(Process Control block)

프로세스를 관리하기 위해 사용하는 자료구조를 말한다.

프로세스 관련 메타데이터를 담고 있으며, 운영체제마다 어떤 정보를 담고 있는지에 차이가 있다.
프로세스 생성시 커널 영역에 생성되고, 프로세스 종료시 폐기된다.
[메타 데이터]
데이터를 설명하는 데이터.
대량의 데이터 가운데에서 원하는 정보를 효율적으로 찾아내기 위해 일정한 규칙에 따라 콘텐츠에 대해 부여되는 데이터다.

인스타그램의 해쉬태그를 예로 들 수 있다.

PCB가 담고 있는 정보는 다음과 같은 것들이 있다. (운영체제마다 상이할 수 있다.)

  1. 프로세스 스케줄링 상태 : 프로세스가 CPU에 대한 소유권을 얻은 이후의 상태
  2. PID : 프로세스 고유 아이디
  3. 프로그램 카운터 : 프로세스에서 실행해야 할 다음 명령어의 주소에 대한 포인터
  4. CPU 레지스터 : 프로세스를 실행하기 위해 저장해야 할 레지스터에 대한 정보
  5. CPU 스케줄링 정보 : CPU 스케줄러에 의해 중단된 시간 등에 대한 정보
  6. I/O 상태 정보 : 프로세스에 할당된 I/O 디바이스 목록
    ...

2. Context Switch

타이머나, 입출력 장치로 인한 인터럽트 등이 발생했을 때 프로세스를 교환하는 과정을 말한다.

Context는 프로세스가 다음 차례시 실행을 재개하기 위해 필요한 정보를 말한다.

프로세스의 실행이 어떤 인터럽트에 의해 중단되고 다른 프로세스가 실행될 때 필요한 정보가 바로 PCB다.

운영체제는 A프로세스에서 B프로세스로 교환을 시킬 때,

1. A의 중간 정보, 즉 PCB를 저장한다.
2. B의 PCB를 복구해 B 프로세스를 실행한다.

컨텍스트 스위칭은 PCB를 저장하고 복구하는 과정에서 유휴 시간이 발생하며, 캐시미스가 발생하기도 한다.

캐시미스란, 프로세스가 교환될 때 기존 캐시된 메모리를 초기화한다는 것이다.

CPU는 새로운 프로그램이 실행되기 위해 캐시와 메모리 매핑을 초기화하며 아무 작업도 하지 못한다.

스레드에서의 Context Switch

Context Switching은 스레드에서도 일어난다.
그러나 스레드는 스택 영역을 제외한 모든 메모리를 공유하기 때문에 프로세스 Context Switching보다 비용도 적고 시간도 덜 걸린다.

3. 프로세스 상태

생성

프로세스가 메모리에 적재되어 PCB를 할당받은 상태다.

fork()exec() 함수를 통해 프로세스를 생성한다.

[fork]
부모가 자신의 복사본을 자식 프로세스로 생성하는 것을 말한다.
메모리 공간을 할당받으며, PID가 다른다.

[exec]
자신의 메모리 공간을 새로운 프로그램으로 덮어쓰는 것을 말한다.

fork()와 exec()의 반복으로 시스템의 계층 구조가 형성된다.

준비

CPU를 할당 받아 사용할 수 있지만 자신의 차례가 아니기에 기대리는 상태다.

실행 중인 프로세스에서 타이머 인터럽트가 발생하면 다시 대기 상태가 된다.

준비상태에서 실행상태가 되는 것을 디스패치라고 한다.

실행

CPU를 할당받아 실행중인 상태다.

  • 타이머 인터럽트 발생시 다시 준비상태로 간다.
  • 프로세스 실행 중 입출력장치 사용시 대기 상태로 간다.

대기

프로세스 실행 중 입출력 장치를 실행하는 경우다.

  • 입출력 작업은 CPU에 비해 매우 느리기 때문에 CPU 낭비 방지를 위해 대기 상태로 전환한다.
  • 입출력 작업이 끝나면 다시 준비 상태로 들어간다.

종료

프로세스가 종료된 상태다.
메모리 영역이 정리되고 PCB가 폐기된다.

4. 프로세스 메모리 구조

스택

지역변수, 매개변수 등 데이터가 일시적으로 저장되는 공간이다.

프로그램을 만드는 사용자, 즉 프로그래머가 직접 할당할수 있는 저장공간이다.

일반적으로 스택영역은 높은 주소에서 낮은 주소로 할당이 되고,
힙영역은 낮은 주소에서 높은 주소르 할당이 된다.

이는 둘 다 동적인 특성을 가지고 있기 때문에 메모리 영역의 충돌을 방지하기 위해 그렇다.

이 블록을 기준으로

위는 프로그램 실행 중 크기가 변할 수 있는 동적 할당 영역이고

아래는 크기가 변하지 않는 정적 할당 영역이다.

데이터영역

일시적인 데이터가 아닌 프로그램이 실행되는 동안 유지할 데이터를 저장한다.

전역 변수 등이 있다.

BSS영역

초기화되지 않은 변수가 0으로 초기화되어 저장된다.

데이터 영역

0이 아닌 다른 값으로 할당된 변수가 저장된다.

코드영역 (Text 영역)

기계어로 이루어진 명령어를 저장하는 곳이다.
데이터가 아닌 CPU가 실행할 명령어가 담기기 때문에 ready only로 쓰기가 금지된 영역이다.

5. 프로세스 계층 구조

프로세스는 실행 중 시스템콜을 통해 다른 프로세스를 생성할 수 있다.
앞서 언급했듯 fork()를 통해 부모 프로세스는 자식 프로세스를 생성할 수 있다.

[부모 프로세스]
새 프로세스를 생성한 프로세스

[자식 프로세스]
부모 프로세스에 의해 생성된 프로세스

부모와 자식 프로세스는 별개의 프로세스기 때문에 각자 다른 PID를 갖는다.
한편 일부 운영체제는 자식 프로세스에 PPID(부모 PID)를 명시하기도 한다.

6. 멀티 프로세스와 멀티 스레드

[멀티 프로세스]
여러개의 프로세스를 실행시켜 동시에 두 가지 이상의 일을 하는 것

[멀티 스레드]
하나의 프로세스를 여러 스레드로 실행하는 것을 말한다.
여러 스레드가 프로세스의 자원 (코드, 데이터 영역)을 공유하며 실행된다.

웹브라우저는 멀티 프로세스 구조를 가지고 있으며 그 구성요소는 다음과 같다.

  • 브라우저 프로세스 : 네트워크 요청이나 파일 접근 같은 권한을 담당한다.
  • 렌더러 프로세스 : 웹사이트에 보이는 부분을 담당한다.
  • 플러그인 프로세스 : 웹사이트에서 사용하는 플러그인을 담당한다.
  • GPU 프로세스 : GPU를 이용해 화면에 그려내는 것을 담당한다.

렌더러 프로세스는 멀티 스레드 구조를 가지고 있으며 메인 스레드, 워커 스레드, 컴포지터 스레드, 레스터 스레드가 있다.

멀티 프로세스와 멀티 스레드의 차이

멀티 프로세스는 똑같은 프로그램을 단일 스레드로 여러 번 동작시킨다.
반면 멀티 스레드는 하나의 프로세스를 여러 스레드로 실행한다.

print() 함수를 실행시킨다 했을 때 멀티 프로세스는 fork()가 세 번 일어나지면,
멀티 스레드는 하나의 프로세스 안에서 print()를 세 개의 스레드로 실행시킨다.

[멀티 프로세스]
1. 자원을 공유하지 않고 독립 실행된다.
2. 다른 프로세스에 지장이 적다.

[멀티 스레드]
1. 스레드는 실행을 위해 꼭 필요한 값만 가질뿐 프로세스 자원을 공유한다.
2. 프로세스의 변화를 모든 스레드가 공유하기 때문에 협력과 통신에 유리하다.
3. 하나의 스레드에 문제가 발생했을 시 전체 프로세스에 영향을 줄 수 있다.

7. IPC(Inter Process Communication)

IPC는 프로세스끼리 데이터를 주고 받고, 공유 데이터를 관리하는 것을 말한다.

프로세스는 기본적으로 자원을 공유하지 않는다.
그러나 스레드만큼 쉽고 빠른 것은 아니지만 아예 불가한 것은 아니다.
우리에게 가장 익숙한 클라이언트-서버 통신도 IPC의 일종이다.

IPC의 종류로는 다음과 같은 것들이 있다.

  • 공유메모리
  • 파일
  • 소켓
  • 익명 파이프
  • 명명 파이프
  • 메시지 큐

공유메모리(shared memory)

여러 프로세스가 동일한 메모리에 대해 접근 권한을 갖고 서로 통신할 수 있도록 하는 것을 말한다.

어떤 매개체를 통해 프로세스끼리 데이터를 주고 받는 것이 아니라 메모리 자체를 공유하기 문에

  1. 불필요한 복사의 오버헤드가 발생하지 않아 가장 빠르고
  2. 여러 프로세스가 같은 메모리를 공유하기 때문에 동기화가 필요하다.

하드웨어 관점에서 공유 메모리는 CPU가 접근할 수 있는 메모리인 RAM을 의미하기도 한다.

파일

디스크에 저장된 데이터 또는 파일 서버에서 제공한 데이터로 프로세스 간 통신을 한다.

소켓

동일한 컴퓨터의 다른 프로세스, 혹은 다른 네트워크 상의 컴퓨터로 네트워크 인터페이스를 통해 전송하는 데이터를 의미한다.

익명파이프(unnamed pipe)

프로세스 간 FIFO(First In First Out) 방식으로 읽히는 임시 공간인 파이를 기반으로 데이터를 주고 받는다.

단방향이며, 읽기전용과 쓰기전용 파이프를 만들어서 작동한다.
부모 자식 프로세스 간에만 사용할 수 있으며 다른 네트워크 상에서는 사용이 불가하다.

명명된파이프(named pipe)

서버용 파이프와 클라이언트 파이프를 두어 하나 이상의 파이프 인스턴스를 기반으로 통신한다.

컴퓨터의 프로세스끼리는 물론, 다른 네트워크 상의 컴퓨터와 통신이 가능하다.

메시지 큐

메시지를 Queue라는 자료 구조 형태로 관리하는 것을 의미한다.

커널에서 전역적으로 관리되며 다른 IPC 방식에 비해 간단하게 메시지 큐에 접근할 수 있다.

공유 메모리로 IPC 통신을 구현했을 때 데이터 쓰기읽기 빈도가 높으면
동기화 문제로 기능을 구현하는 것이 매우 복잡해지는데, 그 대안으로 메시지 큐를 사용하기도 한다.

8. 공유자원과 임계영역

[동기화]

프로그램의 수행 시기를 맞추는 것

공유자원(shared resource)

시스템 내의 프로세스와 스레드가 접근할 수 있는 자원을 의미한다.
모니터, 프린터, 메모리, 파일 등이 있다.

여러 개의 프로세스가 같은 자원에 접근하는 상황을 경쟁 상태(race condition)라고 한다.
경쟁 상태에서 프로세스의 실행 타이밍과 순서로 인해 예상했던 결과값이 달리지기도 한다.

예를 들어 A와 B가 누를 때마다 1씩 더해지는 버튼을 누른다고 했을 때, 20번을 눌렀다면 결과값은 20이 나와야한다.
그러나 A와 B가 동시에 누르는 경우도 존재하기 때문에 결과값은 20이 나오지 않는다.

임계영역(critical section)

공유데이터의 일관성을 보장하기 위해 하나의 프로세스 혹은 스레드만 진입해서 실행 가능한 영역을 말한다.

임계 영역을 보장하기 위해서 잠금(lock)을 사용하며 방법은 세 가지가 있다.

  1. 뮤텍스
  2. 세마포어
  3. 모니터

뮤텍스(Mutex)

상호배제를 위한 동기화 도구.
공유자원을 사용하기 전에 잠금 설정, 사용한 후에 잠금 해제

잠금설정이 되면 다른 스레드는 잠긴 코드 영역에 접근할 수 없다.
뮤텍스는 동시에 접근해서는 안 되는 공유자원이 하나만 있는 경우에 사용할 수 있다.

세마포어(Semaphore)

여기서는 주로 카운팅 세마포어에 대해 다루겠다.

공유 자원이 여러 개 있는 경우에도 적용이 가능한 동기화 도구.

상호 배제를 위한 동기화뿐만 아니라 실행 순서를 동기화한다.  

S는 사용 가능한 공유 자원의 개수,
먼저 실행할 프로세스 뒤에 signal()을 다음에 실행할 프로세스 앞에 wait()을 붙인다.

임계 구역 앞에서 멈춤 신호 wait()을 받으면 잠시 기다리고
임계 구역 앞에서 가도 좋다는 신호 signal()을 받으면 임계 구역에 진입한다.

wait

1. 만일 임계 구역에 진입할 수 있는 프로세스 개수(S)가 0이하라면
2. 사용할 수 있는 자원이 있는지 반복적으로 확인하고
3. 임계 구역에 진입할 수 있는 프로세스가 하나 이상이면 S를 감소시키고 임계 구역에 진입한다.

signal

1. 임계 구역에서 작업을 마친 뒤 S를 1 증가시킨다.

그러나 세마포어는 임계구역 앞뒤로 wait()과 signal()을 명시적으로 호출해줘야 하기 때문에
프로그램의 규모가 커지면서 오류가 발생할 경우 디버깅 하기가 힘들어 사용자 입장에서 다루기 불편하다.

모니터

사용자(개발자)가 다루기 편한 동기화 도구.
모니터 안에는 하나의 프로세스만 있을 수 있다.

상호배제를 위한 동기화와 실행순서를 위한 동기화 두가지 모두를 제공한다.

상호배제를 위한 동기화

모니터는 공유자원과 공유자원에 접근하기 위한 통로를 묶어서 관리한다.
또한 공유자원에 접근하고자 하는 프로세스와 스레드는 반드시 특정 인터페이스를 통해서만 접근할 수 있다.

  • 인터페이스를 위한 큐가 존재하고
  • 공유자원에 접근하고자 하는 프로세스를 큐에 삽입하고
  • 큐에 삽입된 순서대로 공유 자원을 이용한다.

예를 들어 프로세스 A와 B가 있을 때 B가 무조건 먼저 실행되어야 한다고 치자.

  1. A.wait() 조건 변수를 통해 대기 상태로 변경하고 A를 조건 변수에 대한 큐에 삽입한다.
  2. 그러면 다음 차례에 있던 B가 실행을 시작한다.
  3. B가 실행이 끝나고 B.signal()을 호출하면 이어서 A가 모니터 안으로 들어와 실행된다.

9. 교착 상태(deadlock)

두 개 이상의 프로세스가 서로가 가진 자원을 기다리며 중단된 상태를 말한다.

교착상태는 다음과 같이 네 가지 조건이 모두 만족해야 일어난다.

  1. 상호 배제 : 한 프로세스가 사용하는 자원을 다른 프로세스가 사용할 수 없는 상태
  2. 점유와 대기 : 자원을 할당 받은 상태에서 다른 자원을 할당 받기를 기다리는 상태
  3. 비선점 : 어떤 프로세스도 다른 프로세스의 자원을 강제로 빼앗지 못하는 상태
  4. 원형 대기 : 자원 할당 그래프가 원의 형태를 띄는 상태 즉, 서로가 서로의 자원을 요구하는 상태

교착상태의 해결 방법으로는 다음과 같은 것들이 있다.

  1. 교착 상태 가능성이 없을 때만 자원을 할당한다.
    프로세스당 요청할 자원의 최대치를 통해 자원 할당 가능 여부를 파악하는 '은행원 알고리즘'을 쓴다.
    [은행원 알고리즘]
    총 자원의 양과 현재 할당 가능한 자원의 양을 기준으로 안정 또는 불안정 상태로 나누고
    안정 상태로 가도록 자원을 할당하는 알고리즘
  2. 교착 상태가 발생하면 사이클이 있는지 찾아보고 이에 관련된 프로세스를 한 개씩 지운다.
  3. 교착 상태는 매우 드물게 일어나기 때문에 이를 처리하는 비용이 더 크다. 따라서 교착 상태에 마주하면 운영체제는 사용자의 작업을 종료시킨다.

10. CPU 스케줄링 알고리즘

CPU는 CPU 스케줄링 알고리즘에 따라 프로세스가 해야 할 일을 스레드 단위로 CPU에 할당한다.

CPU 스케줄링의 기본적인 목표는 다음과 같다.
1. CPU 이용률이 높게
2. 주어진 시간에 많은 일을 하게
3. 준비 큐(ready queue)에 있는 프로세스는 적게
4. 응답시간은 짧게

비선점형 방식

프로세스 스스로 CPU 소유권을 포기하는 방식으로,
강제로 프로세스를 종료하지 않기 때문에 컨텍스트 스위칭으로 인한 비용이 적다.

FCFS(First Come, First Serve)

  • 가장 먼저 온 것을 가장 먼저 처리하는 알고리즘이다.
  • 길게 수행되는 프로세스가 있다면 준비 큐에서 오래기다리는 현상이 발생한다.

SJF(Shortest Job First)

  • 실행시간이 가장 짧은 프로세스를 가장 먼저 실행하는 것이다.
  • 평균 대기 시간이 짧지만 긴 시간을 가진 프로세스가 실행되지 않아버리는 현상이 발생한다.
  • 그러나 실제로는 실행시간을 알 수 없기 때문에 과거 실행했던 시간을 토대로 추측해서 작동한다.

우선순위

  • 기존 SJF의 문제점(실행시간이 긴 프로세스는 실행되지 않는 현상)을 보완한 알고리즘이다.
  • 오래된 작업일수록 우선순위를 높인다.

선점형 방식

현대 운영체제가 쓰는 방식으로,
지금 사용하고 있는 프로세스를 알고리즘에 의해 중단시키고 강제로 다른 프로세스에 CPU 소유권을 할당한다.

라운드로빈(Round Robin)

  • 현대 컴퓨터가 쓰는 우선순위 스케줄링의 일종이다.
  • 각 프로세스에게 동일한 시간을 할당하고 그 시간 안에 끝나지 않으면 준비 큐의 뒤로 보낸다.
q만큼의 시간이 할당되고 N개의 프로세스가 운영된다고 하면 대기시간은 (N-1) * q다.
  • 할당시간이 너무 크면 FCFS가 되어버리고 짧으면 컨텍스트 스위칭이 잦아져 오버헤드(비용이 커짐)가 발생한다.
  • 전체 작업시간은 길어지지만 평균 응답시간은 짧아진다는 특징이 있다.
  • 로드밸런서의 트래픽 분산 알고리즘으로도 쓰인다.

SRF(Shortest Remaing time First)

  • 실행 중간에 더 짧은 작업이 들어오면 수행하던 프로세스를 중지하고 더 짧은 프로세스를 실행하는 알고리즘이다.

다단계큐

  • 우선순위에 따른 준비 큐를 여러 개 두어 큐마다 다른 알고리즘(라운드로빈, FCFS 등)을 적용하는 것을 말한다.
  • 우선순위가 낮은 큐에서 CPU를 선점해 작업을 수행 중이더라도 우선순위가 높은 큐에 프로세스가 들어오면 CPU를 빼앗는다.
  • 큐 간 프로세스 이동이 되지 않아 스케줄링 부담이 적지만 유연성이 떨어지는 단점이 있다.
profile
채워나가는 과정

0개의 댓글