[운영체제] 총 정리

알감자·2022년 5월 24일
2

게임공부

목록 보기
15/22

프로그램과 프로세스

  • 프로그램
    : 어떤 작업을 위해 실행할 수 있는 파일
  • 프로세스
    : 컴퓨터에서 연속적으로 실행되고 있는 프로그램

    • 동적인 개념으로는 실행된 프로그램을 의미

    • 디스크로부터 메모리에 적재되어 CPU의 할당을 받을 수 있는 것

    • 메모리에 올라와 실행되고 있는 프로그램의 인스턴스 (독립적인 개체)

    • 운영체제로부터 시스템 자원(주소공간, 파일, 메모리 등)을 할당받는 작업의 단위



프로그램과 프로세스는 다르다.

  • 프로그램은 명령어를 내용으로 가진 디스크에 저장된 파일. 즉 수동적인 존재(Passive entity)

  • 프로세스는 다음에 실행할 명령어를 지정하는 프로그램 카운터 및 관련된 자원의 집합을 가진 능동적 존재(active entity)

  • 특징
    : 프로세스는 각각의 독립적인 메모리 영역(Code, Data, Stack, Heap의 구조)를 할당

    • Code: 프로그램을 실행시키는 실행 파일 내의 명령어(소스코드)

    • Data: 전역변수, Static변수의 할당

    • Heap: 동적 할당을 위한 메모리 영역

    • Stack: 지역변수, 함수 호출 시 전달되는 파라미터를 위한 메모리 영역

  1. Stack
    : 지역변수, 매개변수, 복귀 번지 등이 저장되어 있는 프로그램이 자동으로 사용하는 임시 메모리 함수 호출 시 생성되고, 함수 종료시 반환됨 (LIFO)

  2. Heap
    : 프로그래머가 동적으로 사용하는 영역
    malloc, free 또는 new, delete에 의하여 할당 또는 반환되는 영역.
    garbage collector가 활동하는 경우 자동으로 반환되는 경우도 있음

  3. Data
    : 전역변수(global), 정적변수(Static), 배열(Array), 구조체(Structure)등이 저장됨

1) 초기화 된 데이터: data에 저장
2) 초기화 되지 않은 데이터 : bss(Block Stated Symbol)에 저장
=> data 영역이 런타임 이전에 초기화 하는 것이라면 bss는 런타임 이후 초기화 하는 것
 
  1. Code(text)
    : 작성한 코드가 들어가는 부분
    read-only 영역. 프로세스가 종료될 때 까지 계속 유지되는 영역

  • 각 프로세스는 별도의 주소 공간에서 실행, 한 프로세스는 다른 프로세스의 변수나 자료구조에 접근X

  • 한 프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간의 통신(IPC, Inter-Process Communication)을 사용

    • 파이프, 파일, 소켓등을 사용

스레드(Thread)

  • 스레드(thread)
    : 한 프로세스 내에서 실행되는 여러 흐름의 단위

    • 프로세스의 특정한 수행경로

    • 프로세스가 할당받은 자원을 이용하는 실행의 단위, CPU 이용의 기본 단위

    • 프로세스 내의 주소 공간이나 자원을 공유

    • 스레드 ID, 프로그램 카운터(PC), 레지스터 집합, 스택으로 구성

    • 같은 프로세스에 속한 다른 스레드와 코드, 데이터 섹션, 열린 파일이나 신호와 같은 운영체제 자원을 공유

    • 하나의 프로세스를 다수의 실행 단위로 구분하여 자원을 공유하고 자원의 생성과 관리의 중복성을 최소화하여 수행 능력을 향상하는 것
      => 멀티스레딩

    • 각각의 스레드는 독립적인 작업을 수행해야 하기 때문에 각각의 스택과 PC 레지스터를 가짐


  • 특징

    • 스레드는 프로세스 내에서 각각 Stack과 레지스터를 따로 할당받고 Code, Data, Heap 영역은 공유

    • 한 스레드가 프로세스 자원을 변경하면, 다른 이웃 스레드(Sibling Thread)도 그 변경 결과를 즉시 확인 가능

  • 분류
    : 권한이 없는 스레드가 시스템 호출을 이용할 수 없도록 막기 위해 종류를 나눔

    • 사용자 수준의 스레드 (User Threads)
      - 사용자가 만든 라이브러리를 사용하여 스레드를 운용
      - 속도는 빠르지만 구현이 어려움
      - 시스템 호출 권한이 없는 스레드

    • 커널 수준의 스레드 (Kernel Threads)
      - 운영체제 커널에 의해 스레드를 운용
      - 구현은 쉽지만 유저 모드에서 커널 모드로 계속 바꿔줘야 하기 때문에 속도가 느림
      - 시스템 호출 권한이 있는 스레드


스택을 스레드마다 독립적으로 할당하는 이유?

: 스택은 함수 호출 시 전달되는 인자, 되돌아갈 주소 값 및 함수 내에서 선언하는 변수등을 저장하기 위해 사용되는 메모리 공간.
스택 메모리 공간이 독립적이라는 것은 독립적인 함수 호출이 가능하다는 것
=> 독립적인 실행 흐름의 추가


PC 레지스터를 스레드마다 독립적으로 할당하는 이유?

: PC 값은 스레드가 명령어의 어디까지 수행했는지를 나타낸다.
스레드는 CPU를 할당 받았다가 스케줄러에 의해 다시 선점 당하는데, 이 때문에 명령어가 연속적으로 수행되지 못하고 어느 부분까지 수행됐는지 기록을 해야한다.


  • 스레드 풀(Thread Pools)
    : 웹 서버는 요청을 받을 때마다 요청을 위해 새로운 스레드를 생성

    • 프로세스를 시작할 때, 일정한 수의 스레드를 미리 풀로 만들어 두는 것

    • 평소에는 기다리다가 요청이 들어오면 풀의 한 스레드에게 서비스 요청을 할당

    • 요청이 끝나면 스레드는 다시 풀로 돌아가 다음 작업을 대기


  • 다중 스레드 서버의 문제점

    1) 서비스 할 때마다 스레드를 생성하는데 시간이 소요

    • 스레드는 주어진 일만 끝나게 되면 곧장 폐기되기 때문에 더더욱 낭비

    2) 모든 요청마다 새로운 스레드를 만들어 서비스를 한다면 동시에 실행할 수 있는 최대 스레드의 한계를 정해야함

    • 무한정 생성 시 CPU 시간, 메모리 공간 등 시스템 자원이 고갈
  • 장점

    • 새 스레드를 만들어 주는 것 보다 기존 스레드로 서비스 하는 것이 더 빠름

    • 스레드 풀은 임의 시각에 존재할 수 있는 스레드 개수에 제한. 많은 수의 스레드를 병렬 처리 할 수 없는 시스템에 도움


왜 멀티 프로세스 대신 멀티 스레드를 사용할까?

: 프로그램을 여러 개 켜는 것보다 하나의 프로그램에서 여러 작업을 하는 것


1. 응답성(Responsiveness) 증가

  • 프로그램 일부분이 봉쇄되거나, 긴 작업을 실행하더라도 프로그램의 실행이 계속되는 것을 허용함으로써 사용자에 대한 응답성을 증가.

  • ex) 웹 브라우저는 한 스레드가 이미지 파일을 로드하고 있는 동안 다른 스레드에서 사용자와의 상호작용


2. 자원 공유(Resource Sharing) : 자원의 효율성 증가

  • 프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리 가능

    • 프로세스 간의 Context Switching시 단순히 CPU 레지스터만 교체하는 것이 아니라 RAM과 CPU 사이의 캐시 메모리에 대한 데이터까지 초기화 하기 때문에 오버헤드가 큼
  • 스레드는 프로세스 내의 메모리를 공유하기 때문에 독립적인 프로세스와 달리 스레드 간의 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 감소

  • 코드와 데이터를 공유하면 한 응용 프로그램이 같은 주소 공간 내에 여러 개의 다른 작업을 하는 스레드 보유 가능


3. 경제성(Economy) : 처리 비용 감소

  • 프로세스 간의 통신(IPC)보다 스레드 간의 통신 비용이 적어 작업들 간의 통신 부담이 감소

    • 스레드는 Stack영역을 제외한 모든 메모리 공유
  • 프로세스 생성을 위해 메모리와 자원을 할당하는 것보다 스레드를 생성하고 문맥 교환을 하는 것이 더 경제적

  • 프로세스 간의 전환 속도보다 스레드 간의 전환 속도가 더 빠름

    • Context Switching 시 스레드는 Stack 영역만 처리해주면 됨. 캐시 메모리를 비우지 않아도 됨.
  • 스레드가 프로세스보다 경량이기 때문에 생성과 제거가 쉽다.


4. 규모 가변성(Scalability)

  • 다중 처리기 구조에서는 각각의 스레드가 다른 처리기에서 병렬로 실행 가능


멀티 스레드에서 주의할 점

  1. 동기화 문제

    • 스레드 간의 자원 공유는 전역 변수(데이터 세그먼트)를 이용하므로 함께 사용시 충돌 발생 가능

    • 사용중인 변수나 자료구조에 접근하여 잘못된 값을 읽어오거나 수정할 수 있다.

    • 동기화를 통해 작업 처리 순서를 컨트롤하고 공유 자원에 대한 접근을 컨트롤 해야함

      • 그러나 병목 현상이 발생해 성능 저하 가능성
  2. 멀티 스레드는 적은 공간을 차지하고 Context Switching이 빠르다는 장점을 가지고 있지만 오류로 인해 하나의 스레드가 종료될 때 전체 스레드가 종료될 수 있다.


Context Switching

  • Context
    : CPU가 해당 프로세스를 실행하기 위한 해당 프로세스들의 정보

    • 프로세스의 PCB에 저장한다


  • Context Switching
    : 현재 진행하고 있는 Task(Process, Thread)의 상태를 저장하고 다음 진행할 상태의 Task의 저장된 상태 값을 읽어 복구하는 작업

    • Context Switching이 진행되는 동안 시스템은 아무런 유용한 일도 하지 못하기 때문에 순수한 오버헤드


Context Switching을 하는 이유

  • 하나의 Task만 처리할 수 있다면?

    • 해당 Task가 끝날 때 까지 기다려야 함
    • 반응 속도가 느리고 사용하기 불편함
  • 동시에 사용하는 것 처럼 하기 위해

    • Computer Multitasking
    • 빠른 속도로 Task를 바꿔가며 실행하기 때문에 사람의 눈으로는 실시간처럼 보임
    • CPU가 Task를 바꿔가며 실행하기 위해 Context Switching이 필요

  • Context Switching 과정
  1. Task의 대부분 정보는 Register에 저장되고 PCB(Process Control Block)로 관리

  2. 현재 실행되고 있는 Task의 PCB 정보를 저장(Process Stack, Ready Queue)

  3. 다음 실행할 Task의 PCB 정보를 읽어 Register에 적재하고 CPU가 이전에 진행했던 과정을 연속적으로 수행


  • Context Switching Cost

    • 많은 cost가 필요

      • Cache 초기화
      • Memory Mapping 초기화
      • Kernel은 항상 실행되어야 함 (메모리의 접근을 막기 위해)

    • Process VS Thread

      • Process Context Switching Cost > Thread Context Switching Cost

      • Thread는 Stack 영역을 제외한 모든 메모리를 공유하기 때문에 Context Switching 수행 시 Stack 영역만 변경하면 되기 때문에 비용이 적다.


  • Thread-Safe
    : 멀티스레드 환경에서 여러 스레드가 동시에 하나의 객체 및 변수(공유 자원)에 접근할 때, 의도한 대로 동작하는 것

  • 구현하기

    • 공유 자원에 접근하는 임계 영역(Critical Section)을 동기화 기법으로 제어해야 한다.

      • 상호 배제(Mutual Exclusion)
    • 동기화 기법으로는 Mutex나 Semaphore가 존재

  • ReEntrant
    : 재진입성, 여러 스레드가 동시에 접근해도 언제나 같은 실행 결과를 보장하는 것
    이를 만족하기 위해 해당 서브루틴에서 공유 자원을 사용하지 않으면 된다.
    • 예를 들어 정적(전역)변수를 사용하거나 반환하면 안되고 호출 시 제공된 매개 변수만으로 동작해야함.

      => 따라서 ReEntrant하면 Thread-Safe하지만 역은 성립되지 않는다.


  • 동기화 기법의 종류
  1. 유저 모드 동기화

    • 커널의 힘을 빌리지 않는 (커널 모드가 실행되지 않는) 동기화 기법

    • 성능상 이점, 기능상의 제한

    • ex) 크리티컬 섹션 기반의 동기화, 인터락 함수 기반의 동기화


  2. 커널 모드 동기화

    • 커널에서 제공하는 동기화 기능을 활용하는 방법

    • 커널 모드로의 변경이 필요 -> 성능 저하

    • 다양한 기능 활용 가능

    • ex) 뮤텍스 기반의 동기화, 세마포어 기반의 동기화, 이벤트 기반의 동기화


프로세스 동기화

  • 경쟁상황(Race Condition)
    : 동시에 여러 개의 프로세스가 동일한 자료를 접근하여 조작하고, 그 실행 결과가 접근이 발생한 특정 순서에 의존하는 상황

  • 임계 영역(Critical Section)
    : 동일한 자원을 동시에 접근하는 작업을 실행하는 코드 영역

  • 임계 영역 문제(Critical Section Problem)
    : 프로세스들이 Critical Section을 함께 사용할 수 있는 프로토콜을 설계하는 것

  • 해결을 위한 기본 조건

    • Mutual Exclusion(상호배제)
      : 프로세스 1이 임계 영역에서 실행중이라면 다른 프로세스들은 그들이 가진 임계 영역에서 실행될 수 X

    • Progress(진행)
      : 임계 영역에서 실행 중인 프로세스가 없고 별도의 동작이 없는 프로세스들만 임계 영역 후보로서 참여 가능

    • Bounded Waiting(한정된 대기)
      : 프로세스 1이 임계 영역 진입 신청 후 받아들여질 때까지 다른 프로세스들이 임계 영역에 진입하는 횟수는 제한이 있어야함


  • 해결책

    • 뮤텍스(Mutex)

      • 공유된 자원의 데이터를 여러 프로세스나 스레드가 접근하는 것을 막는 것

      • 상호 배제(Mutual Exclusion)라고도 함

      • Critical Section을 가진 스레드의 Running Time이 겹치지 않도록 각각 단독으로 실행하게 하는 기술

      • 다중 프로세스들이 공유 리소스에 대한 접근을 조율하기 위해 Syncronized 또는 lock을 사용

        • 즉, 뮤텍스 객체를 두 스레드가 동시에 사용 불가
    • 세마포어(Semaphore)

      • 공유된 자원의 데이터를 여러 프로세스나 스레드가 접근하는 것을 막는 것

      • 리소스 상태를 나타내는 간단한 카운터로 생각

        • 운영체제 또는 커널의 한 지정된 저장장치 내의 값

        • 일반적으로 비교적 긴 시간을 확보하려는 리소스에 사용

        • 유닉스 시스템 프로그래밍에서 세마포어는 운영체제의 리소스를 경쟁적으로 사용하는 다중 프로세스에 행동을 조정하거나 동기화 시키는 기술

      • 공유 리소스에 접근할 수 있는 프로세스의 최대 허용치만큼 동시에 사용자가 접근하여 사용 가능

      • 각 프로세스는 세마포어 값을 확인하고 변경 가능

        • 사용중이지 않은 자원의 경우 그 프로세스가 즉시 자원을 사용

        • 이미 다른 프로세스에 의해 사용중이라는 사실을 알게 되면 재시도하기 전에 일정 시간을 대기

        • 세마포어를 사용하는 프로세스는 그 값을 확인하고, 자원을 사용하는 동안에는 그 값을 변경함으로써 다른 세마포어 사용자들이 기다리도록 함.

      • 세마포어는 2진수를 사용하거나 추가적인 값을 가질 수 있음

        • 카운팅 세마포어
          : 가용한 개수를 가진 자원에 대한 접근 제어용으로 사용, 세마포어는 가용한 자원의 개수로 초기화.
          자원을 사용하면 감소, 방출하면 증가

        • 이진 세마포어
          : Mutex 라고도 부르며 상호 배제의 머리 글자를 따서 만들어짐. 이름 그대로 0과 1 사이의 값만 가능하며 다중 프로세스들 사이의 임계 영역 문제를 해결하기 위해 사용


  • 세마포어와 뮤텍스의 차이

    • 가장 큰 차이는 관리하는 동기화 대상의 개수

      • Mutex는 동기화 대상이 오직 하나일 때, Semaphore는 동기화 대상이 하나 이상일 때 사용
    • Semaphore는 Mutex가 될 수 있지만 Mutex는 Semaphore가 될 수 없음

      • Mutex는 상태가 0, 1 두 개 뿐인 Binary semaphore
    • Semaphore는 소유할 수 없는 반면, Mutex는 소유 가능. 소유주가 이에 대한 책임을 가짐

      • Mutex의 경우 상태가 두 개 뿐인 lock 이므로 lock을 가질 수 있음
    • Mutex의 경우 Mutex를 소유하고 있는 thread가 Mutex를 해제 할 수 있지만 Semaphore는 Semaphore를 소유하지 않는 스레드가 해제 가능

    • Semaphore는 시스템 범위에 걸쳐 있고 파일 시스템 상의 형태로 존재하지만 Mutex는 프로세스 범위를 가지며 프로세스가 종료될 때 자동으로 Clean up


교착상태의 개념과 조건

  • 교착상태 (Deadlock)
    : 첫 번째 스레드는 두 번째 스레드가 들고 있는 객체의 락이 풀리기를 기다리고 있고, 두 번째 스레드 역시 첫 번째 스레드가 들고 있는 객체의 락이 풀리기를 기다리는 상황
    모든 스레드가 락이 풀리기를 기다리고 있기 때문에 무한 대기 상태 => 교착상태

  • 교착상태의 4가지 조건

    1. 상호 배제 (Mutual Exclusion)

    • 한 번에 한 프로세스만 공유 자원을 사용

    • 좀 더 정확하게는 공유 자원에 대한 접근이 제한

    • 자원의 양이 제한되어 있더라도 교착상태는 발생 가능

    2. 점유대기 (Hold and Wait)

    • 공유 자원에 대한 접근 권한을 갖고 있는 프로세스가 그 접근 권한을 양보하지 않은 상태에서 다른 자원에 대한 접근 권한을 요구 가능

    3. 비선점 (Preemtive)

    • 한 프로세스가 다른 프로세스의 자원 접근 권한을 강제로 취소 불가능

    4. 순환대기(Circular wait)

    • 두 개 이상의 프로세스가 자원 접근을 기다리는데, 그 관계에 사이클이 존재

    => 4가지 조건을 다 만족해야 교착상태

0개의 댓글