Programming Server-Side Applications

냥날위키 페이지목록 변경내역 환경설정 로그인 검색: Home

Programming Server-Side Applications for Windows 2000

by Jeffrey Richter & Jason D. Clark

Chapter One: Te Discipline of Service Development

Scalability and Perfomance

서버 프로그래밍을 할 때 염두해 두어야 하는 것:

Chapter Two: DEVICE I/O AND INTERTHREAD COMMUNICATION

Opening and Closing Devices

Device Creational Functiion
File CreateFile("c:\test.txt")
Directory CreateFile("c:\Program Files", ..., FILE_FLAG_BACKUP_SEMANTICS)
Logical disk drive CreateFile( "\\.\C:" )
Physical disk drive CreateFile( "\\.\PHYSICALDRIVE0" )
Serial Port CreateFile( "COM1" )
Parallel port CreateFile( "LPT1" )
Mailslot server CreateMailslot( "\\.\mailslot\mailslotname" )
Mailslot client CreateFile( "\\servername\mailslot\mailslotname" )
Named pipe server CreateNamedPipe( "\\.\pipe\pipename" )
Named pipe client CreateFile( "\\servername\\pipe\pipename" )
Anonymous pipe CreatePipe client and server
Socket socket(), accept(), AcceptEx()
Console CreateConsoleScreenBuffer(), or GetStdHandle()

A Detailed Look at CreateFile

Working with File Devices

Getting a File's Size

Positioning a File Pointer

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

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)

Asynchronous Device I/O Caveats

Cancelling Queued I/O Requests

Receiving Completed I/O Request Notifications

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

Method 2. Signaling an Event kernel Object

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

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

Method 4. I/O Completion Ports

Creating an I/O Completion Port
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
);

HANDLE CreatenewCompletionPort( DWORD dwNumberOfConcurrentThreads ) {
  return (CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, dwNumberOfConcurrentThreads ));

Associating a Device with an I/O 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

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

How the I/O Completion Port Manages the Thread Pool
  1. I/O completion 을 만들면서 concurrent thread의 개수는 CPU의 개수로 세팅.
  2. 실제 스레드는 CPU개수x2 개를 생성
  3. completed I/O가 큐에 들어오면 completion port가 waiting thread를 하나 깨워서 released thread queue로 옮김.
  4. 만약 running thread가 Sleep(), WaitForSingleObject()등의 sleep을 유도하는 함수를 call하면, paused thread queue로 옮겨감. 이때, released queue의 수가 감소하므로 completion port가 waiting thread의 다른 스레드를 깨워 completed I/O를 처리하도록 함. (최대 CPU의 개수!)
  5. 중간에 paused thread가 특정 조건을 만족하면서 다시 깨어남. completion port는 이를 감지하고 이 스레드를 released thread queue로 옮김. 이 때 순간적으로 지정했던 concurrency thread의 개수보다 많은 스레드가 실행됨.
  6. 보통 루프를 돌면서 다시 GetQueuedCompletionStatus()를 호출하게 되므로 이 스레드 들은 waiting thread queue로 돌아감.

How Many Threads in the Pool?

Simulating Completed I/O Requests
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


분류개발

마지막 편집일: 2013-6-24 2:39 pm (변경사항)
3235 hits | 변경내역 보기 | 페이지 소스 보기