본문 바로가기
👨‍💻Computer Science/운영체제[OS]

[운영체제] 4장 Multithreaded Programming

by 코푸는 개발자 2021. 6. 29.
728x90

Process

Multithreaded Programming 대표적인 예) 메신저프로그램 코딩

어떠한 글자를 키보드를 통해서 입력하는 클라이언트 프로그램을 만들 때

클라이언트 프로그램에서 문자를 입력하면 그 것을 수신하고 다른 사용자들에게 뿌려주는 서버를 프로그램 해야 함

다른 프로그램 클라이언트에게 통신을 날릴 때 키보드에서 입력하는 경우와 데이터를 받고 동시에 뿌려주는 것 두 가지를 해야 함

키보드 입력받는 함수 -> cin, scanf 사용 더불어 클라이언트만 이야기할 때 네트워크를 통해서 글자가 상대방이 입력한 것을 가져와서 뿌려주는 함수 또한 구현을 해야 함

이렇게 되면 키보드 입력을 통해 기다리는 함수와 네트워크를 통해서 데이터가 도착을 했을 때 뿌려주는 함수 2가지가 동시에 기다리게 됨.

cin, scanf를 통해서 입력을 기다리고 있는 상태에서 네트워크를 통해서 들어온 데이터를 뿌려주는 함수가 동시에 작동할 수 있나? NO...(line별로 실행이 되기 때문)

->따라서 fork로 프로세스를 두 개를 만들어서 동작을 시키면 가능함(실행하는 작업이 2개가 되어야함)

그래서 여러 가지를 동시에 수행하는 프로그램에서는 여러 가지 프로세스를 만들어서 동시에 수행을 시켜야함

-> 이러한 것을 Multi-Process라고 함(but 프로세스가 너무 무거워진다. -> 오버헤드가 크다.)

프로세스는 프로세스들 간에 완벽하게 독립적인 공간(메모리 스페이스)를 가진다. -> 각자의 스텝과 데이터 명령을 가지고 서로 보호되고 있는 구조이다.

프로세스는 시작할 때 운영체제에서 PCB와 메모리 공간을 할당받게 되고 초기화과정을 거친다.

다른 프로세스의 영역을 확인할 수 없기 때문에 통신을 위해 IPC가 필요하다. -> 이러한 프로세스가 오버헤드가 크게 되는데 이를 해결하기 위해 나온 개념이 Thread이다.

 

Thread Concept: Key Idea

프로세스는 별도의 공간과 자원을 필요로 하게 되는데 이 프로세스의 실행상태를 Thread 또는 경량프로세스(LWP)라고 부름.

 

Thread 실이라는 뜻을 가짐

그림에서 실처럼 생긴 것이 프로그램이 실행되는 흐름 또는 프로세스 실행의 패스라고 함

프로세스 하나에 여러 Thread를 두려고 함.

 

Thread의 구성

-program counter

-register set

-stack space

Threadcode section, data section, OS resources를 공유를 받음

 

Thread와 Process의 차이

-Thread는 하나의 프로세스에 묶여있음.

-프로세스는 여러 개의 Thread를 가질 수 있음

-프로세스에서 동일한 주소 공간을 사용하고 있기 때문에 Thread 간 데이터를 공유하는데 오버헤드가 줄어들게 됨

-Thread가 스케줄링에 하나의 단위가 되면서 프로세스가 정적인 개체가 되어버리고 Thread가 동적인 개체가 됨

 

프로세스 주소 공간

4가지 영역

-stack

-heap

-static data

-code

 

Threadstack영역에서 메모리를 따로 할당을 받고 heap과 데이터영역은 하나의 프로세스 안에서 동일하게 Program counter는 각자 하나씩 할당을 받게 됨.

 

Single-Thread의 경우에는 프로세스의 code level, data, files 이러한 영역을 공유를 받고 하나의 registerstack공간을 할당받는 형태로 구현이 됨

Multithreadcode level, data, files은 동일한 영역을 사용하지만 registerstack은 따로 할당받아서 여러 개의 Thread가 동시에 수행이 될 수 있는 메모리 영역을 할당받음

 

중요핵심

프로세스와 Thread의 차이점을 명확히 알 것

프로세스는 서로 완벽히 독립된 영역을 가지고 하나하나가 각자의 스텍 영역과 데이터 영역을 할당받고 보호를 받게 됨.

그 과정에서 프로세스를 생성할 때 PCB와 메모리공간을 할당받고 초기화과정이 필요하며 다른 프로세스의 영역을 확인할 수 없기 때문에 프로세스 간에 통신하기 위한 메시지 패싱 기법, 쉐어드메모리기법 같은 것들이 필요함

Thread는 무엇이냐?

>스텍을 따로따로 할당을 받지만 코드영역과 데이터 영역은 하나로 공유 받음.

따라서 매번 프로세스가 생성될 때 PCB 및 메모리공간을 할당받고 초기화해주는 과정과 데이터 영역에 속하는 변수를 통해서 쉽고 빠르게 Thread간의 데이터를 통신할 수 있어서 프로세스를 여러 개를 만드는 것보다 Thread를 여러 개 만드는 것이 오버헤드를 줄여주는 방법이다.

예시) 프로세스 은행지점, Thread 각각의 고객창구(소통이 쉬움)

 

그럼 왜 프로세스를 만들어서 사용을 하나?

>Thread에도 단점이 존재함 어떠한 Thread 하나가 잘못된 연산이나 버그 등으로 비정상 종료를 하게 된다면 같은 프로세스에 소속된 다른 Thread까지 모두 강제 종료되는 사태가 발생할 수 있다. But 프로세스는 한 프로세스가 비정상적으로 종료된다고 해도 다른 프로세스에는 영향이 거의 없다 -> 따라서 어느 정도 프로세스로 나누고 Thread작업을 처리하는 것이 이상적임(은행 한 지점이 불이난다해도 다른 은행은 업무가 가능함)

 

Concurrent Servers: Processes

웹서버 소스코드 -> 프로세스구현과 Thread구현을 이야기하는 예제

소켓이 연결이 완료가 되면 프로세스 하나를 만들고 클라이언트 요청을 처리함

이 구조를 보면 클라이언트의 요청을 여러 개를 동시에 대응할 수 없는 구조로 되어 있음을 알 수 있다 -> 따라서 클라이언트 요청 여러 개를 동시에 대응할 수 있도록 만들기 위해서는

Thread를 통해서 구현하면 가능해짐.

 

Concurrent Servers: Threads

Thread using

웹서버에서 소켓을 연결하고 소켓에서 요청이 들어오는지 확인하는 Thread 하나와 어떠한 요청이 들어오면 그 요청에 반응을 하는 Thread(handle_request)를 구성하면 다양한 요청이 들어와도 여러 개의 Thread가 동시에 반응하는 서버를 만들 수 있음

-> Thread는 서버 클라이언트 프로그램에서는 필수로 사용되는 프로그래밍 스킬이다

때에 따라서는 데이터를 여러 개 동시에 불러 온다던가 하는 다양한 프로그램에 따라서 필요한 프로그래밍 스킬임

 

Thread장점

-반응성이 좋음

-데이터 공유성이 좋음

-경제적임

-MP(Multithread Program) Architecture에 활용

 

User Threads

User ThreadKernel Thread에 대한 이야기

-Thread를 지원하는 주체에 따라 구분해 놓은 것임(Thread를 누가 생성하고 어떤 역할을 하는 가로 구분을 함)

User Thread user영역에서 동작을 하는 Thread로 일반적으로 User level 라이브러리를 통해서 구현이 된 형태(kernel은 스케줄링과 관련된 관리를 해주고 같은 프로세스 내에 동일한 메모리를 메모리 영역에서 생성되고 관리되는 것으로 속도가 빠르다는 장점이 있음)

-> 그렇지만 운영체제가 Thread에게 직접적으로 Interrupt를 전달할 수 없고 user mode에서 실행이 되기 때문에 시스템 콜이 발생했을 때 대응이 좋지 않다는 단점이 있음

종류로는 POSIX Pthreads, Mach C-threads, Solaris threads가 있음

 

Kernel thread

kernel영역에서 Thread를 생성을 하고 스케줄링 등을 관리하는 것

그래서 모든 Thread가 시스템 콜로 구현이 가능함

Kernel이 직접적으로 Thread의 스케줄링 및 Interrupt도 관리가 가능해짐(장점)

But kernel단에 수행시간이 증가하면서 오버헤드가 많이 발생한다는 단점도 있지만 이러한 처리들이 편리하다는 장점으로 최근에는 kernel 방식의 Thread를 많이 사용함

 

User-level Threads vs. Kernel-level Threads

사용자레벨, 커널레벨 Thread의 장단점

앞서 간단히 설명함 읽어볼 것

 

Multithreading Models(3가지)

>Many-to-One

>One-to-One

>Many-to-Many

사실 큰 의미가 있는 것은 아님

 

Many-to-One

Kernel thread(운영체제수행) x 1 + user thread 여러 개

 

One-to-One

여러 개의 kernel thread에서 각각의 user thread를 만들어주는 것

하나의 thread가 정지가 되어도 다른 thread들은 작동함

-> Multiprocess system에서 동시에 수행이 가능함

그러나 이러한 방법에서 사용하는 kernel thread도 한정된 자원이기 때문에 thread개수에 대한 고려가 필요

 

Many-to-Many

여러 개의 kernel thread와 여러 개의 user thread를 사용(kernel thread<=user thread)

스케줄링을 하면서 조절하고 다중 프로세스의 장점을 극대화시키기 위해 고안됨

 

Threading Issues

Thread 유닉스와 함께 나온 개념이 아니고 유닉스 이후 약 10년 뒤에 나온 개념임

thread라는 개념이 나오면서 다중스레드 프로그램에서 forkexec과 같은 시스템 호출에 대한 의미가 조금 달라지게 됨

ex) 한 프로세스가 동작을 할 때 Thread5개를 만들었다고 할 때 그 중에 한 threadfork를 하는 함수가 있다고 가정을 하면 그 thread하나만을 fork를 통해서 다시 생성을 해서 thread6개 되어야 하는 것인지 프로세스 전체를 복사를 해서 프로세스 2thread10개를 만들어야 하는 것인가? 이러한 문제가 발생

>이분은 사람이 만들어 내는 것이라 표준이 없음 -> os마다 상이함

그래서 일반적으로 thread에서는 fork를 하지 않도록 프로그래밍 함.

Thread cancellation -> thread가 끝나기 전에 강제 종료 시키는 작업(여기서 문제가 있을 수 있음 -> 취소하는 thread에 할당된 자원문제에 있음)

갑자기 thread를 종료하게 되면 thread의 자원 공유 및 자료구조에 대해 수정이 이루어져야하는데 이러한 방식에 비동기식 취소(thread가 즉시 취소되어야하는 thread를 강제 종료시키는 방법), 지연 취소(어떠한 thread가 주기적으로 자신이 강제종료 되어야 할지 확인한 뒤에 확인이 되면 취소를 시키는 방법)가 있음

 

운영체제에서 특정한 사항이 발생하게 되면 이를 Signal로 프로세스 및 thread에게 전달을 해줌 -> 신호가 적용될 thread에게만 전달을 해야 할지 모든 thread에게 전달을 할지 아니면 특별한 thread에게만 선택적으로 전달을 해야 할지에 대한 문제가 발생함

 

Thread pool

요청마다 새로운 thread를 생성하는 것은 새로운 프로세스를 생성하는 것보다 오버헤드가 적지만 thread를 생성하는데 소요되는 시간과 요청마다 새로운 thread를 생성해서 제공하게 된다면 언젠가는 하드웨어 자원이 고갈되기 때문에 시스템에서 동시에 실행할 수 있는 thread의 한계를 정해야하는 문제가 있음

Thread의 장점

한 프로세스에 속한 thread들은 그 프로세스의 자료를 모두 공유

그래도 어떠한 특정한 상황에서는 thread들이 자신만 접근 할 수 있는 자료를 가질 필요가 있음 이러한 자료를 Thread specific data라고 함

win32, 자바를 포함한 대부분의 thread 라이브러리들은 thread 별 데이터들을 지원해줌

-> 결론, 원래 유닉스가 만들어졌을 그 당시에는 원칙과 철학은 multithread라는 개념과 완전히 다르기 때문에 thread를 생성할 때 다음과 같은 문제들이 발생함.

 

Pthreads

Pthreads threadPOSIX 여기서 PPOSIX(유닉스 운영체제, 여러 종류의 시스템 콜의 용어 정리를 위해서 만든 표준)

thread를 생성하는 함수(시스템 콜 함수)

 

Threads Interface

OS별로 thread가 다름

Windows -> Win32 threads

IBM -> OS/2 threads

 

Pthread 함수 구성

create thread를 생성

exit thread를 종료

join 다른 thread가 종료 될 때까지 나머지 thread를 대기시킴

(23page)

Mutexes 6장에서 다시함(Pthread의 동기화를 담당)

쉐어드 데이터를 보호하기 위한 것(동기화)

 

Condition value 있는 것만 확인할 것

 

Java Threads

자바에서의 thread, runnable

운영체제는 수업위주 -> 구현 코딩은 모두해볼 것(실습은 개인적)

 

Solaris 2 Threads 운영체제 thread(many-to-many)

각 부분 용어만 알고 넘어가기

 

Solaris 2에서는 threadLWP(lightweight process)라고 말함(현재는 대부분 thread라고 함)

 

원도우 XP threads(one-to-one mapping)

 

개발을 거듭하면서 kernel thread가 제대로 돌아감

 

Java threads 도식화

JVM 위에 만들어짐

 

Threads Design Space

각각의 OSthread 구성

리눅스 many threads/process many processes

 

728x90

댓글