실행중인 프로그램
구성
메모리 (코드, 데이터, 스택)
파일
Signal
IPC
accounting...
CPU
스케줄링 정보
자원 소유권 : 프로세스가 가짐
수행 / 스케줄링 : 보통 쓰레드 단위로 (운영체제에 따라 상이)
<프로세스 이미지>
현대 운영체제에서는 프로세스를 태스크, 쓰레드 두 객체로 분리한다.
태스크 (=프로세스)
: 자원 저장소 (Resource Container)
쓰레드
: 제어 흐름 (=경량 프로세스)
실행 정보, 레지스터 문맥
문맥 교환이 쓰레드 교환일 수 있다. 프로세스 교환보다 훨씬 비용이 적다.
(다른 프로세스 안에 쓰레드가 있을 땐 프로세스 교환일 수 있다. )
1) 단일 프로세스, 단일 쓰레드
2) 단일 프로세스, 다수의 쓰레드: 병렬 프로그래밍
3) 다수의 프로세스, 프로세스 당 하나의 쓰레드: 멀티 프로세서의 경우에 다중 쓰레드와 같은 효과
4) 다수의 프로세스, 프로세스 당 다수의 쓰레드: 병렬 수행 (최고로 좋다!)
MS-DOS
UNIX
최신 버전의 UNIX
최신 버전의 Window
최신 버전의 Solaris
태스크 관련 사항
프로세스 이미지를 유지하는 가상 주소 공간
처리기, (IPC를 위한) 다른 프로세스 파일, I/O 자원들에 대한 접근 제어, 문맥
쓰레드 관련 사항
실행 상태( 수행, 준비, 블록 )
수행 중이 아닐 때 저장되는 쓰레드 문맥
쓰레드 문맥: 쓰레드를 보는 관점 중 하나로, 쓰레드를 한 프로세스 안에서 동작하는 프로그램 카운터로 간주하는 것이다.
실행 스택
지역 변수 저장을 위해 각 쓰레드가 사용하는 어떤 정적 저장소 (Thread Local Storage)
C에서 static (공유하지 않는 global)
프로세스에 속해 있는 쓰레드들 끼리는 global 변수를 공유한다.
자신이 속한 프로세스의 메모리 및 자원들에 대한 접근 공유 (global)
한 프로세스 내의 모든 쓰레드들은 그 프로세스의 자원들을 공유한다.
💨 쓰레드들은 같은 주소 공간에 존재하며, 동일한 데이터를 접근한다.
프로세스에 비해 새로운 쓰레드 생성 시간 / 비용이 절약 된다.
프로세스 종료 시간보다 쓰레드 종료시간이 짧다.
한 프로세스 내의 두 쓰레드들 사이의 교환 / 교체 시간이 짧다.
동일 프로세스 내의 쓰레드들은 메모리 및 파일을 공유하기 때문에, 이들 쓰레드들은 커널의 개입 없이 서로 통신이 가능하다.
모듈화
한 프로그램의 구조를 단순화
다중 처리기 (Multiprocessor)의 효율적 사용
빠른 IPC(메세지 전송 x, 공유 메모리 사용 가능)
병행 서버(Listenings Thread and Responding Threads)
서버 소프트웨어 (멀티 쓰레드)
Listenings Thread (사용자 요청 처리)
Responding Threads (분배)
전면(foreground)과 후면(background) 작업
: 응용의 속도 향상
예
: 하나의 쓰레드(전면)가 메뉴를 나타내고 사용자 입력을 읽는 중에, 다른 쓰레드(후면)는 사용자 명령을 수행하고 스프레드 시트를 갱신할 수 있다.
비동기 처리(asynchronous) 처리
: 다른 작업의 기능
프로그램의 비동기적 요소들을 쓰레드를 통해 구형할 수 있다.
빠른 수행
: 멀티 쓰레드 프로세스는 어떤 데이터 묶음을 계산하면서 동시에 어떤 장치에서 다음 데이터 묶음을 읽어 들일 수 있다.
한 프로세스 내의 여러 쓰레드들은 실제적으로 동시에 수행될 수 있다.
한 쓰레드가 특정 데이터 묶음을 읽기 위해 입출력 작업 오나료를 기다리면서 블록될지라도, 또 다른 쓰레드가 수행될 수 있다.
모듈 프로그램 구조
: 쓰레드를 사용하여 설계하고 구현하는 것이 편리하다.
💨 단일 처리기에서는 멀티 프로그래밍으로 인해, 여러 프로세스 내의 여러 쓰레드들이 번갈아 수행될 수 있다.
쓰레드를 지원하는 운영체제 : 스케줄링과 디스패칭이 쓰레드를 기초로 이루어진다.
(수행에 관련된 대부분의 상태 정보가 쓰레드 수준의 자료구조에 의해 이루어진다.)
쓰레드 상태
수행, 준비, 블록 (+보류)
생성: 프로세스 생성 시 쓰레드 함께 생성
쓰레드는 다른 쓰레드를 생성할 수 있다. (같은 프로세스 내에)
새로 생성된 쓰레드를 위해서 명령 포인터와 인자들을 제공한다.
(새로운 쓰레드는 자신의 레지스터 문맥과 스택 공간을 가지며, 준비큐에 위치)
블록: 쓰레드가 어떤 사건을 기다려야 할 때
비블록: 기다리던 사건 발생 시
기본적인 쓰레드 연산
💨 논점: 한 쓰레드의 블록이 전체 프로세스를 블록 시키는지 여부
(쓰레드의 장점과 유연성을 사라지게 할 수 있기 때문)
쓰레드 동기화 (Synchronization)
한 프로세스 내의 모든 쓰레드들은 동일 주소 공간 및 자원들을 공유한다.
공유자원: 지역 변수, 파일, 힙(heap) 영역
공유자원에 대해 동시 접근 시 (특히, 갱신) 일관성 유지 기법 필요
<사용자 수준 쓰레드(User-level thread, ULT) 와 커널 수준 쓰레드(Kernel-level thread, KLT)>
(a) 커널은 쓰레드의 사정을 알 수 없다.
(b) 커널이 쓰레드의 존재를 안다.
(c) 쓰레드들 간 문맥교환은 빠르나, 교행 수행이 효율적이지 않을 수 있다.
사용자 수준 쓰레드 (ULT)
응용이 모든 쓰레드 관리를 책임짐
커널은 쓰레들의 존재를 모른다.
이러한 접근 방법의 예: cthread, pthread
커널 수준 쓰레드 (KLT)
커널이 프로세스 및 쓰레드에 대한 문맥 정보를 관리
커널은 여러 처리기에 같은 프로세스 내의 여러 쓰레드를 동시에 스케줄 할 수 있다.
한 프로세스의 쓰레드가 블로되면, 커널은 같은 프로세스에서 다른 쓰레드를 스케줄 할 수 있다.
커널 루틴 자체가 멀티 쓰레드로 구성될 수 있다.
쓰레드에 대한 스케줄링이 커널 수준에서 수행 된다.
이러한 접근 방법의 예: windows
결합된 접근 방법 (Combined approach)
사용자 수준 쓰레드의 장점
쓰레드 교환 / 교체 시에 커널 모드 권한이 불필요
(두 번의 모드 전이 오버헤드 절약 가능)
특정 응용에 적합한 스케줄링 적용 가능
모든 OS에서 수행 가능
(쓰레드 라이브러리는 모든 응용에 공유하는 응용 수준 함수들의 집합이기 때문)
사용자 수준 쓰레드의 단점
한 쓰레드가 블록상태를 유발하는 시스템 호출을 수행할 경우, 자신
뿐만아니라 그 프로세스 내의 모든 다른 쓰레드들도 블록 된다.
(커널은 쓰레드의 존재를 모르기 때문)
다중처리기의 장점을 살리지 못한다
(커널은 한 번에 하나의 처리기에 하나의 프로세스만 할당)
커널 루틴 자체는 다중 쓰레딩 될 수 없다.
💨 1:M과 M:N은 현실 구현이 힘들다.
(1 - f)
f
f
의 실행 시간예
순차적으로 실행 코드 : 10%
f = 90 %
, N = 8
1 / (0.1 + (0.9 / 8)) = 4.7
→ 순차 수행률이 높아질수록 속도 향상이 둔화된다.
순차 수행률이 높아질수록 속도 향상이 둔화
처리기 갯수가 많아질수록 오버헤드 증가
멀티 쓰레드화된 네이티브 응용 (원래부터 멀티 쓰레드를 고려해서 설계)
멀티 프로세스 응용
자바 응용
멀티 인스턴스 응용
<응용 예제: Valve 게임 소프트웨어>