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

Post on 14-Jul-2015

1.524 Views

Category:

Technology

10 Downloads

Preview:

Click to see full reader

TRANSCRIPT

11장 윈도우 스레드 풀

12장 파이버

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

김홍준(twitter.com/jun0683)

11장 윈도우 스레드 풀

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

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

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

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

12장 파이버

11장 윈도우 스레드 풀

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

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

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

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

12장 파이버

윈도우 스레드 풀이란?

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

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

어렵지 않아요~

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

VOID NTAPI SimpleCallback(

PTP_CALLBACK_INSTANCE

pInstance,

PVOID pvContext

);

사용자 정의

BOOL TrySubmitThreadpoolCallback(

PTP_SIMPLE_CALLBACK pfnCallback,

PVOID pvContext,

PTP_CALLBACK_ENVIRON pcbe

);

사용자 정의 함수

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

TrySubmitThreadpoolCallback()

이분을 쓰면 CreateThread X

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

=>알아서 재사용

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

명시적 작업 항목 제어

TrySubmitThreadpoolCallback 실패시

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

명시적 작업 항목 제어

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

않는다면?

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

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

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

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

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. 큐에 넣기

명시적 작업 항목 제어

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

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

VOID WaitForThreadpoolWorkCallbacks(

PTP_WORK pWork,

BOOL bCancelPendingCallbacks);

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

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

명시적 작업 항목 제어

VOID CloseThreadpoolWork(PTP_WORK pwk);

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

작업 항목 제거

데모

11장 윈도우 스레드 풀

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

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

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

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

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);

시간 간격을 두고 함수 호출

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

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

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

줄이는 것이 중요

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

을 이용해서 시간 조작

시간 간격을 두고 함수 호출

pftDueTime 을 NULL로 넣으면

타이머 호출 X

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

타이머 정지 가능

VOID SetThreadpoolTimer(

PTP_TIMER pTimer,

PFILETIME pftDueTime,

DWORD msPeriod,

DWORD msWindowLength);

시간 간격을 두고 함수 호출

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

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

VOID WaitForThreadpoolTimerCallbacks(

PTP_WORK pWork,

BOOL bCancelPendingCallbacks);

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

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

11장 윈도우 스레드 풀

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

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

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

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

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);

시그널 대기 함수 원형

시그널 대기 함수 생성

스레드 풀에 등록

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

핸들 오브젝트를 사용

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

VOID SetThreadpoolWait(

PTP_WAIT pWaitItem,

HANDLE hObject,

PFILETIME pftTimeout);

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

내부적으로 스레드 풀은

WaitForMultipleObjects을 이용하기 때문

64개만 대기 가능

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

사용이 안되므로 DuplicateHandle을 이용

복사된 핸들을 각각 등록

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

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

영원히 시그널 상태

SetThreadpoolWait 호출할때 다른 오브젝트

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

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

콜백 함수 내에서 WaitForThreadpoolWork

호출 하면 데드락

SetThreadpoolWait 매개 변수로 전달한

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

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

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

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

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

있음을 보장을 못함!

11장 윈도우 스레드 풀

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

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

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

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

12장 파이버

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

뙇!

10장에 대략적으로 다룸

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

하면 됨

비동기 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 오브젝트 생성파일/장치 핸들값을 넣어줌

비동기 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 오브젝트 닫기

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

VOID WaitForThreadpoolIoCallbacks(

PTP_IO pio,

BOOL bCancelPendingCallbacks);

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

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

완료 통지도 발생 X

+@ 콜백 종료 동작

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

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

LeaveCriticalSectionWhenCallbackReturns

ReleaseMutexWhenCallbackReturns

ReleaseSemaphoreWhenCallbackReturns

SetEventWhenCallbackReturns

FreeLibraryWhenCallbackReturns

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

스레드 풀에서 동작하는

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

OR

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

스레드 풀 커스터마이징

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개를 가짐

11장 윈도우 스레드 풀

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

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

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

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

12장 파이버

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

코루틴은 마치 예전 OS의

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

비슷하게 동작

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

명령을 줘야 스위칭

파이버

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

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

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

스케줄링을 직접 해야 함

파이버 함수 사용

PVOID ConvertThreadToFiberEx(

PVOID pvParam,

DWORD dwFlags);

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

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

플래그에 FIBER_FLAG_FLOAT_SWITCH를 넣어줌

ConvertThreadToFiber

파이버 함수 사용

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

PVOID CreateFiberEx(

SIZE_T dwStackCommitSize,

SIZE_T dwStackReserveSize,

DWORD dwFlags,

PFIBER_START_ROUTINE pStartAddress,

PVOID pvParam);

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

파이버 함수 사용

VOID SwitchToFiber(PVOID pvFiberExecutionContext);

바이퍼 간 스위칭

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

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

데모

끝!

top related