본문 바로가기

오퍼레이팅 시스템

오퍼레이팅 시스템 : Threads and Synchronization

1. Process and Thread

1) Process and Thread

(1) Process 

  • 실행중인 프로그램(프로그램의 인스턴스)
  • 일련의 명령이 실행되는 것을 특징으로 하는 활동 단위 및 관련 시스템 자원 집합

(2) Two characteristics

  1. The unit of resource ownership(자원 소유권의 단위)
    • 프로세스에 메인 메모리, I/O 채널, I/O 장치 및 파일과 같은 리소스의 제어 또는 소유권을 할당할 수 있다.
  2. The unit of scheduling / execution(스케줄링/실행 단위)
    • 프로세스는 실행 상태(Running, Ready 등)와 priority(우선순위)를 가지며 OS에 의해 예약된 엔티티이다.
지금까지는 프로세스에 단일 실행 시퀀스가 있다고 가정했음
- 실행 단위는 일반적으로 스레드(또는 lightweight process)라고 하며, 리소스 소유권 단위는 일반적으로 프로세스(또는 task)라고 한다.

2) Multithreading

  • 모든 최신 OS는 프로세스에 여러 스레드를 포함할 수 있는 기능을 제공한다.
    • 대부분의 소프트웨어 애플리케이션은 멀티 스레드이다.
  • Multithreading
    • 단일 프로세스 내에서 여러 동시 실행 경로를 지원하는 OS 기능
    • 프로세스 내에 하나 이상의 스레드가 있을 수 있음

스레드는 같은 프로세스 안에 다른 스레드와 같은 자원을 공유한다.

3) Concurrency

  • 멀티스레드 프로세스는 여러 프로세스를 사용하는 오버헤드 없이 동시성을 달성한다.
  • Concurrency(동시성)
    • concurrency system은 모든 작업이 진행되도록 허용하여 둘 이상의 작업을 지원한다.
    • concurrency와 parallelism(병렬성)의 차이
    • Parallelism(병렬화) : parallel system은 두 개 이상의 작업을 동시에 수행할 수 있다.
    • 따라서 병렬화 없이 동시성을 갖는 것이 가능

왼쪽 그림의 경우 프로세스가 동시에 실행되었지만, 병렬로 실행되지 않음

4) Multithreading Example

  • 단일 프로세서에서 멀티프로그래밍은 여러 프로세스 내에서 여러 스레드의 interleaving을 가능하게 한다.

스레드 B가 Ready가 되었음에도 불구하고 스레드 A가 quantum을 모두 사용한 후 스레드 C가 실행되기 시작한다. B와 C 중 하나를 선택하는 것은 scheduling decision이다.

2. Motivation

1)  Motivation

  • 응용 프로그램에는 여러 task가 있으며 다른 task가 blocking(차단)되지 않고 계속 진행되도록 허용하는 것이 좋음
  • 예시) 여러 개의 클라이언트가 동시에 있는 busy web server
    1. Traditional single-threaded process(기존의 단일 스레드 프로세스)
      • 한 번에 하나의 클라이언트만 서비스할 수 있음
      • 클라이언트가 요청을 위해 매우 오랜 시간을 기다려야 할 수 있음
    2. Multi-processing soluction
      • 서버는 요청을 수신할 때 요청을 처리하는 새 프로세스를 만듦
    3. Multi-threading soluction
      • 요청이 이루어지면 서버는 다른 프로세스를 생성하는 대신 요청을 처리할 새 스레드를 생서앟고 추가 요청 수신을 재개한다.

(1) Web Server 예시 코드

  • 여러 개의 동시 요청을 처리하는 웹 서버
// Single-thread, Single-process
void main(){
	…
	while(1) {
		int sock = accept();
		// It would be able to service only one client at a time
		// It may be a lengthy operation
	}
}
// Single-thread, Multi-process
void main(){
	…
	while(1) {
		int sock = accept();
		if ((pid = fork()) == 0 ) {
		// A child process services the requests
		}
	}
}
// Multi-thread
void *mythread(void){
	…
}
void main(){
	…
	while(1) {
		int sock = accept();
		create_thread(mythread);
		// child thread handles the requests
	}
}

(2) Multithreading

  1. 프로세스당 단일 실행 스레드에 대한 기존 접근 방식
  2. UNIX는 여러 프로세스를 지원하지만 프로세스당 하나의 스레드만 지원
  3. JVM은 여러 스레드가 있는 하나의 프로세스 시스템의 예이다.
  4. 최신 OS는 일반적으로 멀티스레드이다.

3. Benefits

1) Benefits : Faster response

  • Responsiveness(반응성)
    • 응용 프로그램은 프로그램의 일부가 실행 중인 경우에도 프로그램을 계속 실행할 수 있음
    • I/O와 computation이 중복될 수 있음
  • 예시) RPC(Remote Procedure Call)
    • 단일 스레드 : 프로그램은 각 서버의 응답을 차례로 기다려야 한다.
    • 멀티 스레드 : 두 응답을 동시에 기다림

RPC(Remote Procedure Call) : 서로 다른 컴퓨터에서 실행될 수 있는 두 프로그램프로시저 call/return 구문 및 semantics(의미론)을 사용하여 상호 작용하는 시스템 SW 기술

2) Benefits : Creation/communcation cost

  1. Economy of time
    • 전체  PCB를 새로 작성할 필요 없음
    • 전환이 프로세스보다 빠름
  2. Resoure sharing(자원 공유)
    • 프로세스 간의 통신에는 보호를 제공하기 위한 커널의 개입과 통신에 필요한 메커니즘이 필요
    • 스레드는 공유 메모리와 같은 기술을 통해서만 리소스를 공유할 수 있음
      • 이러한 기술은 프로그래머에 의해 명시적으로 배열되어야 함
      • 예) int fd = shm_open(name, ..);
    • 메모리에서 동일한 데이터를 읽고 쓰는 방식으로 스레드 공동 작업이 가능하다.

왼쪽 멀티프로세스 / 오른쪽 멀티 스레드

3) Benefits : Parallel Processing

  • Scalability on multi-core architecture(멀티코어 아키텍처의 확장성)
    • 멀티코어 아키텍처에서는 멀티스레드의 이점이 훨씬 더 클 수 있음
    • 여러 코어에서 동일한 애플리케이션 실행 가능
    • 프로세스를 여러 CPU에서 실행할 수 있음(parallelism)

4. Multithreading

1) Multithreading on Multicore

  • 멀티코어 시스템에서 멀티스레드 애플리케이션의 성능 확인
    • 속도 향상의 개념은 Amdahl의 법칙에 의해 확립됨

  • 16개의 프로세서가 있는 시스템에서 행렬 곱셈 및 FFT(Fast Fourier Transfrom) 계산

스레드가 많다고해서 좋은 것은 아니다!! → rescheduling overhead가 증가하기 때문!!

  • 프로그래밍 문제
    1. Identifying task(작업 식별) : 작업은 서로 독립적이므로 병렬로 실행할 수 있음
    2. Balance : 프로그래머는 또한 작업이 동일한 가치의 동일한 작업을 수행하는지 확인해야 함
    3. Data dependecny(데이터 종속성) : 작업에 의해 액세스되는 데이터에서 두 개 이상의 작업 간의 종속성을 검사해야 한다. 한 작업이 다른 작업의 데이터에 의존하는 경우 프로그래머는 작업 실행이 데이터 종속성을 수용하도록 동기화되어야 함

5. Multithreaded Process Model

1) Mutithreaded Process Model

  • 먼저 각 스레드에 대해 별도의 스택이 필요
    • 각 스레드에는 고유한 실행 스택(User/Kernel)이 있음

  • Thread Control Block(TCB)
    • 레지스터 값, 기타 스레드 관련 스케줄링 및 상태 정보 및 스택을 포함하는 각 스레드에 대해 별도의 스레드 관련 control block이 필요

(1) Thread Creation

  • 기존 프로세스에서 새 스레드를 생성하는 시간이 새 프로세스를 생성하는 시간보다 훨씬 적음
  • 프로세스 간에 전환하는 것보다 동일한 프로세스 내에서 두 스레드 간에 전환하하는 것이 성능이 더 좋음

lightweight process는 thread와 동일하게 사용

(2) Multithreading Models

  • 스레드 구현에는 두 가지 광범위한 범주가 있다
    1. ULT(User-level thread)
    2. KLT(Kernel-level thread)
    3. 결합된 방법

6. Implementation of Threads

1) User Level Thread

  • 모든 스레드 관리는 애플리케이션에 의해 수행됨
    • 스레드 라이브러리를 사용하여 멀티스레드 가능
    • 스레드 라이브러리에는 스레드 생성 및 삭제, 스레드 간 메시지 및 데이터 전달, 스레드 스케줄링, 그리고 스레드 컨텍스트 저장 및 복원을 위한 코드가 포함되어 있음
    • 프로시저 콜에 의해 control이 전달
  • 스레드 간 전환에는 다음이 수반됨
    • 라이브러리가 라이브러리의 TCB에 저장 또는 로드
    • 라이브러리에서 실행할 새 스레드 선택
    • 하지만 커널은 관여하지 않음
  • 예시
    • 기존 UNIX 시스템과 마찬가지로 이전 버전의 Linux 커널은 멀티스레딩을 지원하지 않았다
    • 대신 user-level 라이브러리 함수 집합을 사용하여 애플리케이션을 작성해야 했다.
    • java 초기 버전의 green thread

(1) 장점

  • 스레드 관리는 스레드 라이브러리가 User space에서 수행하므로 효율적
  • ULT는 모든 OS에서 실행이 가능
    • 기본 OS는 스케줄러를 중단하지 않고 애플리케이션에 맞게 조정 가능

(2) 제한 사항

  • 그러나 이러한 접근 방식은 스레드의 주요 이점을 제거한다.
  • 커널은 한 번에 하나의 커널 스레드만 스케줄링할 수 있기 때문에 병렬 처리를 하지 않음
  • 스레드가 blocking system call을 수행하면 전체 프로세스가 blocking됨

(3) 해결책

  • blocking system call을 jacketing이라는 non-blocking system call로 변환한다.

2) Kernel Level Thread

  • pure KLT에서 스레드 관리의 모든 작업은 커널에 의해 수행됨
    • 커널은 프로세스 내의 개별 스레드에 대한 컨텍스트 정보를 유지
    • 응용 프로그램 수준에 스레드 관리 코드가 없음
    • 커널 스케줄링된 엔티티 1개당 스레드 1개
  • OS-managed thread를 kernel-level thread라고 함

(1) 장점

  • 멀티프로세서에서 여러 스레드를 병렬로 실행할 수 있음
  • 스레드가 blocking system call을 할 때 다른 스레드가 실행되도록 허용하여 더 많은 동시성을 제공

(2) 제한사항

  • 동일한 프로세스 내에서 한 스레드에서 다른 스레드로 제어를 전송하려면 커널로 모드 전환이 필요
  • 세부적인 동시성의 경우 커널 수준 스레드는 여전히 오베해드가 너무 큼
  • ULT와 KLT 간의 차이가 크기 순 이상인 경우

Null Fork : null procedure를 실행하는 프로세스/프로시저를 생성하고 완료하는 시간
Signal Wait : 프로세스/thread가 대기 중인 프로세스/thread에 신호를 보낸 후 조건에 따라 대기하는 시간

3) Combined

  • 일부 OS는 결합된 ULT/KLT를 제공
    • 스레드 생성은 사용자 공간에서 수행됨
    • 단일 애플리케이션의 여러 ULT가 일부(더 작거나 같은) KLT에 매핑됨
    • 프로그래머는 KLT의 수를 조정할 수 잇음
    • Solaris는 이 결합된 접근 방식을 사용하는 OS의 좋은 예

4) Kernel- vs User-level Threads

  1. Kernel-level thread
    • OS와 통합
    • 생성, 조작, 동기화가 느림
  2. User-level thread
    • 신속한 생성, 조작 동기화
    • OS와 통합되지 않음
  3. 커널과 사용자 수준 스레드 간의 차이점을 이해하는 것이 중요!!!
    • 프로그래밍의 정확성, 성능을 위해

7. Thread API

1) Thread API

  • POSIX(UNIX 기반 휴대용 운영 체제)는 스레드 API에 대한 표준을 포함하는 IEEE API 표준이다.
    • POSIX 스레드 표준을 구현하는 라이브러리는 종종 Pthread로 불림
    • Pthread는 Linux 및 Solaris와 같은 UNIX와 유사한 POSIX 시스템에서 가장 일반적으로 사용되지만 마이크로스프트 윈도우즈 구현도 존재

2) Posix Threads(Pthreads) Interface

  • Pthreads : 스레드를 조작하는 최대 60개의 함수를 위한 표준 인터페이스
  • 기본 pthread 함수
pthread_create – create child thread
pthread_exit – thread termination
pthread_join – wait for thread termination
pthread_self – return the calling thread ID
phtread_mutex_lock – lock critical section
pthread_mutex_unlock – unlock critical section
pthread_cond_wait – wait for a condition signal
phtread_cond_signal – wake up one waiting thread

(1) Creating Threads

  • 스레드는 pthread-create를 호출하여 다른 스레드를 만듦
    • pthread_create 함수는 새 스레드를 만들고 새 스레드의 컨텍스트에서 arg의 입력 인수를 사용하여 스레드 루틴 f를 실행
    • attr 인수를 사용하여 기본 특성을 변경할 수 있다.
      • Scheduling priority 등...
    • pthred_create가 반환되는 경우 인수 tid에는 새로 생성된 스레드의 ID가 포함됨
#include <pthread.h>
typedef void *(func)(void *);

int pthread_create(pthread_t *tid, pthread_attr_t *attr, func *f, void *arg);

Returns: 0 if OK, nonzero on error

(2) Terminating Threads

  • pthread_self() 함수는 호출 스레드의 ID를 반환
#include <pthread.h>
pthread_t pthread_self(void);

Returns: thread ID of caller
  • 스레드는 다음 방법 중 하나로 끝남
    • 스레드 루틴이 돌아오면 스레드가 암시적으로 종료
    • 스레드는 pthread_exit를 호출하여 명시적으로 종료
#include <pthread.h>
void pthread_exit(void *thread_return);

Never returns

(3) Reaping Terminated Threads

  • 스레드는 pthread_join을 호출하여 다른 스레드가 종료될 때까지 기다림
    • pthread_join함수는 스레드 tid가 종료될 때까지 차단한 다음 종료된 스레드가 보유한 메모리 리소스를 가져옴
#include <pthread.h>
int pthread_join(pthread_t tid, void **thread_return);

Returns: 0 if OK, nonzero on error

3) Thread API 예시

(1) 예시 1

argv[1] = 4(사용자가 실행 시 준 인자값)

(2) 예시 2 : gcc thread.c -lpthread

전역 변수 x의 경우 0으로 초기화됨

<결과>

전혀 다른 결과가 나옴

<분석>

(3) Race Condition

Race Condition : 두 개 이상의 프로세스가 공통 자원을 병행적으로(concurrently) 읽거나 쓰는 동작을 할 때, 공용 데이터에 대한 접근이 어떤 순서에 따라 이루어졌는지에 따라 그 실행 결과가 같지 않고 달라지는 상황을 말함

8. Thread Synchronization

1) Thread Synchronization(스레드 동기화)

  • 스레드는 멀티스레드 프로그램에서 상호 작동한다.
    • 공유 리소스에 대한 액세스
  • 스레드가 공유 리소스에 동시에 액세스하면 어떻게 될까?
    • 부정확한 결과로 이어짐
    • race condition이라고 불림
  • 스레드 동기화 : 정확성을 위해 공유 리소스 또는 해당 실행을 사용하는 스레드를 조정하는 방법

2) 스레드 동기화 목표

  • cooperating(협력) 동기화가 올바르게 작동하는지 확인한다.
  • 5장, 6장에서 더 배