본 글은 기술 면접 대비 CS 전공 핵심요약집 (길벗) 을 기반으로 정리한 내용입니다.

1. 프로세스

프로세스

프로세스란?

  • 컴퓨터에서 실행 중인 하나의 프로그램
    • 프로그램은 특정 작업을 수행하기 위한 명령어의 집합
  • 프로그램이 프로세스가 되는 과정
    1) OS는 프로그램을 실행하면서 디스크에 저장된 데이터를 메모리로 로드한다.
    2) 프로세스는 OS로부터 독립된 메모리 영역(스택, 힙, 데이터, 코드) 을 할당받는다.
    3) 프로세스는 다른 프로세스의 메모리 영역에 접근할 수 없다.

PCB

  • OS는 프로세스를 제어하기 위해 프로세스 정보를 저장하는 데 이를 PCB (Process Control Block, 프로세스 제어 블록)이라고 한다.
  • PCB는 프로세스의 현재 상태, 프로세스를 나타내는 고유의 PID, 부모/자식 프로세스의 PID, 다음 실행할 명령어의 주소인 PC(Program Counter), 프로세스의 우선순위, 메모리 제한 등을 저장한다.

프로세스의 메모리 영역 구조

프로세스는 OS로부터 독립된 메모리 영역 (스택, 힙, 데이터, 코드)을 할당받는다.

  • 스택(stack)
    • 지역 변수, 함수의 매개변수(파라미터), 반환되는 주소 값 등이 저장되는 영역
    • LIFO(last in first out) 방식으로 높은 주소 값에서 낮은 주소 값으로 메모리가 할당된다.
    • 영역의 크기는 컴파일 때 결정된다.
  • 힙(heap)
    • 사용자에 의해 동적 메모리 할당이 일어나는 영역
    • FIFO(first in first out) 방식으로 낮은 주소 값에서 높은 주소 값으로 메모리가 할당된다.
    • 영역의 크기는 런타임 때 결정된다.
  • 데이터(data)
    • 전역 변수, 정적 변수, 배열, 구조체 등이 저장되는 영역
    • 데이터 영역은 BSS 영역과 데이터 영역으로 다시 나눌 수 있다.
      • BSS 영역은 초기화 하지 않은 변수를, 데이터 영역은 초기화 한 변수를 저장한다.
  • 코드(code)
    • 실행할 코드가 기계어로 컴파일되어 저장되는 영역

스택 오버플로와 힙 오버플로

스택 영역과 힙 영역은 동적으로 메모리 할당이 가능해 두 영역 사이에 빈 메모리 공간이 존재한다. 하지만 메모리 영역을 공유하기 때문에 서로의 영역을 침범하는 문제가 생길 수 있다.

스택 영역이 힙 영역을 침범하는 경우를 스택 오버플로 라고 한다.
스택 영역은 지역 변수와 함수의 매개변수가 저장되는 영역으로, 과도한 재귀호출이 발생하면 힙 영역을 침범하게 되어 스택 오버플로가 발생한다.

힙 영역이 스택 영역을 침범하는 경우를 힙 오버플로 라고 한다.
힙은 동적 메모리 영역이므로 과도하게 동적 할당을 하면 힙 오버플로가 발생한다.

오버플로 : 메모리 공간에서 할당할 수 있는 최대 범위를 넘어가는 것을 의미한다.

프로세스의 생성

  • 새로운 프로세스는 기존 프로세스에서 fork() 함수를 호출해 생성한다.
    • fork() 함수는 함수를 호출한 프로세스를 복사하는 기능이 있다.
  • 부모 프로세스에서 fork() 함수를 호출하면 자식 프로세스의 PID 값을 반환한다.
  • 자식 프로세스는 부모 프로세스가 fork() 함수를 호출한 시점에 생성되고 0을 반환한다.

좀비 프로세스와 고아 프로세스

  • 좀비 프로세스
    자식 프로세스가 종료되었지만 부모 프로세스가 자식 프로세스의 종료 상태를 회수하지 않았을 경우에 남겨진 자식 프로세스를 의미한다.

자식 프로세스가 종료될 때 부모 프로세스에 SIGCHILD 라는 시그널을 보내면 부모 프로세스에서 wait() (시스템 콜)를 호출해 자식 프로세스의 상태 정보를 받고 자원을 회수한다. 이때 자원 회수에 실패하면 좀비 프로세스가 생기게 된다.

  • 고아 프로세스
    부모 프로세스가 자식 프로세스보다 먼저 종료되는 경우에 자식 프로세스를 의미한다.

이럴 때는 자식 프로세스의 부모 PID를 init 프로세스의 PID인 1로 바꿔준다. 이렇게 하면 고아 프로세스의 부모 프로세스는 부팅 시 가장 먼저 실행되는 init 프로세스가 된다.

이후 고아 프로세스가 작업을 종료하면 init 프로세스가 고아 프로세스의 자원을 회수해 좀비 프로세스가 되는 것을 방지할 수 있다.

프로세스 상태도

모든 프로세스는 CPU에 의해 생성되고 소멸하는 과정을 거친다.
이 과정에서 프로세스는 생성, 준비, 실행, 대기, 종료라는 5가지 상태로 존재한다.

프로세스 상태도

  • 생성 : 프로세스가 PCB를 가지고 있지만, OS로부터 승인받기 전
  • 준비 : OS로부터 승인받은 후, 준비 큐에서 CPU 할당 대기
  • 실행 : 프로세스가 CPU를 할당받아 실행함
  • 대기 : 프로세스가 입출력이나 이벤트 발생을 기다려야 해서 CPU 사용을 멈추고 기다림
  • 종료 : 프로세스 실행을 종료
  • 생성 → 준비 : 생성 상태의 프로세스가 OS로부터 승인을 받아, 준비 상태의 프로세스가 모여 있는 자료구조인 준비 큐에 추가됨
  • 준비 → 실행 : 준비 큐에 있는 프로세스 중 우선순위가 높은 프로세스가 디스패치되어 실행됨

    디스패치 (dispatch)

    프로세스에 CPU 자원을 할당해 해당 프로세스가 준비 상태에서 실행 상태가 되는 것을 의미한다.

  • 실행 → 준비 : CPU 독점을 방지하기 위해 타임아웃되어 준비 상태로 변경됨
  • 실행 → 대기 : 입출력 또는 이벤트 때문에 대기 상태로 변경됨
  • 대기 → 준비 : 입출력 또는 이벤트가 완료되어 준비 상태로 변경됨
  • 실행 → 종료 : 실행 중인 프로세스가 정상적으로 끝나서 종료 상태로 변경됨

2. 스레드

스레드

스레드란?

  • 프로세스에서 실제로 실행되는 흐름의 단위를 의미한다.
  • 프로세스는 한 개 이상의 스레드를 갖는다.
  • 스레드는 프로세스 안에 존재하므로 프로세스의 메모리 공간을 이용한다.
    • 지역 변수를 저장하는 스택 영역을 할당받는다.
    • 전역 변수를 저장하는 힙 영역은 다른 스레드와 공유한다.

프로세스와 스레드의 차이점

프로세스는 실행 중인 하나의 프로그램을 의미하며 실행의 단위라고 할 수 있다.
스레드는 프로세스 내에서 실행되는 흐름의 단위를 의미한다.

그래서 프로세스는 독립적인 메모리 영역을 가지만, 스레드는 스택 영역만 독립적이고 그 외 영역은 다른 스레드와 공유한다.

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

동시성과 병렬성

  • 동시성
    • 하나의 코어(싱글 코어)에서 여러 작업을 번갈아 가면서 처리하는 방식
      • 사용자 입장에서는 동시에 처리되는 것처럼 보인다.
    • 이 방식은 CPU에서 처리 중인 작업을 변경하기 위해 콘텍스트 스위칭이 일어나 오버헤드가 발생한다.
  • 병렬성
    • 여러 코어(멀티 코어)에서 여러 작업을 처리하는 것을 의미
      • 물리적인 시간 관점에서 동시에 여러 작업을 실행한다.

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

멀티 프로세스 (1 프로그램 : N 프로세스)

응용 프로그램 하나를 여러 개의 프로세스로 구성하는 것이다.

멀티 프로세스 환경에서는 한 프로세스가 죽어도 다른 프로세스에 영향을 주지 않는다. 그래서 응용 프로그램을 프로세스 하나로 구성하는 것보다 여러 개로 구성하는 것이 안정적이다.

콘텍스트 스위칭

하지만, 시간과 메모리 공간을 많이 사용한다는 단점이 있다. CPU는 하나의 작업만 처리할 수 있기 때문에 여러 프로세스를 처리하려면 CPU에서 처리 중인 프로세스를 교체하는 '콘텍스트 스위칭' 작업이 이루어져야 한다.

오버헤드

이때, CPU에서 기존에 처리하던 프로세스가 할당받은 메모리 영역을 다른 프로세스에서 사용할 수 있게 교체하면서 시간과 메모리가 필요한데, 이를 '오버헤드(overhead)' 라고 한다.

IPC

또한, 프로세스는 독립적인 메모리를 할당받는다. 따라서 프로세스 간에 공유할 자원이 있다면 'IPC(Inter Process Communication)' 를 통해 프로세스 간에 자원을 공유해야 한다. 이는 공유할 메모리를 직접 참조하는 것보다 비효율적이다.

멀티 스레드 (1 프로세스 : N 스레드)

한 프로세스 안에서 여러 스레드로 작업을 처리하는 것이다.

멀티 프로세스의 단점을 보완하는 멀티 스레드의 장점

멀티 스레드는 스레드 간에 힙, 데이터, 코드 영역을 공유하기 때문에 '콘텍스트 스위칭' 할 때 오버헤드가 적게 발생하고 IPC를 사용하지 않아도 된다. 이러한 점으로 인하여 멀티 스레드는 멀티 프로세스의 단점을 보완할 수 있다.

따라서, 독립적인 메모리 공간을 갖는 프로세스를 여러 개 생성하는 것보다 스레드를 여러 개 생성하는 것이 자원을 효율적으로 사용할 수 있다. 그리고 스레드 간 자원 공유가 프로세스 간 자원 공유보다 시스템 처리 비용이 적고 프로그램 응답 시간도 단축된다.

동기화

하지만 스택 영역을 제외한 영역들을 다른 스레드와 함께 사용하기 때문에 공유 자원에 대한 '동기화'가 필수다.

단점

또한, 스레드에 문제가 생기면 다른 스레드에 영향을 미칠 수 있다.

스레드 안전

스레드 안전은 이러한 멀티 스레드 환경에서 하나의 변수, 함수, 객체에 여러 개의 스레드가 동시에 접근해도 문제가 없음을 의미한다.

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

멀티 프로세스와 멀티 스레드의 중요한 차이점 중 하나는 자원 공간의 공유 여부이다.

프로세스는 독립적인 메모리 영역을 갖기 때문에 자원 공유와 통신을 위해서는 IPC를 활용해야 한다. 스레드는 자원 공간을 공유하기 때문에 스레드 간 통신과 자원 공유가 간단하고 프로세스 대비 콘텍스트 스위칭 비용이 적게 든다. 하지만, 동기화가 필요하다.

4. 콘텍스트 스위칭

멀티 프로세싱 환경에서 CPU가 처리 중인 프로세스의 정보를 바꾸는 것이 콘텍스트 스위칭이다.

콘텍스트 (context)

CPU가 처리하는 프로세스의 정보를 의미

CPU는 하나의 프로세스만 처리할 수 있으므로 멀티 프로세스를 처리하려면 CPU 스케줄러에 의해 인터럽트가 발생하면서 콘텍스트 스위칭이 발생한다. 이때 레지스터에 저장된 프로세스 정보가 바뀌면서 오버헤드가 발생한다.

인터럽트 (interrupt)

CPU에서 프로세스를 처리하다가 입출력 관련 이벤트가 발생하거나 예외상황이 발생할 때 이에 대응할 수 있게 CPU에 처리를 요청하는 것을 의미한다.

오버헤드

어떤 처리를 하는 데 간접적인 처리 시간과 메모리가 소요될 경우에 '오버헤드가 발생한다'고 한다.

프로세스가 변경되어도 이전 작업을 이어서 할 수 있는 이유

CPU에서 처리 중인 프로세스가 중간에 변경되어도 이전에 실행하던 코드를 이어서 실행할 수 있는 이유는 PCB에 프로그램 카운터와 스택 포인터 값이 저장되어 있기 때문이다.

프로그램 카운터(PC)는 프로세스가 이어서 처리해야 하는 명령어의 주소 값이고, 스택 포인터는 스택 영역에서 데이터가 채워진 가장 높은 주소 값을 가리킨다. 이어서 실행할 주소 값이 무엇인지, 데이터가 스택에 어디까지 채워져 있는지 알고 있기 때문에 콘텍스트 스위칭이 원활히 이뤄질 수 있다.

멀티 프로세스와 멀티 스레드에서의 콘텍스트 스위칭의 차이

멀티 프로세스에서의 콘텍스트 스위칭과 멀티 스레드에서의 콘텍스트 스위칭의 가장 큰 차이점은 멀티 스레드에서 콘텍스트 스위칭을 할 때 멀티 프로세스보다 오버헤드가 적게 발생한다는 점이다.

멀티 프로세스는 프로세스별로 고유한 메모리 영역을 갖는다. 반면에 멀티 스레드는 스택 영역을 제외한 메모리 영역을 공유하기 때문에 레지스터에 로드해야 하는 데이터 양이 적어서 오버헤드가 적게 발생한다.

5. 프로세스 동기화

프로세스 동기화는 여러 프로세스 또는 스레드가 하나의 공유 자원에 접근해도 일관성을 유지하는 것을 말한다. 공유 자원에 접근하는 코드를 임계 영역이라고 하며, 임계 영역에 대한 상호배제 기법이 잘 이루어져야 프로세스 동기화를 할 수 있다. 상호 배제 기법으로는 뮤텍스와 세마포어가 있다.

경쟁 상태와 임계 영역

  • 경쟁 상태 : 공유 자원에 동시에 접근해 경쟁하는 상태
  • 임계 영역 : 공유 자원에 접근할 수 있고 접근 순서에 따라 결과 값이 달라지는 코드 영역

임계 영역에서 경쟁 상태를 해결하는 방법

여러 프로세스 또는 스레드에서 하나의 공유 자원에 접근하는 경우가 있는데, 이때 자원에 접근하는 순서에 따라 결과 값이 달라질 수 있다. 임계 영역에서 경쟁 상태가 발생하는 것을 방지하려면 여러 프로세스가 공유 자원에 접근해도 데이터의 일관성이 유지되도록 '프로세스 동기화'를 해야 한다.

임계 영역에 여러 접근이 동시에 발생하는 것을 방지하려면 다음 3가지 조건을 충족해야 한다.

  • 상호배제 기법
    어떤 프로세스가 임계 영역을 실행 중일 때 다른 프로세스가 임계 영역에 접근할 수 없다. 상호 배제 기법으로 뮤텍스와 세마포어가 있다.
  • 진행 (progress)
    임계 영역을 실행 중인 프로세스가 없을 때 다른 프로세스가 임계 영역을 실행한다.
  • 한정된 대기
    임계 영역에 접근을 요청했을 때 무한한 시간을 기다리지 않는다.

상호배제 기법, 뮤텍스와 세마포어

뮤텍스

상호배제 기법 중 하나로, 락(lock)을 가진 프로세스만이 공유 자원에 접근할 수 있게 하는 방법이다. 임계 영역에 먼저 접근한 프로세스가 임계 영역에 락을 걸면 다른 프로세들은 해당 프로세스가 락을 해제하기 전까지 대기해야 한다.

바쁜 대기, 스핀락

임계 영역에 접근하지 못한 프로세스는 락을 얻기 위해 락을 기다리는 동안 락이 풀렸는지 반복문을 돌며 확인한다. 이를 바쁜 대기의 한 종류인 스핀락이라고 한다. 즉, 스핀락은 락을 얻기 위해 프로세스가 반복문을 돌면서 기다리는 것을 의미한다.

세마포어

상호배제 기법 중 하나로, 공유 자원에 접근할 수 있는 프로세스의 수를 정해 접근을 제어하는 방법이다. 공유 자원에 접근한 프로세스가 접근을 해제하면 다른 프로세스가 접근할 수 있도록 신호를 보낸다.

교착상태 (deadlock)

상호 배제 기법 때문에 2개 이상의 프로세스가 각각 자원을 가지고 있으면서 서로의 자원을 요구하며 기다리는 상태를 '교착 상태 (deadlock)'라고 한다.

교착 상태가 발생하는 필요 충분 조건은 다음과 같이 4가지가 있고, 교착 상태를 막으려면 4가지 중 한 가지를 제거하면 된다.

  • 상호배제
    하나의 공유 자원에 대해 하나의 프로세스만 사용할 수 있다는 개념이다.
    • 하나의 공유 자원을 여러 프로세스가 공유할 수 있게 되면 서로의 자원을 기다리는 상황을 예방할 수 있다.
  • 점유와 대기
    하나의 프로세스가 이미 자원을 가진 상태에서 다른 프로세스의 자원을 갖기 위해 기다리는 상황이다.
    • 프로세스가 자원을 요구할 때 필요한 자원을 모두 주거나 가진 자원이 없는 경우에만 자원을 할당함으로써 문제를 해결할 수 있다.
  • 비선점
    다른 프로세스가 가지고 있는 자원을 뺏을 수 없다는 개념이다.
    • 서로의 자원을 뺏을 수 있게 한다면 서로의 자원을 갖기 위해 대기하는 상황을 예방할 수 있다.
  • 환형 대기
    프로세스가 서로의 자원을 요구함으로써 생긴다.
    • 작은 번호 프로세스가 큰 번호 프로세스의 자원을 요구하는 것만 가능하게 한다면 큰 번호 프로세스가 작은 번호 프로세스의 자원을 요구할 수 없게 되므로 환형 대기를 없앨 수 있다.

6. IPC

IPC는 Inter Process Communication 의 약자로, 프로세스 간에 자원을 공유하는 방식을 나타낸다. 프로세스는 고유한 메모리 영역을 갖기 때문에 프로세스 간 자원을 공유할 때 IPC를 해야 한다.

공유 메모리

프로세스 간에 공유 가능한 메모리를 구성해 자원을 공유하는 방식이다.
여러 프로세스에서 접근할 수 있기 때문에 동기화 문제가 발생할 수 있다.

소켓

네트워크 소켓을 이용하는 프로세스 간 통신으로 외부 시스템과도 이용할 수 있다.
클라이언트와 서버 구조로 자원을 주고 받는다.

세마포어

접근하는 프로세스를 제어해 공유 자원을 관리한다.

파이프

FIFO 형태의 메모리 파이프를 이용해 프로세스 간 자원을 공유하는 방식이다.

파이프는 단방향 통신만 지원하기 때문에 읽기 또는 쓰기 중 하나만 가능하다. 양방향 통신을 하기 위해서는 읽기 파이프와 쓰기 파이프를 각각 생성해야 한다.

메시지 큐

FIFO 형태의 큐 자료구조를 사용해 프로세스 간 메시지를 주고받는 방식이다.

profile
I want to improve more 👩🏻‍💻

0개의 댓글