[기술면접] 프로세스

uddi·2023년 11월 28일
0

기술면접

목록 보기
2/3

프로세스

⭐️⭐️⭐️프로세스와 스레드

🚨 프로세스는 컴퓨터에서 실행 중인 하나의 프로그램을 의미한다
프로세스는 운영체제로부터 독립된 메모리 영역(코드, 데이터, 스택, 힙)을 할당받으며, 다른 프로세스의 메모리 영역에 접근할 수 없다

프로세스에 할당된 메모리 영역

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

  • 스택 : 지역 변수, 함수의 매개변수, 반환되는 주소 값 등이 저장되는 영역으로 높은 주소 값에서 낮은 주소 값으로 메모리가 할당되며, 영역 크기는 컴파일 때 결정됨
  • 힙 : 사용자에 의해 동적 메모리 할당이 일어나는 영역으로 C언어에서 malloc( )으로 할당되는 영역이라고 보면 됨, 낮은 주소 값에서 높은 주소 값으로 메모리가 할당되며, 영역 크기는 런타임 때 결정됨
  • 데이터 : 전역 변수, 정적 변수, 배열, 구조체 등이 저장되는 영역으로 세부적으로 BSS(Block stated Symbol) 영역과 데이터 영역으로 다시 나눌 수 있음 → BSS 영역은 초기화하지 않은 변수, 데이터 영역은 초기화한 변수를 저장
  • 코드 : 실행할 코드가 기계어로 컴파일되어 저장되는 영역으로 텍스트 영역이라고도 함

스택 영역과 힙 영역은 동적으로 메모리 할당이 가능해 두 영역 사이에 빈 메모리 공간이 존재한다

→ 메모리 영역을 공유하기 때문에 서로의 영역을 침범하는 문제가 생길 수 있음

스택 영역이 힙 영역을 침범 : 스택 오버플로

힙 영역이 스택 영역을 침범 : 힙 오버플로

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

프로세스는 한 개 이상의 스레드를 가진다

사용자 레벨 스레드와 커널 레벨 스레드

스레드도 커널과 마찬가지로 스레드를 관리하는 주체에 따라 구분된다

  • 사용자 레벨 스레드 : 사용자가 라이브러리를 이용해 생성 및 관리
  • 커널 레벨 스레드 : 커널이 스레드를 생성 및 관리

멀티 스레드 환경에서 사용자 레벨 스레드와 커널 레벨 스레드는 3가지 관계를 맺을 수 있음

  1. 다대일 모델
  2. 일대일 모델
  3. 다대다 모델

⭐️⭐️ PCB

🚨 운영체제는 프로세스를 제어하기 위해 프로세스 정보를 저장하는데, 이를 PCB(프로세스 제어 블록)라고 한다

PCB는 프로세스의 현재 상태, 고유 PID, 부모 프로세스의 PID, 자식 프로세스의 PID, 다음 실행할 명령어의 주소인 PC(program counter), 프로세스의 우선순위, 메모리 제한 등을 저장

⭐️⭐️⭐️프로세스의 생성

새로운 프로세스는 기존 프로세스에서 fork( ) 함수를 호출해 생성한다

🚨 부모 프로세스에서 fork( ) 함수를 호출하면 부모 프로세스는 자식 프로세스의 PID 값을, 자식 프로세스는 0을 반환

운영체제가 프로세스를 종료하는 경우

  • 프로세스가 운영체제의 종료 서비스 (exit())를 호출해 정상 종료하는 경우
  • 프로세스의 실행 시간이나 특정 이베트 발생을 기다리는 시간이 제한된 시간을 초과한 경우
  • 프로세스가 파일 검색 또는 입출력에 실패하는 경우
  • 오류가 발생하거나 메모리 부족 등이 발생하는 경우

부모 프로세스가 자식 프로세스를 종료시키는 경우

  • 자식 프로세스가 할당된 자원을 초과해 사용할 때
  • 자식 프로세스에 할당된 작업이 없을 때

⭐️⭐️⭐️프로세스 상태도

모든 프로세스는 CPU에 의해 생성되고 소멸하는 과정을 거친다

🚨 이 과정에서 프로세스는 생성, 준비, 대기, 실행, 종료의 상태로 존재

  • 생성 : 프로세스가 PCB를 가지고 있지만 운영체제로부터 승인받기 전
  • 준비 : 운영체제로부터 승인받은 후 준비 큐에서 CPU 할당을 기다림
  • 실행 : 프로세스가 CPU를 할당받아 실행
  • 대기 : 프로세스가 입출력이나 이벤트 발생을 기다려야 해서 CPU 사용을 멈추고 기다림
  • 종료 : 프로세스 실행 종료

프로세스 상태 변화

  • 생성 → 준비 : 생성 상태의 프로세스가 운영체제로부터 승인받아 준비 상태의 프로세스가 모여 있는 자료구조인 준비 큐에 추가됨
  • 준비 → 실행 : 준비 큐에 있는 프로세스 중 우선순위가 높은 프로세스가 디스패치되어 실행
  • 실행 → 준비 : CPU 독점을 방지하기 위해 타임아웃되어 준비 상태로 변경
  • 실행 → 대기 : 입출력이나 이벤트 때문에 대기 상태로 변경
  • 대기 → 준비 : 입출력이나 이벤트가 완료되어 준비 상태로 변경
  • 실행 → 종료 : 실행 중인 프로세스가 정상적으로 끝나서 종료 상태로 변경

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

  • 동시성 : 하나의 코어(싱글 코어)에서 여러 작업을 번갈아 가면서 처리하는 방식
    • 콘텍스트 스위칭 : CPU에서 여러 작업을 번갈아 가면서 처리하기 위해 처리 중인 작업을 교체하는 것
  • 병렬성 : CPU가 여러 개(멀티 코어) 있어서 각 CPU에서 각 작업을 동시에 처리하는 방식

멀티 프로세스

🚨 멀티 프로세스는 응용 프로그램 하나를 여러 프로세스로 구성하는 것 의미

→ 응용 프로그램을 프로세스 하나로 구성하는 것보다 여러 개로 구성하는 것이 안정적

단점 : 시간과 메모리 공간을 많이 사용 → 콘텍스트 스위칭 작업 중 CPU에서 기존에 처리하던 프로세스가 할당받은 메모리 영역을 다른 프로세스에서 사용할 수 있게 교체하면서 시간과 메모리 필요 ⇒ 오버헤드

프로세스는 독립적인 메모리를 할당받기 때문에 프로세스 간에 공유할 자원이 있다면 IPC(inter process communication)을 통해 프로세스 간 자원을 공유해야 한다 → 공유할 메모리를 직접 참조하는 것보다 비효율적

멀티 스레드

🚨 멀티 스레드는 스레드를 여러 개 생성해 스레드들이 각자 다른 작업을 처리하는 것 의미

스레드 간에 힙, 데이터, 코드 영역을 공유하므로 콘텍스트 스위칭할 때 오버헤드가 적게 발생하고 IPC를 사용하지 않아도 되어 멀티 프로세스의 단점을 보완할 수 있다 → 자원 공유 시 시스템 처리 비용이 적고 프로그램 응답 시간도 단축

⇒ 독립적인 메모리 공간을 갖는 프로세스를 여러 개 생성하는 것보다 멀티 스레드가 자원을 효율적으로 사용 가능

단점 : 공유 자원에 대한 동기화 필수, 스레드에 문제가 생기면 프로세스 내 다른 스레드에 영향을 미칠 수 있음

⭐️⭐️⭐️ 콘텍스트 스위칭

  • 인터럽트 : CPU에서 프로세스를 처리하다가 입출력 관련 이벤트나 예외 상황이 발생할 때 이에 대응할 수 있게 CPU에 처리를 요청하는 것 의미
    • 인터럽트 발생하는 경우 : 입출력 발생, CPU 사용 시간 만료, 자식 프로세스 생성
  • 콘텍스트 : CPU가 처리하는 프로세스의 정보

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

콘텍스트 스위칭 과정

처리 중인 프로세스를 P1, 다음에 처리해야하는 프로세스를 P2라고 할 때 CPU가 P1을 처리하던 중 운영체제에 의해 인터럽트가 발생한다 → P1은 유휴 상태로 변하고 스케줄러는 레지스터에 있는 처리 중인 작업 정보를 P1의 PCB에 저장, P2의 PCB에 있는 정보를 가져와 레지스터에 로드하고 CPU는 P2를 처리하기 시작

P1의 정보를 저장하고 P2의 정보를 레지스터에 로드하는 동안 CPU는 아무 일도 못하게 되는데, 이처럼 어떤 처리를 하는 데 간접적인 처리 시간과 메모리가 소요되는 경우 ‘오버헤드가 발생한다‘고 한다

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

🚨 프로그램 카운터는 프로세스가 이어서 처리해야 하는 명령어의 주소 값
스택 포인터는 스택 영역에서 데이터가 채워진 가장 높은 주소 값

⭐️⭐️⭐️프로세스 동기화

경쟁 상태

🚨 여러 프로세스나 스레드에서 하나의 공유 자원에 접근하는 경우, 자원에 접근하는 순서에 따라 결과 값이 달라질 수 있는데 이러한 현상을 공유 자원에 동시에 접근해 경쟁하는 상태라고 해서 경쟁 상태라고 한다

임계 영역

🚨 공유 자원에 접근할 수 있고 접근 순서에 따라 결과가 달라지는 코드 영역을 임계 영역이라고 한다

임계 영역에서 경쟁 상태가 발생하는 것을 방지하려면 여러 프로세스가 공유 자원에 접근해도 데이터의 일관성이 유지되도록 프로세스 동기화를 해야 함

임계 영역에 여러 접근이 동시에 발생하는 것 방지하기 위한 조건

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

뮤텍스

🚨 뮤텍스는 lock을 가진 프로세스만이 공유 자원에 접근할 수 있게 하는 방법이다

임계 영역에 접근한 프로세스가 임계 영역에 락을 건다고 해서 락킹 매커니즘이라고도 함

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

⇒ 스핀락 : 락을 얻기 위해 프로세스가 반복문을 돌면서 기다리는 것

⇒ 프로세스가 대기 상태가 되지 않고 반복문을 돌면서 자원의 사용 가능 여부를 확인하므로 프로세스가 빠르게 교체될 수 있다

세마포어

🚨 세마포어는 공유 자원에 접근할 수 있는 프로세스의 수를 정해 접근을 제어하는 방법이다

공유 자원에 접근한 프로세스가 접근을 해제하면 다른 프로세스가 접근할 수 있도록 신호를 보낸다고 해서 시그널링 매커니즘이라고도 함

동기/비동기 & 블로킹/넌블로킹

동기와 비동기는 작업 순서에 대한 개념, 블로킹과 넌블로킹은 작업을 위한 대기를 구분하는 개념

  • 동기 : 여러 작업을 처리할 때 작업 순서를 보장
  • 비동기 : 여러 작업을 처리할 때 작업 순서를 보장하지 않음
  • 블로킹 : 작업을 수행할 때 대기할 수 있다는 것을 의미하며 작업 순서를 보장하지 않음
  • 넌블로킹 : 작업을 시작하면 대기 없이 수행한다는 것 의미

⭐️⭐️⭐️교착 상태

🚨 2개 이상의 프로세스가 각각 자원을 가지고 있으면서 서로의 자원을 요구하며 기다리는 상태를 교착상태라고 한다

교착 상태 발생 필요 충분 조건

  • 상호배제 : 하나의 공유 자원에 하나의 프로세스만 접근 가능
  • 점유와 대기 : 프로세스가 최소 하나의 자원을 점유하고 있는 상태에서 추가로 다른 프로세스에서 사용 중인 자원을 점유하기 위해 대기
  • 비선점 : 다른 프로세스에 할당된 자원을 뺏을 수 없음
  • 환형 대기 : 프로세스가 자신의 자원을 점유하면서 앞이나 뒤에 있는 프로세스의 자원 요구

교착 상태를 막기 위해서는 필요 충분 조건 중 한 가지를 제거하면 된다

⭐️⭐️스레드 안전

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

스레드 안전이 이뤄지지 않는 경우

스레드 안전을 위한 조건

  • 상호 배제
  • 원자 연산 : 공유 자원에 접근할 때 원자 연산을 이용하거나 원자적으로 정의된 연산을 이용해 연산 도중에 다른 스레드가 접근할 수 없게 한다 → ‘연산했다’와 ‘연산 안했다’ 두가지만 존재하는 연산
  • 재진입성 : 특정 함수를 하나의 스레드에서 실행 중일 때 다른 스레드가 해당 함수를 실행해도 각 스레드에 올바른 결과가 나올 수 있게 해야 한다
  • 스레드 지역 저장소 : 각 스레드에서만 접근할 수 있는 저장소를 사용해서 공유되는 자원을 줄여야 한다

⭐️⭐️IPC

🚨 IPC는 프로세스 간에 자원을 공유하는 방식을 나타낸다

공유 메모리

여러 프로세스에서 접근할 수 있기 때문에 동기화 문제가 발생할 수 있다

소켓

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

세마포어

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

파이프

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

파이프는 단방향 통신만 지원하므로 양방향 통신을 하려면 읽기 파이프와 쓰기 파이프를 각각 생성해야 함

메시지 큐

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

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

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

자식 프로세스가 종료될 때 부모 프로세스에 시그널을 보내면 부모 프로세스에서 wait( ) 함수를 호출해 자식 프로세스의 상태 정보를 받고 자원을 회수한다

이때 자원 회수에 실패하면 좀비 프로세스가 생기게 되고 이게 쌓이면 자원이 낭비될 수 있다

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

자식 프로세스의 부모 PID를 init 프로세스의 PID인 1로 바꿔주면 고아 프로세스의 부모 프로세스는 init 프로세스가 되고, 고아 프로세스가 작업을 종료하면 init 프로세스가 고아 프로세스의 자원을 회수해 좀비 프로세스가 되는 것을 방지할 수 있다

profile
거북이는 느리지만 결국 결승선을 통과한다

0개의 댓글