11장 윈도우 스레드 풀 + 12장 파이버

40
11장 윈도우 스레드 풀 12장 파이버 아꿈사(http://cafe.naver.com/architect1) 김홍준(twitter.com/jun0683)

Upload: -

Post on 14-Jul-2015

1.524 views

Category:

Technology


10 download

TRANSCRIPT

Page 1: 11장 윈도우 스레드 풀 + 12장 파이버

11장 윈도우 스레드 풀

12장 파이버

아꿈사(http://cafe.naver.com/architect1)

김홍준(twitter.com/jun0683)

Page 2: 11장 윈도우 스레드 풀 + 12장 파이버

11장 윈도우 스레드 풀

- 비동기 함수 호출(스레드)

- 시간 간격을 두고 함수 호출(타이머)

- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)

- 비동기 I/O 요청 완료되면 함수 호출(IOCP)

12장 파이버

Page 3: 11장 윈도우 스레드 풀 + 12장 파이버

11장 윈도우 스레드 풀

- 비동기 함수 호출(스레드)

- 시간 간격을 두고 함수 호출(타이머)

- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)

- 비동기 I/O 요청 완료되면 함수 호출(IOCP)

12장 파이버

Page 4: 11장 윈도우 스레드 풀 + 12장 파이버

윈도우 스레드 풀이란?

스레드 생성, 파괴, 관리작업을 좀 더 쉽게구

현 할 수 있도록 제공(책에서는 비스타 이상)

어렵지 않아요~

Page 5: 11장 윈도우 스레드 풀 + 12장 파이버

비동기 함수 호출(스레드)를 뙇!

VOID NTAPI SimpleCallback(

PTP_CALLBACK_INSTANCE

pInstance,

PVOID pvContext

);

사용자 정의

BOOL TrySubmitThreadpoolCallback(

PTP_SIMPLE_CALLBACK pfnCallback,

PVOID pvContext,

PTP_CALLBACK_ENVIRON pcbe

);

사용자 정의 함수

작업 요청(비동기적으로)

Page 6: 11장 윈도우 스레드 풀 + 12장 파이버

TrySubmitThreadpoolCallback()

이분을 쓰면 CreateThread X

스레드 일일이 생성 파괴 관리 X

=>알아서 재사용

=>알아서 스레드 개수 증가 감소

Page 7: 11장 윈도우 스레드 풀 + 12장 파이버

명시적 작업 항목 제어

TrySubmitThreadpoolCallback 실패시

(메모리 부족,메모리 할당제한등..)

Page 8: 11장 윈도우 스레드 풀 + 12장 파이버

명시적 작업 항목 제어

스레드 풀에서 작업 항목이 들어 가지

않는다면?

내부적으로 작업 항목을 새로 생성 한 후

작업 항목을 스레드 풀 큐에 넣음

=> 작업 항목 큐를 이용하자!

Page 9: 11장 윈도우 스레드 풀 + 12장 파이버

명시적으로 작업 항목을 제어 하려면

1.작업 항목 만들고

2.큐에 넣고

0.작업 할 콜백함수 구현

1.콜백 함수 원형 넣고

작업 항목 만듦

PTP_WORK CreateThreadpoolWork(

PTP_WORK_CALLBACK

pfnWorkHandler,

PVOID pvContext,

PTP_CALLBACK_ENVIRON pcbe);

VOID CALLBACK WorkCallback(

PTP_CALLBACK_INSTANCE Instance,

PVOID Context,

PTP_WORK Work);

VOID SubmitThreadpoolWork(PTP_WORK

pWork);2. 큐에 넣기

Page 10: 11장 윈도우 스레드 풀 + 12장 파이버

명시적 작업 항목 제어

삽입한 장업항목을 취소하거나

처리될때까지 특정 스레드를 대기상태

VOID WaitForThreadpoolWorkCallbacks(

PTP_WORK pWork,

BOOL bCancelPendingCallbacks);

True면 취소,처리중이라면 취소하지 않고 처리될때 까지 대기

False면 완전히 처리 될떄까지 대기

Page 11: 11장 윈도우 스레드 풀 + 12장 파이버

명시적 작업 항목 제어

VOID CloseThreadpoolWork(PTP_WORK pwk);

작업 항목이 더 이상 필요 없다면

작업 항목 제거

Page 12: 11장 윈도우 스레드 풀 + 12장 파이버

데모

Page 13: 11장 윈도우 스레드 풀 + 12장 파이버

11장 윈도우 스레드 풀

- 비동기 함수 호출(스레드)

- 시간 간격을 두고 함수 호출(타이머)

- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)

- 비동기 I/O 요청 완료되면 함수 호출(IOCP)

12장 파이버

Page 14: 11장 윈도우 스레드 풀 + 12장 파이버

시간 간격을 두고 함수 호출(타이머)를 뙇!

VOID CALLBACK TimeoutCallback(

PTP_CALLBACK_INSTANCE pInstance,

PVOID pvContext,

PTP_TIMER pTimer);

PTP_TIMER CreateThreadpoolTimer(

PTP_TIMER_CALLBACK

pfnTimerCallback,

PVOID pvContext,

PTP_CALLBACK_ENVIRON pcbe)

타이머 함수 원형

타이머 생성

타이머 스레드 풀에 등록

VOID SetThreadpoolTimer(

PTP_TIMER pTimer,

PFILETIME pftDueTime,

DWORD msPeriod,

DWORD msWindowLength);

Page 15: 11장 윈도우 스레드 풀 + 12장 파이버

시간 간격을 두고 함수 호출

콜백 함수가 정확한 시간에 호출

해주는 것 보다 스레드를 깨웠다가

다시 대기 상태로 만드는 비용을

줄이는 것이 중요

타이머를 한번 만들고 SetThreadpoolTimer()

을 이용해서 시간 조작

Page 16: 11장 윈도우 스레드 풀 + 12장 파이버

시간 간격을 두고 함수 호출

pftDueTime 을 NULL로 넣으면

타이머 호출 X

타이머 오브젝트를 파괴 하지 않고

타이머 정지 가능

VOID SetThreadpoolTimer(

PTP_TIMER pTimer,

PFILETIME pftDueTime,

DWORD msPeriod,

DWORD msWindowLength);

Page 17: 11장 윈도우 스레드 풀 + 12장 파이버

시간 간격을 두고 함수 호출

삽입한 타이머을 취소하거나

처리될때까지 특정 스레드를 대기상태

VOID WaitForThreadpoolTimerCallbacks(

PTP_WORK pWork,

BOOL bCancelPendingCallbacks);

True면 취소,처리중이라면 취소하지 않고 처리될때 까지 대기

False면 완전히 처리 될떄까지 대기

Page 18: 11장 윈도우 스레드 풀 + 12장 파이버

11장 윈도우 스레드 풀

- 비동기 함수 호출(스레드)

- 시간 간격을 두고 함수 호출(타이머)

- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)

- 비동기 I/O 요청 완료되면 함수 호출(IOCP)

12장 파이버

Page 19: 11장 윈도우 스레드 풀 + 12장 파이버

커널 오브젝트가 시그널 되면 함수 호출

(이벤트)를 뙇!

VOID CALLBACK WaitCallback(

PTP_CALLBACK_INSTANCE pInstance,

PVOID Context,

PTP_WAIT Wait,

TP_WAIT_RESULT WaitResult);

PTP_WAIT CreateThreadpoolWait(

PTP_WAIT_CALLBACK pfnWaitCallback,

PVOID pvContext,

PTP_CALLBACK_ENVIRON pcbe);

VOID SetThreadpoolWait(

PTP_WAIT pWaitItem,

HANDLE hObject,

PFILETIME pftTimeout);

시그널 대기 함수 원형

시그널 대기 함수 생성

스레드 풀에 등록

Page 20: 11장 윈도우 스레드 풀 + 12장 파이버

커널 오브젝트가 시그널 되면 함수 호출

핸들 오브젝트를 사용

시그널 상태가 됬을 때 콜백 함수를 호출

VOID SetThreadpoolWait(

PTP_WAIT pWaitItem,

HANDLE hObject,

PFILETIME pftTimeout);

Page 21: 11장 윈도우 스레드 풀 + 12장 파이버

커널 오브젝트가 시그널 되면 함수 호출

내부적으로 스레드 풀은

WaitForMultipleObjects을 이용하기 때문

64개만 대기 가능

동일한 커널 오브젝트를 동시에 여러 번

사용이 안되므로 DuplicateHandle을 이용

복사된 핸들을 각각 등록

Page 22: 11장 윈도우 스레드 풀 + 12장 파이버

커널 오브젝트가 시그널 되면 함수 호출

프로세스 커널 오브젝트는 한번 시그널이면

영원히 시그널 상태

SetThreadpoolWait 호출할때 다른 오브젝트

또는 Null값을 전달해서 해당 핸들을 제거

Page 23: 11장 윈도우 스레드 풀 + 12장 파이버

커널 오브젝트가 시그널 되면 함수 호출

콜백 함수 내에서 WaitForThreadpoolWork

호출 하면 데드락

SetThreadpoolWait 매개 변수로 전달한

커널 오브젝트는 삭제 하면 안됨!

Page 24: 11장 윈도우 스레드 풀 + 12장 파이버

커널 오브젝트가 시그널 되면 함수 호출

대기중인 커널 오브젝트에 대해

PulseEvent 같은 시그널 함수 호출도 안됨!

해당 이벤트가 호출한 시점에 대기 하고

있음을 보장을 못함!

Page 25: 11장 윈도우 스레드 풀 + 12장 파이버

11장 윈도우 스레드 풀

- 비동기 함수 호출(스레드)

- 시간 간격을 두고 함수 호출(타이머)

- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)

- 비동기 I/O 요청 완료되면 함수 호출(IOCP)

12장 파이버

Page 26: 11장 윈도우 스레드 풀 + 12장 파이버

비동기 I/O 요청 완료되면 함수 호출(IOCP)

뙇!

10장에 대략적으로 다룸

어떤 함수를 호출 할지를 지정하기만

하면 됨

Page 27: 11장 윈도우 스레드 풀 + 12장 파이버

비동기 I/O 요청 완료되면 함수 호출(IOCP)

VOID CALLBACK

OverlappedCompletionRoutine(

PTP_CALLBACK_INSTANCE pInstance,

PVOID pvContext,

PVOID pOverlapped,

ULONG IoResult,

ULONG_PTR NumberOfBytesTransferred,

PTP_IO pIo);

I/O 작업 완료시 호출되는 함수 원형

PTP_IO CreateThreadpoolIo(

HANDLE hDevice,

PTP_WIN32_IO_CALLBACK

pfnIoCallback,

PVOID pvContext,

PTP_CALLBACK_ENVIRON pcbe);

스레드 풀 I/O 오브젝트 생성파일/장치 핸들값을 넣어줌

Page 28: 11장 윈도우 스레드 풀 + 12장 파이버

비동기 I/O 요청 완료되면 함수 호출(IOCP)

VOID StartThreadpoolIo(PTP_IO pio);

VOID CancelThreadpoolIo(PTP_IO pio);

VOID CloseThreadpoolIo(PTP_IO pio);

단,풀에 넣고 나서 READ/WRITE 할것

I/O 오브젝트와 스레드 풀 연동

I/O 작업이 실패 하면 반드시 호출

사용을 마치려면 …

I/O 오브젝트 닫기

Page 29: 11장 윈도우 스레드 풀 + 12장 파이버

비동기 I/O 요청 완료되면 함수 호출(IOCP)

VOID WaitForThreadpoolIoCallbacks(

PTP_IO pio,

BOOL bCancelPendingCallbacks);

I/O 작업이 완료 될때까지 다른 스레드가 대기 시킴

True 면 시작 되지 않은 모든 요청을 취소

완료 통지도 발생 X

Page 30: 11장 윈도우 스레드 풀 + 12장 파이버

+@ 콜백 종료 동작

콜백 함수가 종료 될때 쓰면 유용

스레드 풀이 종료시 자동적으로 호출

LeaveCriticalSectionWhenCallbackReturns

ReleaseMutexWhenCallbackReturns

ReleaseSemaphoreWhenCallbackReturns

SetEventWhenCallbackReturns

FreeLibraryWhenCallbackReturns

Page 31: 11장 윈도우 스레드 풀 + 12장 파이버

스레드 풀 커스터마이징 뙇!

스레드 풀에서 동작하는

스레드의 최소 최대 개수를 설정

OR

스레드 풀을 각각 독립적으로 생성,파괴

Page 32: 11장 윈도우 스레드 풀 + 12장 파이버

스레드 풀 커스터마이징

PTP_POOL CreateThreadpool(PVOID reserved);

BOOL SetThreadpoolThreadMinimum(PTP_POOL pThreadPool,

DWORD cthrdMin);

BOOL SetThreadpoolThreadMaximum(PTP_POOL pThreadPool,

DWORD cthrdMost);

VOID CloseThreadpool(PTP_POOL pThreadPool);

기본 스레드 풀은 최소 스레드 1개 최대 500개를 가짐

Page 33: 11장 윈도우 스레드 풀 + 12장 파이버

11장 윈도우 스레드 풀

- 비동기 함수 호출(스레드)

- 시간 간격을 두고 함수 호출(타이머)

- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)

- 비동기 I/O 요청 완료되면 함수 호출(IOCP)

12장 파이버

Page 34: 11장 윈도우 스레드 풀 + 12장 파이버

파이버라 쓰고 코루틴이라 읽는다…

코루틴은 마치 예전 OS의

비선점형(non-preemptive) 쓰레드와

비슷하게 동작

프로그래머가 강제로 컨텍스트 스위칭

명령을 줘야 스위칭

Page 35: 11장 윈도우 스레드 풀 + 12장 파이버

파이버

기존 UNIX 프로그램을 포팅하기 위해서…

윈도우는 그냥 스레드 쓰면 됨….

유저모드에서 돌아서 가볍다

스케줄링을 직접 해야 함

Page 36: 11장 윈도우 스레드 풀 + 12장 파이버

파이버 함수 사용

PVOID ConvertThreadToFiberEx(

PVOID pvParam,

DWORD dwFlags);

기존 스레드를 파이버로 변경

파이버 단위에는 부동소수점 상태 정보를 포함하지 않으므로

플래그에 FIBER_FLAG_FLOAT_SWITCH를 넣어줌

ConvertThreadToFiber

Page 37: 11장 윈도우 스레드 풀 + 12장 파이버

파이버 함수 사용

새로운 파이버를 생성리턴 받은 컨텍스트 정보를 저장 해두고 사용

PVOID CreateFiberEx(

SIZE_T dwStackCommitSize,

SIZE_T dwStackReserveSize,

DWORD dwFlags,

PFIBER_START_ROUTINE pStartAddress,

PVOID pvParam);

VOID WINAPI FiberFunc(PVOID pvParam); 파이버 함수 원형

Page 38: 11장 윈도우 스레드 풀 + 12장 파이버

파이버 함수 사용

VOID SwitchToFiber(PVOID pvFiberExecutionContext);

바이퍼 간 스위칭

컨텍스트 정보를 이용해서 스위칭을 함

PVOID GetCurrentFiber(); 현재 컨텍스트 주소를 얻어옴

Page 39: 11장 윈도우 스레드 풀 + 12장 파이버

데모

Page 40: 11장 윈도우 스레드 풀 + 12장 파이버

끝!