OS03. 프로세스와 스레드

HoyongLee·2022년 9월 13일
0

프로세스란 컴퓨터에서 실행되고 있는 프로그램을 말한다. CPU 스케줄링의 대상이 되는 task라는 용어와 거의 같은 의미를 가진다. 스레드는 프로세스 내 작업흐름이다.

프로그램이 인스턴스화 되면 프로세스가 되어 메모리에 올라간다. 이후 운영체제의 CPU 스케줄러에 따라 CPU가 프로세스를 실행한다.

프로세스와 컴파일 과정

컴파일이란, 고수준 언어로 작성된 소스 코드를 컴퓨터가 이해할 수 있는 기계어로 번역하여 실행될 수 있는 파일로 만드는 것

(출처 : https://bradbury.tistory.com/226)

전처리

전처리기를 통해 소스 코드 파일을 전처리된 소스 코드 파일로 바꾸는 과정.

  • 주석 제거
  • 헤더 파일 삽입 : #include에 해당하는 헤더 파일을 찾아 복사하여 소스 코드에 삽입한다. 헤더 파일 내의 함수는 링킹 과정에서 실제 함수가 정의된 오브젝트 파일과 결합한다.
  • 매크로 치환 : #define에 정의된 이름을 찾아 값을 모두 바꾼다.

컴파일

문법 검사, 오류 처리, 코드 최적화 작업을 진행한다. Static 영역(Data, BSS)의 메모리 할당을 진행한다.

어셈블리

어셈블러를 통해 어셈블리어 파일을 오브젝트 파일(기계어로 이루어짐.)로 변환한다.

링킹

링커를 통해 프로그램 내에 있는 라이브러리 함수 혹은 다른 파일들과 오브젝트 파일을 결합하여 실행 파일을 만든다.

정적 라이브러리와 동적 라이브러리

  • 정적 라이브러리 : 프로그램 빌드(컴파일 타임) 시 라이브러리가 제공하는 모든 코드를 실행 파일에 넣는 방식. 시스템 환경 등 외부 의존도가 낮지만, 코드 중복이 발생할 수 있어 메모리 효율성이 떨어진다.
  • 동적 라이브러리 : 프로그램 실행(런타임) 시 필요할 때만 dll이라는 함수 정보를 통해 참조하는 방식이다. 메모리 효율성이 좋지만, 외부 의존도가 높아진다.

프로세스의 상태

생성 상태

프로세스가 생성된 상태를 의미한다. fork() 혹은 exec() 함수를 통해 생성되고, PCB가 이 시점에 생성된다.

fork()

부모 프로세스의 주소 공간을 그대로 복사하고, 새로운 자식 프로세스를 생성하는 함수이다. 주소 공간만 복사할 뿐 부모 프로세스의 비동기 작업 등을 상속하지 않는다.

exec()

새롭게 프로세스를 생성하는 함수이다.

대기 상태

대기 상태는 메모리 공간이 충분하면 메모리를 할당받고 아니면 아닌 상태로 대기하고 있다. CPU 스케줄러로부터 CPU 소유권이 넘어오기를 기다리는 상태이다.

대기 중단 상태

메모리 부족으로 일시 중단된 상태이다.

실행 상태

CPU 소유권과 메모리를 할당받고 인스트럭션을 수행 중인 상태를 의미한다. CPU burst가 일어났다고 표현한다.

중단 상태

어떤 이벤트가 발생한 이후 기다리며 프로세스가 차단된 상태이다. I/O 디바이스에 의한 인터럽트로 이런 현상이 많이 발생한다.

일시 중단 상태

중단 상태의 프로세스가 다시 실행되려고 했지만 메모리 부족으로 일시 중단된 상태이다.

종료 상태

메모리와 CPU 소유권을 모두 놓고 가는 상태이다.

프로세스의 메모리 구조

stack

지역변수, 매개변수, 함수가 저장되고 컴파일 시에 크기가 결정되며 동적이다. 함수가 함수를 재귀적으로 호출하며 동적으로 크기가 늘어날 수 있다. heap 영역과 메모리 영역이 겹치면 안 되기 때문에 힙과 스택 사이의 공간을 비워놓는다.
잠시 사용되었다가 사라지는 데이터를 저장하는 영역

heap

동적 할당 시 사용되며 런타임에 크기가 결정된다. 벡터와 같은 배열은 힙에 동적 할당된다. 프로그래머가 필요할 때 마다 사용하는 메모리 영역이다.

data

전역변수, 정적변수가 저장된다.

  • BSS 영역: 초기화가 되지 않은 변수가 0으로 초기화되어 저장된다.
  • Data 영역 : 0이 아닌 다른 값으로 할당된 변수들이 저장된다.

code

사용자가 작성한 코드가 기계어로 변환되어 저장되는 영역이다. 수정 불가능한 기계어로 저장되어 있으며 정적인 특징을 가진다. 컴파일 타임에 결정된다.

PCB(Process Control Block)

운영체제에서 프로세스에 대한 메타데이터를 저장한 데이터.

  • 프로그램이 실행되면 프로세스가 생성되고 PCB가 생성된다.
  • 프로세스 주소 값들에 스택, 힙, 등의 구조를 기반으로 메모리가 할당된다.
  • 일반 사용자가 접근할 수 없도록 커널 스택의 가장 앞 부분에서 관리된다.

PCB의 구조

  • 프로세스 스케줄링 상태 : '준비', '일시중단' 프로세스가 CPU에 대한 소유권을 얻은 이후 또는 이후 경과된 시간과 같은 기타 스케줄링 정보
  • 프로세스 ID : 프로세스, 자식 프로세스의 ID
  • 프로세스 권한 : 컴퓨터 자원 혹은 I/O 디바이스에 대한 권한 정보
  • 프로그램 카운터 : 프로세스에서 실행해야 할 다음 명령어의 주소에 대한 포인터
  • CPU 레지스터 : 프로세스를 실행하기 위해 저장해야 할 레지스터에 대한 정보
  • CPU 스케줄링 정보 : CPU 스케줄러에 의해 중단된 시간 등에 대한 정보
  • 계정 정보 : 프로세스 실행에 사용된 CPU 사용량, 실행 사용자의 정보
  • I/O 상태 정보 : 프로세스에 할당된 I/O 디바이스 목록

컨텍스트 스위칭

PCB를 교환하는 과정, 프로세스에 할당된 시간이 끝나거나 인터럽트에 의해 발생한다.

싱글코어를 기준으로 어느 한 시점에 실행되는 프로세스는 단 하나이다.

  • 프로세스 P0를 실행하다가 멈추고, PCB에 저장한다.
  • 프로세스 P1을 로드하여 실행한다.

컨텍스트 스위칭이 일어날 때 발생하는 비용

  • 유휴시간(idle time) : PCB를 저장하거나 로드할 때 CPU를 사용할 수 없는 시간
  • 캐시 미스 : 캐시에는 현재 실행 중인 프로세스의 데이터가 들어간다. 컨텍스트 스위칭이 발생하면 캐시에 있는 데이터는 필요가 없어져 캐시를 클리어 한다. 캐시 미스가 발생하므로 메모리를 참조하는 오버헤드가 발생한다.
    • 스레드는 스택 영역을 제외한 모든 메모리를 공유하기 때문에, 스레드 간 컨텍스트 스위칭이 발생할 때는 캐시를 비우지 않아도 되고 비용, 시간이 더 적다.

멀티 프로세싱

웹 브라우저

웹 브라우저는 멀티프로세스 구조를 가진다.

  • 브라우저 프로세스
  • 렌더러 프로세스
  • 플러그인 프로세스
  • GPU 프로세스

IPC(Inter Process Communication)

프로세스끼리 데이터를 주고받고 공유 데이터를 관리하는 메커니즘

프로세스는 새로 생성되면 PCB를 생성하고, 메모리 공간을 할당받는다. 따라서 프로세스 간에는 메모리를 공유하지 않으므로 IPC는 메모리가 완전히 공유되는 스레드보다는 속도가 떨어진다.

공유 메모리

여러 프로세스에 동일한 메모리 블록에 대한 접근 권한이 부여된다. 따라서 프로세스가 서로 통신할 수 있도록 공유 버퍼를 생성한다.

  • 메모리 자체를 공유하기 때문에 불필요한 데이터 복사의 오버헤드가 발생하지 않아 가장 빠르다.
  • 메모리 영역을 여러 프로세스가 공유하므로 동기화가 필요하다.

파일

디스크에 저장된 데이터 혹은 파일 서버에서 제공한 데이터를 말한다. 이를 기반으로 프로세스 간 통신이 이루어진다.

소켓

동일 컴퓨터의 다른 프로세스나 네트워크의 다른 컴퓨터로 네트워크 인터페이스를 통해 데이터를 전송함. 네트워크를 경유하는 프로세스 간 통신의 종착점.

  • TCP
  • UDP

익명 파이프

프로세스 간 통신을 위해 FIFO 구조의 임시 공간인 파이프를 이용한다. 단방향 읽기 전용, 쓰기 전용 파이프를 만들어 동작한다. 부모, 자식 프로세스 사이에서만 이용이 가능하며, 다른 네트워크 상에서는 사용할 수 없다.

네임드 파이프

파이프 서버와 하나 이상의 파이프 클라이언트 간의 통신을 위한 명명된 단방향 파이프 혹은 양방향 파이프를 지칭한다. 여러 파이프를 동시에 사용할 수 있고, 다른 네트워크 상의 컴퓨터와도 통신할 수 있다.

  • 외부 프로세스와 통신을 하기 위해 파이프의 이름을 붙이자는 취지에서 등장.
  • 읽기, 쓰기를 모두 지원하지만 한 번에 한 방향으로만 통신이 가능한 반이중통신. 따라서 전이중통신을 지원하기 위해서는 두 개의 파이프가 필요하다.

파이프는 프로세스 간 양방향 통신을 하기 위해서 두 개의 파이프를 생성해야 하므로 메모리의 낭비가 심하다.

메시지 큐

  • 커널의 전역변수 형태 등 커널에서 전역적으로 관리된다.
  • 다른 IPC 방식에 비해 직관적이고 간단하게 사용할 수 있다.
  • 공유 메모리를 통해 IPC를 구현하면 쓰기 및 읽기 빈도가 증가함에 따라 동기화 때문에 코드 구현이 복잡해지는데, 이때의 대안으로 메세지 큐가 있다.

스레드와 멀티스레딩

스레드

프로세스의 실행 가능한 가장 작은 단위. 프로세스는 여러 스레드를 가질 수 있다.

프로세스는 코드, 데이터, 스택, 힙을 각각 생성하지만, 스레드는 코드, 데이터, 힙은 스레드끼리 서로 공유하고 그 외의 영역은 각각 생성된다.

멀티스레딩

  • 멀티스레딩은 여러 스레드로 프로세스 내 작업을 처리하는 기법으로 서로 자원을 공유하기 때문에 효율적이다.
  • 한 스레드가 중단되어도 다른 스레드는 실행 상태일 수 있기 때문에 중단되지 않은 빠른 처리가 가능하다.
  • 한 스레드가 문제가 생기면 다른 스레드에 영향을 끼칠 수 있다.

공유 자원과 임계 영역

공유 자원

시스템 안에서 프로세스나 스레드가 동시에 접근하여 경쟁 상태(race condition)를 일으킬 수 있는 모니터, 프린터, 메모리, 파일, 데이터 등의 자원이나 변수를 의미.

임계 영역

공유자원에 접근할 때 순서와 같은 이유로 결과가 달라지는 영역을 임계 영역(critical section)이라고 한다.

이를 해결하기 위한 방법은 뮤텍스, 세마포어, 모니터가 있다.

  • 상호 배제(mutual exclusion)
    한 프로세스가 임계 영역에 들어갔을 때 다른 프로세스는 들어갈 수 없음.
  • 한정 대기(bounded waiting)
    특정 프로세스가 영원히 임계 영역에 들어가지 못하면 안됨. 상호 배제 때문에 기다리는 프로세스가 끝없이 대기하지 않아야 한다.
  • 진행의 융통성(progress, progress flexibility)
    한 프로세스가 다른 프로세스의 일을 방해해서는 안된다. 임계구역에 프로세스가 없다면 어떤 프로세스든 임계구역에 들어갈 수 있다.

위 세 조건을 만족한다.

뮤텍스

공유 자원을 사용하기 전에 잠금을 설정하고 사용한 후에는 잠금을 해제한다. 잠금이 설정되면 다른 프로세스는 공유 자원에 접근할 수 없다. 하나의 잠금 상태만을 가진다.

세마포어

일반화된 뮤텍스. 정수값과 wait, signal함수를 통해 공유 자원에 대한 접근을 처리한다.

  • wait는 임계 구역에 들어가기 전에 수행되고, signal은 임계 구역에서 나올 때 수행된다. 이 함수들은 정수값을 바꾸는 연산으로 원자성이 보장되어야 한다.

    • busy waiting을 통한 구현 방법(Spin lock)
      임계 구역에 들어갈 수 있을 때 까지 빈 반복문을 수행한다.
      - 스핀락은 운영체제의 스케줄링 지원을 받지 않아 컨텍스트 스위칭이 발생하지 않는다. 따라서 짧은 시간 안에 임계 영역에 진입할 수 있는 경우 컨텍스트 스위칭 비용이 발생하지 않아 효율적이다(멀티 프로세서 시스템에서만 사용할 수 있음.).
      - 하지만 임계 영역이 오랫동안 unlock 되지 않으면 CPU를 계속 선점하고 있기 때문에 효율이 떨어진다.
      - 단일 프로세서 시스템에서 효율이 떨어지고, 대기 중인 프로세스 중 어떤 것을 먼저 진입시킬지 결정할 수 없다.
      출처 : https://ko.wikipedia.org/wiki/%EC%84%B8%EB%A7%88%ED%8F%AC%EC%96%B4

    • 재움 큐를 통한 구현 방법

바이너리 세마포어 vs 카운팅 세마포어

  • 바이너리 세마포어는 0, 1 두 가지 값만 가질 수 있다. 뮤텍스와 비슷하지만 뮤텍스는 리소스에 대한 접근을 동기화할 때 사용되는 잠금 메커니즘이고, 세마포어는 신호를 기반으로 상호 배제가 일어나는 메커니즘이다.
  • 카운팅 세마포어는 위에 설명했던 것들과 같다. 여러 자원에 대한 접근을 제어하는 데 사용된다.

모니터

공유 자원에 여러 스레드나 프로세스가 안전하게 접근할 수 있도록 공유 자원을 숨기고 접근할 수 있는 인터페이스만 제공한다.
ex) 모니터큐를 통해 공유 자원에 대한 작업을 순차적으로 처리한다.

교착 상태(Dead Lock)

두 개 이상의 프로세스가 서로 가진 자원을 하염없이 기다리기 때문에 아무것도 완료하지 못하는 상태

교착 상태의 원인

상호 배제(Mutual Exclusive)

한 프로세스가 자원을 독점하고 있고, 다른 프로세스들은 자원에 접근할 수 없다.

점유 대기(Hold and wait)

프로세스가 할당된 자원을 가진 상태에서 다른 자원을 기다린다.

비선점(No preemption)

다른 프로세스의 자원을 강제적으로 뺐을 수 없다.

환형 대기(Circular wait)

프로세스 A가 프로세스 B의 자원을 요구하고, 프로세스 B가 프로세스 A의 자원을 요구한다. 즉, 프로세스가 다음 프로세스의 자원을 순환적으로 요구한다.

교착 상태의 해결 방법

교착 상태의 예방

상호 배제 제거
점유 대기 제거
한 프로세스에 수행되기 전에 모든 자원을 할당시키고 점유하지 않을 때 다른 프로세스가 자원을 요구하도록 한다.

  • 문제점
    • 자원 과다 사용으로 인한 효율성
    • 프로세스가 요구하는 자원을 파악할 때 비용
    • 자원에 대한 내용을 저장, 복원하기 위한 비용
    • 기아 상태
    • 무한대기

비선점 제거
비선점 프로세스에 대해 선점 가능 프로토콜을 만들어준다.
순환 대기 예방
자원 유형에 따라 순서를 매긴다.

교착 상태의 회피

시스템에서 환형 대기가 생기지 않도록 자원이 어떻게 요청될지에 대한 추가정보를 요구한다.
교착 상태 회피 알고리즘

  • 자원 할당 그래프 알고리즘

    자원할당 그래프를 통해 프로세스가 자원을 요청했을 때 사이클이 생기는 지 알아본다. 사이클이 생기고 자원이 할당될 수 있는 프로세스가 하나이면 데드락이 발생한다.

  • 은행원 알고리즘
    교착상태에 빠질 가능성이 있는지 판단하기 위해 safe state와 unsafe state로 나눈다.

    • safe state : 시스템이 교착상태를 일으키지 않으면서 각 프로세스가 요구한 최대 요구량만큼 필요한 자원을 할당해 줄 수 있는 안전순서열이 있는 상태

    • unsafe state : 안전순서열이 존재하지 않는 상태. 교착상태를 일으킬 가능성이 있다.

    • 은행원 알고리즘에서 운영체제는 안전상태를 유지할 수 있는 요구만을 수락한다. '최소한 고객 한명에게 대출해줄 금액은 항상 은행이 가지고 있어야 한다.' 라는 개념에서 나온다.

      위는 교착 상태의 조건인 unsafe state이다. 은행에 남은 돈을 누구에게 빌려줘도 돌려받을 수 없다(고객이 필요한 돈을 다 빌리면 다시 반환할 수 있다는 가정).

    • Max : 프로세스가 자원을 얼마나 요청할 수 있는지

    • Allocated : 프로세스가 보유하고 있는 자원은 얼마인지

    • Available : 시스템(은행)이 얼마나 자원을 보유하고 있는지

    • 단점

      • 불안전 상태를 방지해야 하므로 자원이용도가 떨어진다.
      • 할당할 수 있는 자원의 수, 사용자 수가 일정해야 한다.
      • 최대 자원 요구량을 미리 알아야 한다.
        위 단점 때문에 오버헤드가 너무 크다.

교착 상태의 무시

예방, 회피 기법은 성능에 큰 영향을 미칠 수 있고, 교착 상태는 드물게 일어나므로 발생하면 사용자가 직접 작업을 종료한다. 현재 운영체제에서 채택한 방법이다.

profile
아직 반지하

0개의 댓글