/* * IoByAPC.c * * Sample code for Multithreading Applications in Win32 * This is from Chapter 6, Listing 6-3 * * Demonstrates how to use APC's (asynchronous * procedure calls) instead of signaled objects * to service multiple outstanding overlapped * operations on a file. */
#define WIN32_LEAN_AND_MEAN#include <stdio.h>#include <stdlib.h>#include <windows.h>#include "MtVerify.h"
//// Constants//#define MAX_REQUESTS 5#define READ_SIZE 512#define MAX_TRY_COUNT 5
//// Function prototypes//void CheckOsVersion();int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount);
//// Global variables//
// Need a single event object so we know when all I/O is finishedHANDLE ghEvent;// Keep track of each individual I/O operationOVERLAPPED gOverlapped[MAX_REQUESTS];// Handle to the file of interest.HANDLE ghFile;// Need a place to put all this datachar gBuffers[MAX_REQUESTS][READ_SIZE];int nCompletionCount;
/* * I/O Completion routine gets called * when app is alertable (in WaitForSingleObjectEx) * and an overlapped I/O operation has completed. */VOID WINAPI FileIOCompletionRoutine( DWORD dwErrorCode, // completion code DWORD dwNumberOfBytesTransfered, // number of bytes transferred LPOVERLAPPED lpOverlapped // pointer to structure with I/O information ){ // The event handle is really the user defined data int nIndex = (int)(lpOverlapped->hEvent); printf("Read #%d returned %d. %d bytes were read.\n", nIndex, dwErrorCode, dwNumberOfBytesTransfered);
if (++nCompletionCount == MAX_REQUESTS) SetEvent(ghEvent); // Cause the wait to terminate}
int main(){ int i; char szPath[MAX_PATH];
CheckOsVersion();
// Need to know when to stop MTVERIFY( ghEvent = CreateEvent( NULL, // No security TRUE, // Manual reset - extremely important! FALSE, // Initially set Event to non-signaled state NULL // No name ) );
GetWindowsDirectory(szPath, sizeof(szPath)); strcat(szPath, "http://www.cnblogs.com/nanshouyong326/admin/file://WINHLP32.EXE/"); // Open the file for overlapped reads ghFile = CreateFile( szPath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ); if (ghFile == INVALID_HANDLE_VALUE) { printf("Could not open %s\n", szPath); return -1; }
// Queue up a few requests for (i=0; i<MAX_REQUESTS; i++) { // Read some bytes every few K QueueRequest(i, i*16384, READ_SIZE); }
printf("QUEUED!!\n");
// Wait for all the operations to complete. for (;;) { DWORD rc; rc = WaitForSingleObjectEx(ghEvent, INFINITE, TRUE ); if (rc == WAIT_OBJECT_0) break; MTVERIFY(rc == WAIT_IO_COMPLETION); }
CloseHandle(ghFile);
return EXIT_SUCCESS;}
/* * Call ReadFileEx to start an overlapped request. * Make sure we handle errors that are recoverable. */int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount){ int i; BOOL rc; DWORD err;
gOverlapped[nIndex].hEvent = (HANDLE)nIndex; gOverlapped[nIndex].Offset = dwLocation;
for (i=0; i<MAX_TRY_COUNT; i++) { rc = ReadFileEx( ghFile, gBuffers[nIndex], dwAmount, &gOverlapped[nIndex], FileIOCompletionRoutine );
// Handle success if (rc) { // asynchronous i/o is still in progress printf("Read #%d queued for overlapped I/O.\n", nIndex); return TRUE; }
err = GetLastError();
// Handle recoverable error if ( err == ERROR_INVALID_USER_BUFFER || err == ERROR_NOT_ENOUGH_QUOTA || err == ERROR_NOT_ENOUGH_MEMORY ) { Sleep(50); // Wait around and try later continue; }
// Give up on fatal error. break; }
printf("ReadFileEx failed.\n"); return -1;}
//// Make sure we are running under an operating// system that supports overlapped I/O to files.//void CheckOsVersion(){ OSVERSIONINFO ver; BOOL bResult;
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
bResult = GetVersionEx((LPOSVERSIONINFO) &ver);
if ( (!bResult) || (ver.dwPlatformId != VER_PLATFORM_WIN32_NT) ) { fprintf(stderr, "IoByAPC must be run under Windows NT.\n"); exit(EXIT_FAILURE); }
}
od
00401040 /$ 81EC 0C020000 sub esp, 20C00401046 |. 56 push esi00401047 |. 57 push edi00401048 |. E8 E3020000 call 004013300040104D |. 6A 00 push 0 ; /EventName = NULL0040104F |. 6A 00 push 0 ; |InitiallySignaled = FALSE00401051 |. 6A 01 push 1 ; |ManualReset = TRUE00401053 |. 6A 00 push 0 ; |pSecurity = NULL00401055 |. FF15 28204000 call dword ptr [<&KERNEL32.CreateEven>; \CreateEventA0040105B |. 85C0 test eax, eax0040105D |. A3 90314000 mov dword ptr [403190], eax00401062 |. 0F85 80000000 jnz 004010E800401068 |. FF15 24204000 call dword ptr [<&KERNEL32.GetLastErr>; [GetLastError0040106E |. 6A 00 push 0 ; /Arguments = NULL00401070 |. 8D4C24 0C lea ecx, dword ptr [esp+C] ; |00401074 |. 6A 00 push 0 ; |BufSize = 000401076 |. 51 push ecx ; |Buffer00401077 |. 6A 00 push 0 ; |LanguageId = 0 (LANG_NEUTRAL)00401079 |. 50 push eax ; |MessageId0040107A |. 6A 00 push 0 ; |pSource = NULL0040107C |. 68 00110000 push 1100 ; |Flags = ALLOCATE_BUFFER|FROM_SYSTEM|000401081 |. FF15 20204000 call dword ptr [<&KERNEL32.FormatMess>; \FormatMessageA00401087 |. 8B5424 08 mov edx, dword ptr [esp+8]0040108B |. 8D4424 10 lea eax, dword ptr [esp+10]0040108F |. 52 push edx ; /<%s>00401090 |. 68 D8304000 push 004030D8 ; |<%s> = "ghEvent = CreateEvent( NULL, TRUE, FALSE, NULL )"00401095 |. 68 CC304000 push 004030CC ; |<%s> = "IoByAPC.c"0040109A |. 6A 55 push 55 ; |<%d> = 55 (85.)0040109C |. 68 88304000 push 00403088 ; |Format = LF,"The following call failed at line %d in %s:",LF,LF," %s",LF,LF,"Reason: %s",LF,""004010A1 |. 50 push eax ; |s004010A2 |. FF15 7C204000 call dword ptr [<&USER32.wsprintfA>] ; \wsprintfA004010A8 |. 83C4 18 add esp, 18004010AB |. 8D4C24 0C lea ecx, dword ptr [esp+C]004010AF |. 8D7C24 10 lea edi, dword ptr [esp+10]004010B3 |. 33C0 xor eax, eax004010B5 |. 6A 00 push 0 ; /pOverlapped = NULL004010B7 |. 51 push ecx ; |pBytesWritten004010B8 |. 83C9 FF or ecx, FFFFFFFF ; |004010BB |. 8D5424 18 lea edx, dword ptr [esp+18] ; |004010BF |. F2:AE repne scas byte ptr es:[edi] ; |004010C1 |. F7D1 not ecx ; |004010C3 |. 49 dec ecx ; |004010C4 |. 51 push ecx ; |nBytesToWrite004010C5 |. 52 push edx ; |Buffer004010C6 |. 6A F4 push -0C ; |/DevType = STD_ERROR_HANDLE004010C8 |. FF15 1C204000 call dword ptr [<&KERNEL32.GetStdHand>; |\GetStdHandle004010CE |. 50 push eax ; |hFile004010CF |. FF15 18204000 call dword ptr [<&KERNEL32.WriteFile>>; \WriteFile004010D5 |. 68 B80B0000 push 0BB8 ; /Timeout = 3000. ms004010DA |. FF15 14204000 call dword ptr [<&KERNEL32.Sleep>] ; \Sleep004010E0 |. 6A 01 push 1 ; /status = 1004010E2 |. FF15 40204000 call dword ptr [<&MSVCRTD.exit>] ; \exit004010E8 |> 53 push ebx004010E9 |. 8D8424 140100>lea eax, dword ptr [esp+114]004010F0 |. 68 04010000 push 104 ; /BufSize = 104 (260.)004010F5 |. 50 push eax ; |Buffer004010F6 |. FF15 10204000 call dword ptr [<&KERNEL32.GetWindows>; \GetWindowsDirectoryA004010FC |. BF 78304000 mov edi, 00403078 ; ASCII "\WINHLP32.EXE"00401101 |. 83C9 FF or ecx, FFFFFFFF00401104 |. 33C0 xor eax, eax00401106 |. 8D9424 140100>lea edx, dword ptr [esp+114]0040110D |. F2:AE repne scas byte ptr es:[edi]0040110F |. F7D1 not ecx00401111 |. 2BF9 sub edi, ecx00401113 |. 50 push eax ; /hTemplateFile => NULL00401114 |. 8BF7 mov esi, edi ; |00401116 |. 8BD9 mov ebx, ecx ; |00401118 |. 8BFA mov edi, edx ; |0040111A |. 83C9 FF or ecx, FFFFFFFF ; |0040111D |. F2:AE repne scas byte ptr es:[edi] ; |0040111F |. 8BCB mov ecx, ebx ; |00401121 |. 4F dec edi ; |00401122 |. C1E9 02 shr ecx, 2 ; |00401125 |. F3:A5 rep movs dword ptr es:[edi], dword p>; |00401127 |. 68 00000040 push 40000000 ; |Attributes = OVERLAPPED0040112C |. 8BCB mov ecx, ebx ; |0040112E |. 6A 03 push 3 ; |Mode = OPEN_EXISTING00401130 |. 50 push eax ; |pSecurity => NULL00401131 |. 83E1 03 and ecx, 3 ; |00401134 |. 6A 03 push 3 ; |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE00401136 |. 8D8424 280100>lea eax, dword ptr [esp+128] ; |0040113D |. 68 00000080 push 80000000 ; |Access = GENERIC_READ00401142 |. F3:A4 rep movs byte ptr es:[edi], byte ptr>; |00401144 |. 50 push eax ; |FileName00401145 |. FF15 0C204000 call dword ptr [<&KERNEL32.CreateFile>; \CreateFileA0040114B |. 83F8 FF cmp eax, -10040114E |. A3 94314000 mov dword ptr [403194], eax00401153 |. 5B pop ebx00401154 |. 75 22 jnz short 0040117800401156 |. 8D8C24 100100>lea ecx, dword ptr [esp+110]0040115D |. 51 push ecx ; /<%s>0040115E |. 68 64304000 push 00403064 ; |format = "Could not open %s",LF,""00401163 |. FF15 3C204000 call dword ptr [<&MSVCRTD.printf>] ; \printf00401169 |. 83C4 08 add esp, 80040116C |. 83C8 FF or eax, FFFFFFFF0040116F |. 5F pop edi00401170 |. 5E pop esi00401171 |. 81C4 0C020000 add esp, 20C00401177 |. C3 retn00401178 |> 33FF xor edi, edi0040117A |. 33F6 xor esi, esi0040117C |> 68 00020000 /push 20000401181 |. 56 |push esi00401182 |. 57 |push edi00401183 |. E8 E8000000 |call 0040127000401188 |. 83C4 0C |add esp, 0C0040118B |. 81C6 00400000 |add esi, 400000401191 |. 47 |inc edi00401192 |. 81FE 00400100 |cmp esi, 1400000401198 |.^ 72 E2 \jb short 0040117C0040119A |. 68 58304000 push 00403058 ; /format = "QUEUED!!",LF,""0040119F |. FF15 3C204000 call dword ptr [<&MSVCRTD.printf>] ; \printf004011A5 |. 8B15 90314000 mov edx, dword ptr [403190]004011AB |. 8B35 08204000 mov esi, dword ptr [<&KERNEL32.WaitF>; kernel32.WaitForSingleObjectEx004011B1 |. 83C4 04 add esp, 4004011B4 |. 6A 01 push 1 ; /fAlertable = TRUE004011B6 |. 6A FF push -1 ; |Timeout = INFINITE004011B8 |. 52 push edx ; |hObject => NULL004011B9 |. FFD6 call esi ; \WaitForSingleObjectEx004011BB |. 85C0 test eax, eax004011BD |. 74 17 je short 004011D6004011BF |> 3D C0000000 /cmp eax, 0C0004011C4 |. 75 28 |jnz short 004011EE004011C6 |. A1 90314000 |mov eax, dword ptr [403190]004011CB |. 6A 01 |push 1004011CD |. 6A FF |push -1004011CF |. 50 |push eax004011D0 |. FFD6 |call esi004011D2 |. 85C0 |test eax, eax004011D4 |.^ 75 E9 \jnz short 004011BF004011D6 |> 8B0D 94314000 mov ecx, dword ptr [403194]004011DC |. 51 push ecx ; /hObject => NULL004011DD |. FF15 04204000 call dword ptr [<&KERNEL32.CloseHandl>; \CloseHandle004011E3 |. 5F pop edi004011E4 |. 33C0 xor eax, eax004011E6 |. 5E pop esi004011E7 |. 81C4 0C020000 add esp, 20C004011ED |. C3 retn004011EE |> FF15 24204000 call dword ptr [<&KERNEL32.GetLastErr>; [GetLastError004011F4 |. 6A 00 push 0 ; /Arguments = NULL004011F6 |. 8D5424 0C lea edx, dword ptr [esp+C] ; |004011FA |. 6A 00 push 0 ; |BufSize = 0004011FC |. 52 push edx ; |Buffer004011FD |. 6A 00 push 0 ; |LanguageId = 0 (LANG_NEUTRAL)004011FF |. 50 push eax ; |MessageId00401200 |. 6A 00 push 0 ; |pSource = NULL00401202 |. 68 00110000 push 1100 ; |Flags = ALLOCATE_BUFFER|FROM_SYSTEM|000401207 |. FF15 20204000 call dword ptr [<&KERNEL32.FormatMess>; \FormatMessageA0040120D |. 8B4424 08 mov eax, dword ptr [esp+8]00401211 |. 8D4C24 10 lea ecx, dword ptr [esp+10]00401215 |. 50 push eax ; /<%s>00401216 |. 68 3C304000 push 0040303C ; |<%s> = "rc == WAIT_IO_COMPLETION"0040121B |. 68 CC304000 push 004030CC ; |<%s> = "IoByAPC.c"00401220 |. 6A 78 push 78 ; |<%d> = 78 (120.)00401222 |. 68 88304000 push 00403088 ; |Format = LF,"The following call failed at line %d in %s:",LF,LF," %s",LF,LF,"Reason: %s",LF,""00401227 |. 51 push ecx ; |s00401228 |. FF15 7C204000 call dword ptr [<&USER32.wsprintfA>] ; \wsprintfA0040122E |. 8D7C24 28 lea edi, dword ptr [esp+28]00401232 |. 83C9 FF or ecx, FFFFFFFF00401235 |. 33C0 xor eax, eax00401237 |. 83C4 18 add esp, 180040123A |. F2:AE repne scas byte ptr es:[edi]0040123C |. F7D1 not ecx0040123E |. 8D5424 0C lea edx, dword ptr [esp+C]00401242 |. 6A 00 push 0 ; /pOverlapped = NULL00401244 |. 49 dec ecx ; |00401245 |. 52 push edx ; |pBytesWritten00401246 |. 8D4424 18 lea eax, dword ptr [esp+18] ; |0040124A |. 51 push ecx ; |nBytesToWrite0040124B |. 50 push eax ; |Buffer0040124C |. 6A F4 push -0C ; |/DevType = STD_ERROR_HANDLE0040124E |. FF15 1C204000 call dword ptr [<&KERNEL32.GetStdHand>; |\GetStdHandle00401254 |. 50 push eax ; |hFile00401255 |. FF15 18204000 call dword ptr [<&KERNEL32.WriteFile>>; \WriteFile0040125B |. 68 B80B0000 push 0BB8 ; /Timeout = 3000. ms00401260 |. FF15 14204000 call dword ptr [<&KERNEL32.Sleep>] ; \Sleep00401266 |. 6A 01 push 1 ; /status = 100401268 |. FF15 40204000 call dword ptr [<&MSVCRTD.exit>] ; \exit0040126E |. 90 nop0040126F |. 90 nop00401270 |$ 53 push ebx00401271 |. 55 push ebp00401272 |. 56 push esi00401273 |. 57 push edi00401274 |. 8B7C24 14 mov edi, dword ptr [esp+14]00401278 |. 8B4C24 18 mov ecx, dword ptr [esp+18]0040127C |. 8B5C24 1C mov ebx, dword ptr [esp+1C]00401280 |. 8B2D 2C204000 mov ebp, dword ptr [<&KERNEL32.ReadF>; kernel32.ReadFileEx00401286 |. 8D04BF lea eax, dword ptr [edi+edi*4]00401289 |. 33F6 xor esi, esi0040128B |. C1E0 02 shl eax, 20040128E |. 89B8 B03B4000 mov dword ptr [eax+403BB0], edi00401294 |. 8988 A83B4000 mov dword ptr [eax+403BA8], ecx0040129A |. 8D90 A03B4000 lea edx, dword ptr [eax+403BA0]004012A0 |. 8BC7 mov eax, edi004012A2 |. C1E0 09 shl eax, 9004012A5 |. 895424 14 mov dword ptr [esp+14], edx004012A9 |. 8D88 A0314000 lea ecx, dword ptr [eax+4031A0]004012AF |. 894C24 18 mov dword ptr [esp+18], ecx004012B3 |> 8B5424 14 /mov edx, dword ptr [esp+14]004012B7 |. 8B4424 18 |mov eax, dword ptr [esp+18]004012BB |. 8B0D 94314000 |mov ecx, dword ptr [403194]004012C1 |. 68 00104000 |push 00401000004012C6 |. 52 |push edx004012C7 |. 53 |push ebx004012C8 |. 50 |push eax004012C9 |. 51 |push ecx004012CA |. FFD5 |call ebp004012CC |. 85C0 |test eax, eax004012CE |. 75 3D |jnz short 0040130D004012D0 |. FF15 24204000 |call dword ptr [<&KERNEL32.GetLastEr>; [GetLastError004012D6 |. 3D F8060000 |cmp eax, 6F8004012DB |. 74 0C |je short 004012E9004012DD |. 3D 18070000 |cmp eax, 718004012E2 |. 74 05 |je short 004012E9004012E4 |. 83F8 08 |cmp eax, 8004012E7 |. 75 0E |jnz short 004012F7004012E9 |> 6A 32 |push 32 ; /Timeout = 50. ms004012EB |. FF15 14204000 |call dword ptr [<&KERNEL32.Sleep>] ; \Sleep004012F1 |. 46 |inc esi004012F2 |. 83FE 05 |cmp esi, 5004012F5 |.^ 7C BC \jl short 004012B3004012F7 |> 68 34314000 push 00403134 ; /format = "ReadFileEx failed.",LF,""004012FC |. FF15 3C204000 call dword ptr [<&MSVCRTD.printf>] ; \printf00401302 |. 83C4 04 add esp, 400401305 |. 83C8 FF or eax, FFFFFFFF00401308 |. 5F pop edi00401309 |. 5E pop esi0040130A |. 5D pop ebp0040130B |. 5B pop ebx0040130C |. C3 retn0040130D |> 57 push edi ; /<%d>0040130E |. 68 0C314000 push 0040310C ; |format = "Read #%d queued for overlapped I/O.",LF,""00401313 |. FF15 3C204000 call dword ptr [<&MSVCRTD.printf>] ; \printf00401319 |. 83C4 08 add esp, 80040131C |. B8 01000000 mov eax, 100401321 |. 5F pop edi00401322 |. 5E pop esi00401323 |. 5D pop ebp00401324 |. 5B pop ebx00401325 \. C3 retn
routu
00401000 . 8B4424 08 mov eax, dword ptr [esp+8]00401004 . 8B5424 0C mov edx, dword ptr [esp+C]00401008 . 8B4C24 04 mov ecx, dword ptr [esp+4]0040100C . 50 push eax ; /<%d>0040100D . 8B42 10 mov eax, dword ptr [edx+10] ; |00401010 . 51 push ecx ; |<%d>00401011 . 50 push eax ; |<%d>00401012 . 68 10304000 push 00403010 ; |format = "Read #%d returned %d. %d bytes were read.",LF,""00401017 . FF15 3C204000 call dword ptr [<&MSVCRTD.printf>] ; \printf0040101D . A1 98314000 mov eax, dword ptr [403198]00401022 . 83C4 10 add esp, 1000401025 . 40 inc eax00401026 . 83F8 05 cmp eax, 500401029 . A3 98314000 mov dword ptr [403198], eax0040102E . 75 0D jnz short 0040103D00401030 . 8B0D 90314000 mov ecx, dword ptr [403190]00401036 . 51 push ecx ; /hEvent => NULL00401037 . FF15 00204000 call dword ptr [<&KERNEL32.SetEvent>] ; \SetEvent0040103D > C2 0C00 retn 0C
ida
转载于:https://www.cnblogs.com/nanshouyong326/archive/2010/07/09/1774396.html
