[운영체제+iOS] 프로세스와 스레드 (Process & Thread)

hye0n.gyu·2025년 12월 17일

운영체제+iOS

목록 보기
1/4
post-thumbnail

⭐ Process

🧩Process 구조

  • 프로세스가 추상화하는 것
    - Execution Unit(실행 단위): 스케줄링의 단위
    - Protection Domain(보호 도메인): 서로 침범하지 못함
    - 각 프로세스는 자신만의 독립된 메모리 공간을 가지며, 다른 프로세스의 영역을 함부로 침범할 수 없음.

  • 프로세스의 구성 요소
    - Program Counter : 현재 어떤 명령어를 실행하고 있는지를 가리킵니다.
    프로세스가 중단되었다가 다시 실행될 때, 정확히 멈췄던 지점부터 이어서 실행할 수 있도록 합니다.
    - Stack : 함수 호출 정보와 지역 변수를 저장합니다. 함수가 호출될 때마다 스택 프레임이 쌓이고, 반환되면 제거되는 구조로 동작
    - Data Section : 전역 변수와 정적 변수가 저장되는 영역입니다. 프로그램이 시작될 때 할당되어 종료될 때까지 유지됩니다.

🧩Process State

  • New: 프로세스가 생성되고 있는 상태
  • Running: 프로세스의 명령어들이 실제로 실행되고 있는 상태
  • Waiting: 프로세스가 어떤 사건(I/O 작업, signal 등)이 발생하기를 기다리고 있는 상태 (예: I/O 작업이 완료되거나, 신호(signal)를 수신하는 경우)
  • Ready: 프로세스가 CPU에 할당되기를 기다리고 있는 상태
  • Terminated: 프로세스의 실행이 종료된 상태

커널내에 Ready Queue, Waiting Queue, Running Queue를 두고 프로세스들을 상태에 따라 관리한다.

🧩 문맥전환(Context Switch)

CPU 1개로 여러 프로그램을 "동시에" 실행하는 것처럼 보이게하는 멀티태스킹 (Multitasking)을 위해서 새로운 프로세스로 전환될 때, 커널은 기존(현재) 프로세스의 상태를 저장하고, 새 프로세스의 저장된 상태를 로드하는 작업인 Context switching이 필요하다.

이 때 가장 중요한 것은 PCB(Process Control Block)이다. 프로세스의 모든 상태 정보를 담은 자료구조인 PCB가 없다면 프로세스는 다시 실행할 수 없다.

⭐ Thread

🧩 Thread의 등장 배경

  • 하나의 Process에는 하나의 Control만이 존재하기 때문에, 한 번에 하나의 일 만을 처리
  • Process에서 할 작업을 여러 개로 나눈 후에 각각을 Thread화 한다면, 병렬적으로 작업을 완수할 수 있음
  • Cooperative Process와의 차이점
    • Cooperative Process는 IPC(Inter-Process Communication)가 필요– 비용이 많이 듦
    • Process 사이의 Context Switching 비용
    • Process 내에서 Cooperation하는 Thread를 만든다면
      → Process보다 적은 비용으로 Cooperative Process가 하는 일을 동일하게 수행 가능

🧩 Thread의 구성 요소

  • Thread마다 존재하는 것 - 실행과 관련된 자료 구조
    • Thread ID – Thread 식별자
    • Program Counter – 현재 실행중인 Instruction의 주소
    • Register Set - CPU의 Register 값들
    • Stack
      • Process보다 Thread의 고유 정보 수가 적기 때문에 Thread Switching 비용이 적음
  • 동일한 Process 내에 있는 다른 Thread와 공유하는 것
    • Code – Program의 Code Section
    • Data – Process의 Data Section
    • File – Process에서 Open한 File

🧩 Thread Issues: Thread간 IPC

  • Multithreaded Programming에서는 Thread 간 통신이 필요함
  • ThreadIPC 구현은?
    • 동일한 Process 내의 Thread 간 통신은, 공유 Memory가 효율적임
      • 이유: Thread들은 같은 Process의 Data 영역을 공유하므로, 자연스런 공유 Memory가 가능해짐
  • 결국 IPC가 최소화 됨
    • Thread들 간의 자원 공유로 인하여 가능해짐
  • 다른 Process에 존재하는 다른 Thread와의 통신은?
    • Process의 경우와 비슷한 성능을 보임
    • 이런 통신이 빈번하다면, Program 설계의 잘못 - thread를 만드는 이유가 모호해짐

⭐ Process vs. Thread 차이

🧩 Process vs. Thread

  • Process
    • 하나의 Thread와 같은 실행 흐름을 가짐
    • Process 간의 Memory는 독립적이므로, 서로의 영역에 접근하기 어려움
    • Process 간의 Switch 비용이 큼 (상대적으로 Heavy Weight)
  • Thread
    • 하나의 Process 안에 여러 개의 Thread가 존재
    • Process의 Code영역과 Data영역은 Thread간에 공유
    • Thread들은 같은 Memory 영역을 사용하므로, Thread간 Switch 비용이 적음

⭐ iOS에서의 Main Thread와 Background Thread

iOS 앱은 기본적으로 Main Thread에서 시작됩니다. Main Thread는 UI 업데이트를 담당하는 유일한 스레드로, 모든 UI 관련 작업은 반드시 여기서 실행되어야 합니다.

🧩 Main Thread (UI Thread)

DispatchQueue.main.async {
    recognizedText = ...
}

앱 실행 시 자동으로 생성
UI 렌더링, 사용자 입력 처리 담당
무거운 작업을 실행하면 앱이 버벅이거나 멈춤 (UI Freeze)

기본적으로 작업은 메인 쓰레드에서 실행된다.

UI 업데이트, 사용자 입력, 화면 표시 등 모든 사용자 인터페이스 관련 작업은 이곳에서만 해야합니다.

DispatchQueue.main.async를 쓰는 이유
DispatchQueue.main.async는 Background 클로저 안에서 UI 업데이트가 필요할 때 Main Thread로 전환하기 위해 사용한다. 이미 Main Thread라면 쓸 필요 없다.

DispatchQueue.global(qos: .background).async {
    let data = fetchDataFromServer()
   
    DispatchQueue.main.async {
        self.updateUI(with: data)
    }
}

SwiftUI의 @State, @Binding, View 업데이트 등은 항상 메인 스레드에서 실행해야 한다.

백그라운드에서 이걸 바꾸려고 하면 앱이 충돌이 일어난다.

결과만 메인 스레드로 넘겨서 안전하게 UI에 적용하는 것.

🧩 Background Thread

DispatchQueue.global(qos: .userInitiated).async {
    try handler.perform([request])
}

네트워크 요청, 파일 I/O, 복잡한 연산 등 시간이 오래 걸리는 작업 수행
Main Thread를 블로킹하지 않아 UI가 부드럽게 유지됨

이미지 처리, OCR, 네트워크 통신, 데이터 저장 등 무거운 연산이나 시간이 걸리는 작업을 담당합니다.

Vision의 OCR 엔진은 이미지 분석이라는 무거운 작업을 한다.

그렇기 때문에 메인 스레드에서 하면 앱이 멈춘 듯 버벅거리기 때문에

다른 스레드(백그라운드 스레드)에서 처리해야 한다.

🧩 qos란?

Quality of Service (서비스 품질)의 줄임말이다.
즉, 이 작업이 얼마나 중요한 작업인가? 를 시스템에게 알려주는 우선순위 등급을 뜻한다.

QoS설명예시
.userInteractive가장 높은 우선순위, 즉시 완료되어야 하는 UI 반응성 작업드래그, 스크롤 등
.userInitiated사용자가 요청한 작업으로, 즉시 필요하지만 약간의 처리 시간은 허용OCR 처리, 검색 실행
.default기본 우선순위 (명시하지 않으면 사용)일반적인 작업
.utility오래 걸리지만 급하지 않은 작업다운로드, 파일 처리
.background사용자가 직접 보지 않아도 되는 작업백업, 캐시 저장
.unspecified특별히 지정하지 않음 (시스템 판단에 맡김)잘 쓰지 않음

실무에서는 특별한 이유가 없으면 DispatchQueue.global().async기본값(.default)을 사용하는 경우가 많다.

⭐ 멀티코어 활용 전략

🧩 Multicore Programming

  • 최근 Processor 설계 동향은 하나의 Chip에 여러 개의 Computing Core를 탑재 -> Multicore Processor
  • Multithread ProgrammingMulticore 시스템에서도 효율적임
    • Multicore Processor는 운영체제에서 각각의 Core를 하나의 Processor로 인식하고 Scheduling
    • 각각의 Thread에 Core를 할당하여 실행 가능
    • Multiple Processor가 달린 Multicore는 Cache를 공유하기 때문에 Data, Code, 등 Process 자원을 공유하는 Multithreaded Programming에 보다 효율적임

멀티코어에서 멀티스레딩이 효율적인 이유
멀티스레딩은 같은 프로세스 내에서 데이터를 공유한다. 멀티코어 CPU에서는 여러 코어가 캐시(L3)를 공유하기 때문에, 공유 데이터에 접근할 때 RAM보다 훨씬 빠른 캐시를 활용할 수 있다. 덕분에 멀티코어 환경에서 멀티스레딩이 더 효율적으로 동작한다.

핵심: 캐시 공유RAM 접근 감소속도 향상

🧩 iOS에서의 멀티코어 활용

iOS는 위에서 배운GCDOperation Queue를 통해 멀티코어를 자동으로 활용한다.

// 병렬 처리 - 시스템이 알아서 여러 코어에 분배
DispatchQueue.concurrentPerform(iterations: 100) { index in
    processItem(at: index)
}

concurrentPerform은 반복문을 여러 코어에서 병렬로 실행하는 함수이다.

profile
반려묘 하루 velog

0개의 댓글