티스토리 뷰
👾 아래 문서 정리 ⬇️
http://www.it.uu.se/education/course/homepage/os/vt18/module-4/implementing-threads/
스레드 라이브러리는 개발자가 스레드를 생성하고 관리할 수 있도록 하는 API를 제공한다.
커널 레벨 스레드
os에서 직접 제공하고 관리하는 스레드. 1 PCB/ 1 process 그리고 1 TCB/ 1 thread. 유저 레벨에서 스레드를 생성하고 관리할 수 있도록 시스템 콜을 제공한다.
🧸 장점 => 커널이 모든 스레드에 대한 정보를 알고 있다. 따라서 스케줄러가 더 많은 수의 스레드를 가지고 있는 프로세스에게 더 많은 cpu 타임을 할당하도록 할 수 있다.
자주 block 되는 어플리케이션의 경우에는 이 방식이 더 좋다. ( 유저 레벨 스레드의 경우에는 1 스레드가 blocking operation을 하면 전체 process가 block 되기 때문.. )
🧸 단점 => 커널이 모든 스레드를 관리하고 스케줄링 해야 해서 kernel 복잡도와 오버헤드가 매우 올라감.
유저레벨 스레드보다 느리고 비효율적이다. ( 몇백배 느림 )
유저 레벨 스레드
전적으로 런타임 시스템 (user-level library)에 의해 스레드가 관리된다. 커널은 유저레벨 스레드에 대한 정보는 전혀 알지 못한다. 커널이 보기에는 그저 싱글 스레드 프로세스로 보임.
이상적으로는 거의 function call 만큼 빠르다.
🧸 장점 => 커널 레벨 스레드를 지원하지 않는 os에서도 구현될 수 있고 os 수정이 필요 없음.
유저 레벨 프로세스 address 스페이스에 작은 사이즈의 TCB를 저장하는 것으로 심플하게 표현할 수 있음.
스레드 생성, 컨텍스트 스위치, 동기화도 커널 간섭 없이 유저 스페이스에서 간단히 관리됨.
스레드 스위칭은 비용은 function call 정도로 빠르고 효율적이다.
🧸 단점 => user level 스레드 매니저(스케줄러)와 커널간에 커뮤니케이션을 잘해야 한다. os가 다음과 같은 잘못된 판단을 내릴 가능성이 높다. idle한 스레드를 가진 프로세스가 코어에 스케줄링 되도록하거나, 다른 runnable한 스레드가 있음에도 1개의 스레드가 blocking되서 전체 프로세스가 blocking되거나, 프로세스에 스레드가 몇개가 됐든 1 타임 슬라이스만 배정해 주거나, 락을 들고 있는 스레드를 스케줄링 하지 않거나 하는식의.
유저 레벨 스레드 모델
일반적으로 유저 레벨 스레드는 다음 4가지 중 한 모델을 사용해서 구현된다.
- many-to-one
- one-to-one
- many-to-many
- 2-level
모든 모델에서 유저 레벨 스레드를 커널 레벨 스레드에 매핑한다. 커널 레벨 스레드는 non-threaded 시스템(single-threaded 시스템)의 프로세스 같은 것이다. 커널 스레드는 CPU위에서 실행될 수 있도록 커널에 의해서 스케줄링 되는 실행 단위로 보면 된다.
커널 스레드 대신 virtual processor 라는 용어가 자주 쓰인다.
many-to-one
모든 유저레벨 스레드가 같은 커널 스레드위에서 동작한다. 해당 프로세스와 연관된 커널 스레드가 1개 밖에 없기 때문에 이 스레드는 한번에 1개의 유저레벨 스레드 밖에 실행시키지 못한다.
커널은 유저 레벨 스레드 정보에 대해 아무것도 알지 못한다. 이 관점으로 보면 프로세스는 가끔씩 시스템 콜을 호출하는 불투명한 블랙박스 이다.
(프로세스가 동시에 실행되는 효과는 없음. 단지 실행 단위별로 각자 콜스택을 가지고 독립적으로 실행된다 정도..?)
one-to-one
유저 레벨 스레드와 커널 스레드 1:1 매칭. 이 모델에서는 반드시 커널이 새 커널 스레드를 생성할 수 있는 시스템 콜을 제공해야 한다.
(커널 레벨 스레드가 너무 많이 생성돼야 해서 좀 비효율적..)
many-to-many
n개의 유저레벨 스레드에 m개의 커널스레드 매핑
two-level
many-to-many 모델과 비슷하지만 중요도가 높은 특정 유저레벨 스레드는 커널 스레드에 1:1 매핑되어 좀더 빠르게 cpu 스케줄링 될 수 있도록 하는 모델 (?)
scheduler activation
(=> 커널 - 유저레벨 스레드 매니저 간 communication mechanism)
many-to-many, two-level 모델에서는 프로세스에 할당될 적당한 커널 스레드 숫자를 유지하기 위해서 유저레벨 스레드 매니저와 커널이 커뮤니케이션 할 방법이 꼭 필요하다. 이 매커니즘을 scheduler activation 이라고 부른다.
커널은 어플리케이션에 커널 스레드(virtual processor) set을 제공한다. 이 set에 들어갈 커널 스레드 개수는 시스템에 있는 여러 프로세스(어플리케이션)들의 요구를 본 다음에 커널이 결정하고,
어떤 유저레벨 스레드가 어떤 커널 스레드 위에서 실행되게 만들지는 온전히 어플리케이션 단에서 관리한다.
커널이 유저레벨 스레드 매니저에 중요한 커널 이벤트 (스레드가 blocking 시스템콜을 호출했다든가, 커널이 프로세스에 추가적인 커널 스레드를 할당 했다든가 등등)를 알릴 필요가 있을 때는 upcalls를 사용한다.
* upcalls
An upcall is a mechanism that allows the kernel to execute a function in userspace, and potentially be returned information as a result.
An upcall is like a signal, except that the kernel may use it at any time, for any purpose, including in an interrupt handler.
example
(1) 커널이 3개의 유저레벨 스레드를 가지고 있는 프로세스에 1개의 커널 스레드를 할당 해줬다.
(2) 3개의 유저 레벨 스레드는 순차적으로 1개의 커널 레벨 스레드 위에서 실행된다.
(3) 스레드 실행 중에 blocking 시스템 콜이 호출 되었다.
(4) 커널을 시스템 콜 호출한 유저레벨 스레드, 그리고 그 유저 레벨 스레드를 실행한 커널 스레드를 blocking 한다.
(5) 커널은 프로세스에 새 커널 스레드를 할당해 주기로 결정한다 : scheduler activation
(6) 커널은 유저레벨 스레드 매니저에 현재 어떤 유저레벨 스레드가 blocking 되어 있는지, 그리고 새로운 커널 스레드가 사용가능하다고 알린다 : upcall
(7) 유저 레벨 스레드는 ready 상태인 다른 유저 레벨 스레드를 새 커널 스레드로 옮기고 실행을 재개한다.
(8) 유저 레벨 스레드 1개는 blocking 된채로 있는 동안
(9) 다른 유저 레벨 스레드는 새로운 커널 스레드 에서 순차적으로 계속 실행될 수 있다.
유저 레벨 스레드 스케줄링
유저레벨 스레드를 가용한 커널 스레드로 스케줄링 하는 것은 user space에 구현되어 있는 스레드 스케줄러에 의해서 수행된다.
2가지 메인 방식이 있다 : cooperative, preemptive 스레드 스케줄링
cooperative scheduling
유저 레벨 스레드가 자발적으로 커널 스레드를 스레드 매니저에게 되돌려주기 전까지는 할당 받은 커널 스레드 위에서 계속 실행된다.
cooperative 모델에서는 서로에게 스레드를 yield (양보) 한다.
explicit한 방식( 유저 레벨 스레드 라이브러리가 제공하는 yield() 함수 호출) 이나 implicit한 방식으로 (다른 스레드가 가지고 있는 lock을 요구하는 식으로 ..?)
* yield
In computer science, yield is an action that occurs during multithreading, of forcing a processor to relinquish(포기) control of the current running thread, and sending it to the end of the running queue, of the same scheduling priority
preemptive scheduling
정기적인 time 인터벌마다 인터럽트를 발생시키는 타이머가 세팅되어 있음. running 스레드가 I/O request나 타이머 인터럽트가 있을때 replace 될 수 있다. 실행시간이 주어진 타임 슬라이스를 넘길 수 없음.
타이머가 실행 flow를 중앙 dispatcher 스레드로 넘기도록 하고 이게 다음 실행 될 스레드를 선정한다.
hybrid scheduling
running 스레드가 자발적으로 yield(양보)하거나 타이머에 의해서 preempted 되는게 둘다 가능한 스케줄링 방식.
'시리즈 > Concurrency' 카테고리의 다른 글
[문서정리] 루비로 동시성 모델 소개하기 Part I (0) | 2022.01.30 |
---|---|
yield에 관한 고찰 (0) | 2022.01.23 |
메모리로 보는 프로세스와 스레드 (0) | 2022.01.23 |
IPC, 프로세스간 통신 그리고 gRPC (0) | 2021.12.05 |
서버는 여러개의 request를 어떻게 감당할까? (0) | 2021.11.29 |