Programming Server-Side Applications for Windows 2000
by Jeffrey Richter & Jason D. Clark
Chapter One: Te Discipline of Service Development
Scalability and Perfomance
- Å©¸®Æ¼Äà ¼½¼ÇÀ» ¾µ ¼ö ÀÖÀ¸¸é ±×°É ½á¶ó. (Mutex¸¦ ÀÌ¿ëÇÑ ¶óÅ·: 1000 CPU Clock. Critical SectionÀ» ÀÌ¿ëÇÑ ¶óÅ·: 100 CPU Clock)
- Scalability: ½Ì±Û ¸Ó½Å¿¡¼ ½ÇÇàµÇ´Â ¼¹öÀÇ °æ¿ì, RAMÀ» µÎ ¹è ´Ã·È´Ù°í »ý°¢ÇßÀ» ¶§, ¼º´ÉÀÌ 2¹è °³¼±µÇ¸é scalability °¡ ÁÁÀº °ÍÀÌ´Ù. ¼º´ÉÀÌ 0.2 ¹è °³¼±µÇ¸é scalability °¡ ³ª»Û °ÍÀÌ´Ù.
¼¹ö ÇÁ·Î±×·¡¹ÖÀ» ÇÒ ¶§ ¿°µÎÇØ µÎ¾î¾ß ÇÏ´Â °Í:
- user-mode ¿Í kernel-mode °£ÀÇ ÀüȯÀÌ Àß ÀϾÁö ¾Ê°Ô Â¥°í Àִ°¡?
- cacheÀÇ ¿ë·®À» ÃÊ°úÇÏ¿© ¸Þ¸ð¸®¸¦ ¾ï¼¼½ºÇÏ°í ÀÖÁö´Â ¾ÊÀº°¡?
- º¯¼ö¸¦ ÀûÀýÈ÷ Á¤·ÄÇÏ°í Àִ°¡?
- ½Ã½ºÅÛ ÀÚ¿ø ¼Ò¸ð¸¦ ÁÙÀ̱â À§Çؼ ½º·¹µåÁúÀ» ÇÏ°í Àִ°¡?
- ¾µ¸ð¾ø´Â ÄÁÅؽºÆ® ½ºÀ§ÄªÀ» ÁÙÀ̱â À§ÇØ ½ÇÇàµÇ´Â ½º·¹µåÀÇ ¼ö¸¦ ÁÙÀÌ°í Àִ°¡?
- device I/O ÀÛ¾÷ÀÌ ¿Ï·áµÇ±â¸¦ ±â´Ù¸®´Â µ¿¾È ½º·¹µå°¡ À¯¿ëÇÑ ÀÏÀ» ÇÏ°í Àִ°¡?
- Windows ÇÔ¼öÀÇ ÆÛÆ÷¸Õ½º¸¦ Çâ»óÇϱâÀ§ÇØ ANSI ¹®ÀÚ¿ ´ë½Å À¯´ÏÄڵ带 ¾²°í Àִ°¡?
- Windows °¡ Á¦°øÇÏ´Â (¸ÚÁø?) ±â´ÉÀ» Àß »ç¿ëÇÏ°í Àִ°¡?
Chapter Two: DEVICE I/O AND INTERTHREAD COMMUNICATION
- I/O completion port : ½º·¹µå¿¡¼ i/o request °¡ 󸮵DZ⸦ ±â´Ù¸®´Â µ¿¾È, ¸¶³É ±â´Ù¸®´Â °ÍÀÌ ¾Æ´Ï¶ó ¾µ¹ýÇÑ ÀÏÀ» ÇÒ ¼ö ÀÖµµ·Ï Çϱâ À§ÇØ, Áï ¸ÖƼ½º·¹µù ¼º´ÉÀ» Çâ»ó ½ÃÅ°±âÀ§ÇØ Microsoft°¡ °³¹ßÇÑ i/o ó¸® ±â¼ú.
- Windows 2000 kernel ¿¡ Æ÷ÇÔµÈ job object ´Â i/o completion port ¿Í »óÈ£ Çùµ¿Çϸç i/o °ü·Ã notificationÀ» ¼öÇàÇØ ÁØ´Ù.
- I/O completion port ´Â º»µð i/o device ¿Í °ü·ÃÇؼ¸¸ ¾²ÀÌ´Â °ÍÀ̾úÀ¸³ª, ÀÌÁ¦´Â Á» ´õ Å« ±Ô¸ð·Î ¹ßÀüÇÏ¿© interthread communication and device I/O ¸¦ À§ÇÑ ¸ÞÄ¿´ÏÁòÀÌ µÇ¾ú´Ù.
Opening and Closing Devices
- ÀÌ Ã¥¿¡¼ Á¤ÀÇÇÑ device: ÆÄÀÏ(File, Directory, Logical disk drive, Physical disk drive), Æ÷Æ®(Serial port, Parallel port), Åë½Å(Mailslot, Named Pipe, Anonymous pipe, Socket), Console
- Device Close : CloseHandle( handle ) ¶Ç´Â closesocket( sock ) (¼ÒÄÏÀÇ °æ¿ì´Â CloseHandle·Î ´ÝÀ¸¸é ¾ÈµÊ)
- ÇÚµéÀÇ Å¸ÀÔÀ» ¾Ë¾Æ³»·Á¸é : DWORD GetFileType( HANDLE hDevice )
A Detailed Look at CreateFile
- File ÀÌ¿ÜÀÇ device ¸¦ ¿¶§¿¡´Â dwCreationDistribution ÆĶó¹ÌÅÍ¿¡ OPEN_EXISTING À» ÁÖ¾î¾ß¸¸ ÇØ.
- CreateFile Cache Flags
- FILE_FLAG_NO_BUFFERING : ½Ã½ºÅÛÀÇ cache manager °¡ ÇØ´ç ÆÄÀÏÀ» ij½¬ÇÏÁö ¾Êµµ·Ï ÇÔ. (ÀÌ °æ¿ì ½Ã½ºÅÛÀº »ç¿ëÀÚ°¡ Á¦°øÇÑ ¹öÆÛ¿¡ Á÷Á¢ µ¥ÀÌÅ͸¦ ´ã±×±â ¶§¹®¿¡ offset À̳ª ¹öÆÛ»çÀÌÁî´Â ¹Ýµå½Ã sector sizeÀÇ Á¤¼ö¹è¿©¾ß ÇÑ´Ù) ´Ü, ¾öû³ª°Ô Å« »çÀÌÁîÀÇ ÆÄÀÏÀ» ¿©´Â °æ¿ì¿¡´Â ÀÌ Ç÷¢À» »ç¿ëÇÏ´Â °ÍÀÌ ÁÁ´Ù.
- FILE_FLAG_SEQUENTIAL_SCAN / FILE_FLAG_RANDOM_ACCESS : ij½¬¸Å´ÏÁ®°¡ ¾ÕÀ¸·Î ÀÐÀ» ³»¿ëÀ» ¹Ì¸® ÀÐÀ½ / ÀÐÁö ¾ÊÀ½
- FILE_FLAG_WRITE_THROUGH : read cache ´Â µ¿ÀÛ, write cache ´Â ÀÛµ¿ÇÏÁö ¾Ê°í µð½ºÅ©¿¡ ¹Ù·Î ¾¸. (Àå¾Ö¿¡ ÀÇÇÑ µ¥ÀÌÅÍ ¼Õ½ÇÀ» ÃÖ´ëÇÑ ¸·À» ¼ö ÀÖÀ½.)
- Miscellaneous CreateFile Flags
- FILE_FLAG_DELETE_ON_CLOSE : ÈǸ¢Çϱº. ¸ðµç ÇÚµéÀÌ close µÇ¸é ÆÄÀÏ »èÁ¦.
- FILE_FLAG_BACKUP_SEMANTICS : ¹é¾÷±ÇÇÑÀ»°¡Áø »ç¿ëÀÚ´Â ¿ÀÇ°¡´É. µð·ºÅ丮¸¦ ¿ÀÇ°¡´É
- FILE_FLAG_POSIX_SEMANTICS : ÆÄÀϸíÀ» ´ë¼Ò¹®ÀÚ ±¸º°ÇÔ.
- FILE_FLAG_OPEN_REPARSE_POINT : ÆÄÀÏÀÇ repase attribute ¸¦ ÀÛµ¿½ÃÅ°Áö ¾Ê°í ÆÄÀÏÀ» ¿°. (ºñÃßõ)
- FILE_FLAG_OPEN_NO_RECALL : ÆÄÀÏÀÇ data ¸¦ offline storage(TAPEµî) ¿¡ ¸¸µéµµ·Ï ÇÔ.
- FILE_FLAG_OVERLAPPED : device ¿¡ asynchronous ÇÏ°Ô Á¢±ÙÇÒ °ÍÀÓÀ» ÁöÁ¤ÇÔ. (±âº»°ªÀº synchronous ÇÔ) ÀÌ°ÍÀ̾߸»·Î, ¿ì¸®°¡ ¼¹ö ÆÛÆ÷¸Õ½º¸¦ Çâ»ó½ÃÅ°±â À§ÇØ ½á¾ß ÇÏ´Â °ÍÀÓ!!
- File Attribute Flags
- FILE_ATTRIBUTE_HIDDEN µîµî
- FILE_ATTRIBUTE_TEMPORARY : ¸Þ¸ð¸®¿¡¼ ÆÄÀÏÀ» Á¶ÀÛ. ÆÄÀÏÀÌ ´õ ÀÌ»ó ÇÊ¿ä¾ø°Ô µÇ¸é µð½ºÅ©¿¡ ¾¸. (FILE_FLAG_DELETE_ON_CLOSE ¿Í ÇÔ²² ¾²¸é ÁÁÀ½)
- ¿Ü ´Ù¼ö
- hfileTemplate ÀÎÀÚ - ÀÌ¹Ì ¿·Á ÀÖ´Â ÆÄÀÏÀÇ ÇÚµéÀ» ¿©±â¿¡ Á¦°øÇϸé, ±× ÆÄÀÏÀÇ dwFlagsAndAttrs ¼Ó¼ºÀ» ºô·Á ¾¸.
- CreateFile ÀÌ ½ÇÆÐÇϸé INVALID_HANDLE_VALUE °¡ ¸®ÅÏµÊ (NULLÀÌ ¸®ÅϵǴ °ÍÀÌ ¾Æ´Ô¿¡ ÁÖÀÇ!!)
Working with File Devices
- À©µµ¿ìÁîÀÇ ÆÄÀÏ»çÀÌÁîÀÇ ÃÖ´ëÅ©±â´Â »ç½Ç 64-bit (16ExaByte) ÀÌ´Ù.
Getting a File's Size
- BOOL GetFileSizeEx( HANDLE hfile, PLARGE_INTEGER pliFileSize )
- LARGE_INTEGER, ULARGE_INTEGER, LONGLONG, ULONGLONG
- DWORD GetCompressedFileSize( PCTSTR pszFileName, PDWORD pdwFileSizeHigh )
Positioning a File Pointer
- ¾Ë¾ÆµÎ¸é ÁÁÀº APIµé:
- BOOL ReadFile( HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped );
- BOOL DuplicateHandle( HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions )
- BOOL SetEndOfFile( HANDLE hFile ) : ÆÄÀÏÀÇ Å©±â¸¦ °£´ÜÇÏ°Ô ´ÃÀ̰ųª ÁÙÀÏ ¼ö ÀÖ´Ù.
- BOOL SetFilePointerEx( HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod ) : ÆÄÀÏ Æ÷ÀÎÅ͸¦ ¿òÁ÷ÀδÙ.
Performing Synchronous Device I/O
BOOL ReadFile(
HANDLE hFile, // handle to file
LPVOID lpBuffer, // data buffer
DWORD nNumberOfBytesToRead, // number of bytes to read
LPDWORD lpNumberOfBytesRead, // number of bytes read
LPOVERLAPPED lpOverlapped // overlapped buffer
);
BOOL WriteFile(
HANDLE hFile, // handle to file
LPCVOID lpBuffer, // data buffer
DWORD nNumberOfBytesToWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten, // number of bytes written
LPOVERLAPPED lpOverlapped // overlapped buffer
);
BOOL FlushFileBuffers(
HANDLE hFile // handle to file
);
Basics of Asynchronous Device I/O
- FILE_FLAG_OVERLAPPED ·Î »ý¼ºÇÑ hFile À» °¡Áö°í, ReadFile/WriteFileÀ» ÇÏ¸é ¾î½ÌÅ©ÇÏ°Ô µ¿ÀÛÇÑ´Ù.
- ÀÌ °æ¿ì pdwNumBytes´Â Àǹ̾øÀ¸¹Ç·Î º¸Åë NULL À» ³Ö´Â´Ù.
- ¶ÇÇÑ OVERLAPPED ±¸Á¶Ã¼¸¦ ÃʱâÈÇÏ¿© ÀÎÀÚ·Î Á¦°øÇØ¾ß ÇÑ´Ù.
The OVERLAPPED Structure
typedef struct _OVERLAPPED {
ULONG_PTR Internal; // [out] Error code
ULONG_PTR InternalHigh; // [out] Numver of bytes transferred
DWORD Offset; // [in] Low 32-bit file offset
DWORD OffsetHigh; // [in] High 32-bit file offset
HANDLE hEvent; // [in] Event handle or data
} OVERLAPPED;
#define HasOverlappedIoCompleted(pOverlapped) ((pOverlapped)->Internal != STATUS_PENDING)
- Offset & OffsetHigh - 64ºñÆ® ÆÄÀÏ ¿É¼Â. ÆÄÀÏÀÌ ¾Æ´Ñ µð¹ÙÀ̽º¿¡ ´ëÇؼµµ üũµÇ¹Ç·Î ÀÌ °æ¿ì´Â 0 À¸·Î ¹Ýµå½Ã ÃʱâÈ ÇØ ÁÖ¾î¾ß ÇÑ´Ù. ±×·¸Áö ¾ÊÀ¸¸é GetLastError()¿¡¼ ERROR_INVALID_PARAMETER °¡ ¸®Å쵃 °ÍÀÌ´Ù.
- hEvent - I/O completion notification À» ¹Þ±â À§ÇØ ¼¼ÆÃÇØ ÁØ´Ù.
- Internal - ¿¡·¯ÄÚµå ȤÀº I/O request ó¸® »óÅ°¡ ±â·ÏµÈ´Ù. ¾ÆÁ÷ 󸮽ÃÀÛÇÏÁö ¾ÊÀº ÃʱⰪÀº STATUS_PENDING ÀÌ´Ù.
- InternalHigh - I/O request°¡ ¿Ï·áµÇ¸é Àü¼ÛµÈ ¹ÙÀÌÆ®°¡ ±â·ÏµÈ´Ù.
- I/O request°¡ ¿Ï·áµÇ¸é lpOverlapped ÀÇ Æ÷ÀÎÅ͸¦ Å뺸¹Þ°Ô µÈ´Ù.
- ¸¸¾à ´õ ¸¹Àº context Á¤º¸ (¿¹¸¦ µé¾î hFile)¸¦ ÀÌ ±¸Á¶Ã¼¿¡ ³Ö°í ½Í´Ù¸é ¹æ¹ýÀÌ ÀÖ´Ù. OVERLAPPED¸¦ »ó¼ÓÇÑ ±¸Á¶Ã¼¸¦ Çϳª ¸¸µé¾î, lpOverlapped ¸¦ ¹Þ¾ÒÀ» ¶§ »õ ±¸Á¶Ã¼·Î casting ÇÏ¸é µÈ´Ù. Áï, Àú Æ÷ÀÎÅÍ´Â À¯ÁöµÈ´Ù.
Asynchronous Device I/O Caveats
- Overlapped I/O ´Â FIFO ¹æ½ÄÀ¸·Î 󸮵ÇÁö ¾ÊÀ» ¼öµµ ÀÖ´Ù. Áï, ¸ÕÀú ¿äûÇÑ °ÍÀÌ ¸ÕÀú ó¸®µÈ´Ù°í º¸ÀåÇØ ÁÖÁö ¾Ê´Â´Ù.
- ¿¡·¯Ã³¸®¿¡ ÁÖÀÇÇÒ °Í:
- async ·Î ¿äûÇصµ sync ·Î ó¸®µÉ ¼ö°¡ ÀÖ´Ù. (ij½¬¿¡ ÀÖ´Â °æ¿ì µî) ÀÌ·± °æ¿ì¿¡´Â TRUE °¡ ¸®ÅϵǹǷΠµû·Î ó¸®ÇÒ °Í.
- ¿¡·¯°¡ ³ª°Å³ª request °¡ queue ¿¡ µé¾î°¡¸é FALSE °¡ ¸®ÅϵȴÙ.
- GetLastError()¸¦ ÇغÁ¾ß ÇÑ´Ù.
- ERROR_IO_PENDING ÀÌ¸é ¼º°øÀûÀ¸·Î Å¥À×µÈ °Í.
- ´Ù¸¥ °ªÀÌ¸é ¿¡·¯ ¹ß»ý.
- ERROR_INVALID_USER_BUFFER or ERROR_NOT_ENOUGH_MEMORY : device ÀÇ »ç¿ëÀÚ ¹öÆÛ°¡ ²Ë Âù °æ¿ì
- ERROR_NOT_ENOUGH_QUOTA : device ¿¡ µû¶ó buffer (memory)¸¦ page lock ÇØ¾ß ÇÏ´Â °æ¿ì°¡ ÀÖ´Ù. ½Ì±Û ÇÁ·Î¼¼½º°¡ ÇÒ ¼ö ÀÖ´Â page lockÀÇ »çÀÌÁî´Â ¹Ì¸® Á¤ÇØÁ® ÀÖÀ¸¹Ç·Î À̸¦ ³Ñ±â¸é page lock ¿¡ ½ÇÆÐÇÏ°Ô µÈ´Ù. À̶§ ¹ß»ýÇÏ´Â ¿¡·¯. SetProcessWorkingSetSize() ·Î ÀÌ ¾çÀ» ´Ã¸± ¼ö ÀÖ´Ù.
- ¿¡·¯ ÇØ°á¹ý: ÀÌ ¿¡·¯µéÀº °á±¹ ³Ê¹« ¸¹Àº I/O request°¡ 󸮵ÇÁö ¸øÇÑ Ã¤ ³²¾Æ Àֱ⿡ »ý±â´Â °ÍÀÌ´Ù. ±×·¯¹Ç·Î Àá½Ã ¿äûÀ» º¸·ùÇß´Ù°¡ ´Ù½Ã ReadFileÀ̳ª WriteFileÀ» È£ÃâÇÏ¸é µÉ °ÍÀÌ´Ù.
- Data Buffer¿Í OVERLAPPED ±¸Á¶Ã¼ÀÇ ¸Þ¸ð¸®´Â I/O request°¡ ¿Ï·áµÉ ¶§±îÁö ÇØÁ¦µÇ°Å³ª À̵¿µÇ¾î¼´Â ¾ÈµÈ´Ù!! ¹°·Ð °¢ I/O request¿¡ ´ëÇØ OVERLAPPED ±¸Á¶Ã¼´Â ¸ðµÎ ´Þ¶ó¾ß ÇÑ´Ù!!
Cancelling Queued I/O Requests
- BOOL CancelIo( HANDLE hFile )
- handle À» ´ÝÀ¸¸é ¸ðµç Å¥À×µÈ i/o´Â Ãë¼ÒµÈ´Ù.
- ½º·¹µå°¡ Á×À¸¸é ±× ½º·¹µå°¡ Å¥À×ÇÑ i/o´Â ÀÚµ¿À¸·Î Ãë¼ÒµÈ´Ù.
- ƯÁ¤ i/o request Çϳª¸¸À» Ãë¼ÒÇÏ´Â ¹æ¹ýÀº ¾ø´Ù.
- Ãë¼ÒµÈ I/O request´Â ERROR_OPERATION_ABORTED °ªÀ» °¡Áö°í complete 󸮵ȴÙ.
Receiving Completed I/O Request Notifications
- I/O request°¡ ¿Ï·áµÇ¾úÀ» ¶§ notification À» ¹Þ´Â ¹æ¹ýÀº 4 °¡Áö°¡ ÀÖ´Ù.
Signaling a device kernel object | ÇÑ device ¿¡ ´ëÇØ ¿©·¯ I/O request°¡ µ¿½Ã¿¡ ÁøÇàÁßÀ̶ó¸é ¾µ¸¸ÇÏÁö ¾ÊÀº ¹æ¹ýÀÌÁö¸¸, ÇÑ ¾²·¹µå°¡ I/O request¸¦ ¹ß»ý½ÃÅ°°í, ´Ù¸¥ ½º·¹µå°¡ ±×°ÍÀ» ó¸®ÇÏ´Â °ÍÀÌ °¡´ÉÇÏ´Ù. |
Signaling an event kernel object | ÇÑ device ¿¡ ´ëÇØ ¿©·¯ I/O request°¡ µ¿½Ã¿¡ ¹ß»ýÇصµ ±¦Âú´Ù. ÇÑ ¾²·¹µå°¡ I/O request¸¦ ¹ß»ý½ÃÅ°°í, ´Ù¸¥ ½º·¹µå°¡ ±×°ÍÀ» ó¸®ÇÏ´Â °ÍÀÌ °¡´ÉÇÏ´Ù. |
Using alertable I/O | ÇÑ device ¿¡ ´ëÇØ ¿©·¯ I/O request°¡ µ¿½Ã¿¡ ¹ß»ýÇصµ ±¦Âú´Ù. I/O request¸¦ ¹ß»ý½ÃŲ ½º·¹µå°¡ ¹Ýµå½Ã ±×°ÍÀ» ó¸®ÇØ¾ß ÇÑ´Ù. |
Using I/O completion ports | ÇÑ device ¿¡ ´ëÇØ µ¿½Ã´Ù¹ß I/O request°¡ ¹ß»ýÇصµ ±¦Âú´Ù. ÇÑ ½º·¹µå°¡ I/O request¸¦ ¹ß»ý½ÃÅ°°í, ´Ù¸¥ ½º·¹µå°¡ ±×°ÍÀ» ó¸®ÇÏ´Â °ÍÀÌ °¡´ÉÇÏ´Ù. ¼º´É°ú À¯¿¬¼ºÀÌ °¡Àå ÁÁÀº ¹æ¹ý. |
Method 1. Signaling a Device Kernel Object
- thread syncronization : °á±¹ device ¿¡ÀÇ ¿äûÀÌ Ã³¸®µÇ¾ú´ÂÁö¸¦ ±â´Ù·Á¾ß ÇÑ´Ù.
- Ä¿³Î ¿ÀºêÁ§Æ®´Â signaled state³ª nonsignaled state ÁßÀÇ ÇÑ °ªÀ» °¡Áö°Ô µÈ´Ù.
- WaitForSingleObject() ³ª WaitForMultipleObjects() ¸¦ ½á¼ request °¡ ¿Ï·áµÇ¾ú´ÂÁö ¾Ë ¼ö ÀÖ´Ù.
Method 2. Signaling an Event kernel Object
- OVERLAPPED ±¸Á¶Ã¼ÀÇ hEvent ÆĶó¸ÞÅ͸¦ ÀÌ¿ëÇÑ´Ù.
- hEvent ÀÇ À̺¥Æ® ÇÚµéÀº CreateEvent()¸¦ ÀÌ¿ëÇؼ »ý¼º.
- multiple objectÀÇ ´ë±â´Â WaitForMultipleObjects()¸¦ ÀÌ¿ëÇؼ ÇÒ ¼ö ÀÖ´Ù.
- ¹°·Ð, WaitForSingleObject()·Î Çϳª¾¿ ±â´Ù·Áµµ µÈ´Ù.
- GetOverlappedResult()
BOOL GetOverlappedResult(
HANDLE hFile, // handle to file, pipe, or device
LPOVERLAPPED lpOverlapped, // overlapped structure
LPDWORD lpNumberOfBytesTransferred, // bytes transferred
BOOL bWait // wait option
);
Method 3. Alertable I/O
- ÀÌ ³ÑÀº ÁöÀúºÐ ÇϹǷΠ°¡´ÉÇϸé ÇÇÇØ¾ß ÇÑ´Ù. ÇÏÁö¸¸ OS¿¡ Æ÷ÇÔµÈ ±× Áö¿øºÎºÐÀº ¾µ¹ýÇÑ °ÍÀÌ ÀÖ´Ù.
- APC Queue: an Asynchronous Procedure Call Queue - per threads.
- APC Queue¸¦ ÀÌ¿ëÇÏ·Á¸é ReadFileEx¿Í WriteFileEx¸¦ ½á¾ß ÇÑ´Ù.
BOOL ReadFileEx(
HANDLE hFile, // handle to file
LPVOID lpBuffer, // data buffer
DWORD nNumberOfBytesToRead, // number of bytes to read
LPOVERLAPPED lpOverlapped, // offset
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine // completion routine
);
BOOL WriteFileEx(
HANDLE hFile, // handle to output file
LPCVOID lpBuffer, // data buffer
DWORD nNumberOfBytesToWrite, // number of bytes to write
LPOVERLAPPED lpOverlapped, // overlapped buffer
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine // completion routine
);
VOID CALLBACK FileIOCompletionRoutine(
DWORD dwErrorCode, // completion code
DWORD dwNumberOfBytesTransfered, // number of bytes transferred
LPOVERLAPPED lpOverlapped // I/O information buffer
);
- ReadFileEx/WriteFileEx¿¡ callback ÇÔ¼ö¸¦ ÁöÁ¤ÇÏ¿© È£ÃâÇÑ´Ù. (¹«Á¶°Ç async i/o request)
- tip: ÀÌ °æ¿ì OVERLAPPED::hEvent ´Â ÀüÇô »ç¿ëµÇÁö ¾ÊÀ¸¹Ç·Î, ¿øÇÏ´Â ¿ëµµ·Î ½áµµ µÈ´Ù.
- i/o request°¡ 󸮵Ǹé device driver´Â ±× Á¤º¸¸¦ APC Queue¿¡ µî·ÏÇÑ´Ù. APC Queue¿¡´Â callback functionÀÇ ÁÖ¼Ò¿Í Ã³¸®°á°ú¸¦ ÀúÀåÇÑ entry µéÀÌ Àִµ¥, ½ÇÁ¦·Î callback ÀÌ È£ÃâµÇ´Â °ÍÀº ÀÌÈÄÀÇ ½ÃÁ¡ÀÌ´Ù. ±× ½ÃÁ¡À̶õ ¹Ù·Î thread°¡ alertable »óÅ°¡ µÇ´Â °ÍÀÌ´Ù.
- thread¸¦ altertable »óÅ·Π¸¸µå´Â ÇÔ¼ö´Â 5 °³°¡ ÀÖ´Ù.
- DWORD SleepEx( DWORD dwTimeout, BOOL fAlertable )
- DWORD WaitForSingleObjectEx( HANDLE hObject, DWORD dwTimeout, BOOL fAlertable )
- DWODD WaitForMultipleObjectsEx( DWOD cObjects, PHANDLE phObjects, BOOL fWaitAll, DWORD dwTimeout, BOOL fAlertable )
- BOOL SingleObjectAndWait( HANDLE hObjectToSignal, HANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL fAlertable )
- DWORD MsgWaitForMultipleObjectsEx( DWORD nCount, PHANDLE pHandles, DWORD dwMilliseconds, DWORD dwWakeMask, DWORD dwFlags )
- À§ÀÇ ÇÔ¼öµéÀº thread °¡ alertabe »óÅ°¡ µÇ¾î Çϳª¶óµµ i/o complete ¸¦ È®ÀÎÇÏ°í callback function À» È£ÃâÇßÀ¸¸é WAIT_IO_COMPLETION À» ¸®ÅÏ. ±×·¸Áö ¾ÊÀ¸¸é sleep Çß´Ù°¡ timeout µÇ¾î ÀϾ °ÍÀÓ.
- DWORD QueueUserAPC( PAPCFUNC pfnAPC, HANDLE hThread, ULONG_PTR dwData )
- pfnAPC : VOID WINAPI APCFunc( ULONG_PTR dwParam )
- hThread : ´Ù¸¥ ÇÁ·Î¼¼½ºÀÇ thread µµ °¡´É. ÀÌ °æ¿ì¿¡µµ pfnAPC´Â ÇØ´ç ½º·¹µåÀÇ ÁÖ¼Ò°ø°£À̾î¾ß ÇÔ.
- dwData : ±×Àú callback ÇÔ¼ö¿¡ ³Ñ°ÜÁö´Â °ª. À̸¦ ÅëÇØ ´Ù¸¥ ÇÁ·Î¼¼½º/½º·¹µå¿Í °£´ÜÇÑ Åë½ÅÀ» ÇÒ ¼ö ÀÖ´Ù.
- ÀÌ ÇÔ¼ö´Â wait state ÀÇ thread¸¦ °Á¦·Î ±ú¾î³ª°Ô ÇÒ ¼ö ÀÖ´Ù. (Graceful Close: ±ú±ßÇÑ ¾²·¹µå Á×À̱⠱¸Çö µî¿¡ »ç¿ë°¡´É)
Method 4. I/O Completion Ports
- Serial model: ping ¼¹öó·³ Ŭ¶óÀ̾ðÆ®ÀÇ ¿ä±¸¸¦ ª°Ô ó¸®ÇÒ ¼ö ÀÖ´Â ÀÏ.
- Concurrent model: listening thread¿Í working thread°¡ ºÐ¸®µÈ ¸ðµ¨. context switching ºñ¿ëÀÌ ³Ê¹« ¸¹ÀÌ µç´Ù.
Creating an I/O Completion Port
- I/O completion port´Â thread pool ¸ðµ¨¿¡¼ »ç¿ëµÇµµ·Ï ¸¸µé¾î Á³´Ù.
HANDLE CreateIoCompletionPort (
HANDLE FileHandle, // handle to file
HANDLE ExistingCompletionPort, // handle to I/O completion port
ULONG_PTR CompletionKey, // completion key
DWORD NumberOfConcurrentThreads // number of threads to execute concurrently
);
- ÀÌ ÇÔ¼ö´Â ¸Å¿ì º¹ÀâÇÏ°í µÎ ºÎºÐÀ» Æ÷°ýÇÏ°í ÀÖÀ¸¹Ç·Î ´ÙÀ½ÀÇ µÎ °¡Áö ÀÛÀº ÇÔ¼ö·Î ºÐÇÒÇÒ °ÍÀ» Á¦¾ÈÇÑ´Ù.
- ù¹ø° ºÎºÐ: i/o completion port »ý¼º.
HANDLE CreatenewCompletionPort( DWORD dwNumberOfConcurrentThreads ) {
return (CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, dwNumberOfConcurrentThreads ));
- i/o completion portÀÇ »ý¼ºÀº ´ÙÀ½ÀÇ 5 °¡Áö ±¸Á¶ÀÇ »ý¼ºÀ» ¾ß±âÇÑ´Ù.
- Device List
- I/O Completion Queue (FIFO)
- Waiting Thread Queue (LIFO)
- Released Thread List
- Paused Thread List
Associating a Device with an I/O Completion Port
- µÎ¹ø° ºÎºÐ: device¿Í completion port¸¦ ¿¬°á
BOOL AssociateDeviceWithCompletionPort( HANDLE hCompPort, HANDLE hDevice, DWORD dwCompKey ) {
HANDLE h = CreateIoCompletionPort( hDevice, hCompPort, dwCompKey, 0 );
return ( h == hCompPort );
}
Archtecting Around an I/O Completion Port
- thread pool Àº kernel ¿¡ ÀÇÇØ °ü¸®µÇ´Â ¸ð¾ç(?)
- concurrent ÇÏ°Ô ½ÇÇàµÇ´Â ½º·¹µåÀÇ ¼ö´Â CPUÀÇ °³¼ö¿Í °°°Ô. ½ÇÁ¦·Î »ý¼ºÇÏ´Â ½º·¹µåÀÇ °³¼ö´Â CPU °³¼ö x 2 °¡ ±ÇÀå»çÇ×.
- °¢ ½º·¹µå´Â ·çÇÁ¸¦ µ¹¸ç device I/O °¡ ³¡³ª±â¸¦ ±â´Ù¸®°ï ÇÒ °ÍÀÌ´Ù. (thread sleep!)
- ÀÌ ÀÛ¾÷À» ÇÏ´Â °ÍÀÌ GetQueuedCompletionStatus() ÇÔ¼ö.
BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort, // handle to completion port
LPDWORD lpNumberOfBytes, // bytes transferred
PULONG_PTR lpCompletionKey, // file completion key
LPOVERLAPPED *lpOverlapped, // buffer
DWORD dwMilliseconds // optional timeout value
);
- ÀÌ thread´Â Ä¿³Î ³»ºÎÀÇ waiting thread queue¿¡ µî·ÏµÊ.
- i/o completion ÀÌ ÀϾ¸é Ä¿³ÎÀÌ ÇØ´ç thread¸¦ ±ú¿ò.
- GetQueuedCompletionStatus()ÀÇ ¸®ÅÏ°ªÀ» °áÁ¤ÇÏ´Â °ÍÀº Á¶±Ý º¹ÀâÇÏ´Ù. (»ùÇÃÄڵ带 º¼°Í)
- Waiting Thread Queue°¡ LIFOÀÎ °ÍÀº ¼º´É Çâ»óÀ» À§ÇÑ °Í. i/o completionÀÇ ¼Óµµ°¡ ´À¸®´Ù¸é ÀûÀº ¼ö (ȤÀº 1°³)ÀÇ ½º·¹µå¸¸ ¾²ÀÏ °ÍÀÌ°í, ³ª¸ÓÁö´Â µð½ºÅ©¿¡ flush µÇ°Å³ª ÇÏ¿© ¸®¼Ò½º¸¦ °ÅÀÇ ¾²Áö ¾Ê°ÔµÈ´Ù.
How the I/O Completion Port Manages the Thread Pool
- I/O completion À» ¸¸µé¸é¼ concurrent threadÀÇ °³¼ö´Â CPUÀÇ °³¼ö·Î ¼¼ÆÃ.
- ½ÇÁ¦ ½º·¹µå´Â CPU°³¼öx2 °³¸¦ »ý¼º
- completed I/O°¡ Å¥¿¡ µé¾î¿À¸é completion port°¡ waiting thread¸¦ Çϳª ±ú¿ö¼ released thread queue·Î ¿Å±è.
- ¸¸¾à running thread°¡ Sleep(), WaitForSingleObject()µîÀÇ sleepÀ» À¯µµÇÏ´Â ÇÔ¼ö¸¦ callÇϸé, paused thread queue·Î ¿Å°Ü°¨. À̶§, released queueÀÇ ¼ö°¡ °¨¼ÒÇϹǷΠcompletion port°¡ waiting threadÀÇ ´Ù¸¥ ½º·¹µå¸¦ ±ú¿ö completed I/O¸¦ ó¸®Çϵµ·Ï ÇÔ. (ÃÖ´ë CPUÀÇ °³¼ö!)
- Áß°£¿¡ paused thread°¡ ƯÁ¤ Á¶°ÇÀ» ¸¸Á·ÇÏ¸é¼ ´Ù½Ã ±ú¾î³². completion port´Â À̸¦ °¨ÁöÇÏ°í ÀÌ ½º·¹µå¸¦ released thread queue·Î ¿Å±è. ÀÌ ¶§ ¼ø°£ÀûÀ¸·Î ÁöÁ¤Çß´ø concurrency threadÀÇ °³¼öº¸´Ù ¸¹Àº ½º·¹µå°¡ ½ÇÇàµÊ.
- º¸Åë ·çÇÁ¸¦ µ¹¸é¼ ´Ù½Ã GetQueuedCompletionStatus()¸¦ È£ÃâÇÏ°Ô µÇ¹Ç·Î ÀÌ ½º·¹µå µéÀº waiting thread queue·Î µ¹¾Æ°¨.
- ÀÌ·± ½ÄÀ¸·Î released thread queue´Â Ç×»ó ÃÖ´ë °³¼ö·Î À¯ÁöµÇ¸ç, context switchingÀÇ È¸¼ö°¡ ÃÖ¼Ò·Î À¯ÁöµÇ´Â °¡¿îµ¥, ÃÖ´ë È¿À²·Î µ¹¾Æ°¡°Ô µÊ.
How Many Threads in the Pool?
- heuristic algorithms (°¡À̵å¶óÀÎ »ùÇà ÄÚµå ÂüÁ¶)
Simulating Completed I/O Requests
- PostQueuedCompletionStatus ¸¦ ÀÌ¿ëÇؼ °¡Â¥ i/o completion entry¸¦ ¿Ã¸± ¼ö ÀÖ´Ù.
- À̸¦ ÀÌ¿ëÇؼ thread °£ÀÇ Åë½ÅÀ» ÇÒ ¼ö ÀÖ´Ù!
- threadÀÇ graceful close ¸¦ ÇÒ ¼ö ÀÖÀ¸³ª, ÀÌ °æ¿ì wait thread queue°¡ LIFO ¶ó´Â °ÍÀ» ÁÖÀÇÇØ¾ß ÇÑ´Ù. (Ã¥ÀáÁ¶)
BOOL PostQueuedCompletionStatus(
HANDLE CompletionPort, // handle to an I/O completion port
DWORD dwNumberOfBytesTransferred, // bytes transferred
ULONG_PTR dwCompletionKey, // completion key
LPOVERLAPPED lpOverlapped // overlapped buffer
);
Tips From This Book
ºÐ·ù°³¹ß