博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IO完成端口
阅读量:5895 次
发布时间:2019-06-19

本文共 5188 字,大约阅读时间需要 17 分钟。

 

学习IO完成端口,最好的例子是Detours中的模块syelog,它为了高效地接收多个来源的log,创建了IO完成端口以及线程池,线程池中的线程数目为当前processor数目的8倍。

BOOL CreateWorkers(HANDLE hCompletionPort){    DWORD dwThread;    HANDLE hThread;    DWORD i;    SYSTEM_INFO SystemInfo;    GetSystemInfo(&SystemInfo);    for (i = 0; i < 2 * SystemInfo.dwNumberOfProcessors; i++) {        hThread = CreateThread(NULL, 0, WorkerThread, hCompletionPort, 0, &dwThread);        if (!hThread) {            MyErrExit("CreateThread WorkerThread");            // Unreachable: return FALSE;        }        CloseHandle(hThread);    }    return TRUE;}

  

然后创建pipe文件,并且将pipe文件与IO完成端口绑定到一起,当其他线程(进程)向该pipe文件写数据时,会通过异步方式写,

VOID SyelogExV(BOOL fTerminate, BYTE nSeverity, PCSTR pszMsgf, va_list args){    SYELOG_MESSAGE Message;    DWORD cbWritten = 0;    Real_GetSystemTimeAsFileTime(&Message.ftOccurance);    Message.fTerminate = fTerminate;    Message.nFacility = s_nFacility;    Message.nSeverity = nSeverity;    Message.nProcessId = s_nProcessId;    PCHAR pszBuf = Message.szMessage;    PCHAR pszEnd = Message.szMessage + ARRAYSIZE(Message.szMessage) - 1;    if (s_szIdent[0]) {        pszBuf = do_str(pszBuf, pszEnd, s_szIdent);    }    *pszEnd = '\0';    VSafePrintf(pszMsgf, args,                pszBuf, (int)(Message.szMessage + sizeof(Message.szMessage) - 1 - pszBuf));    pszEnd = Message.szMessage;    for (; *pszEnd; pszEnd++) {        // no internal contents.    }    // Insure that the message always ends with a '\n'    //    if (pszEnd > Message.szMessage) {        if (pszEnd[-1] != '\n') {            *pszEnd++ = '\n';            *pszEnd++ = '\0';        }        else {            *pszEnd++ = '\0';        }    }    else {        *pszEnd++ = '\n';        *pszEnd++ = '\0';    }    Message.nBytes = (USHORT)(pszEnd - ((PCSTR)&Message));    Real_EnterCriticalSection(&s_csPipe);    if (syelogIsOpen(&Message.ftOccurance)) {        if (!Real_WriteFile(s_hPipe, &Message, Message.nBytes, &cbWritten, NULL)) {            s_nPipeError = GetLastError();            if (s_nPipeError == ERROR_BAD_IMPERSONATION_LEVEL) {                // Don't close the file just for a temporary impersonation level.            }            else {                if (s_hPipe != INVALID_HANDLE_VALUE) {                    Real_CloseHandle(s_hPipe);                    s_hPipe = INVALID_HANDLE_VALUE;                }                if (syelogIsOpen(&Message.ftOccurance)) {                    Real_WriteFile(s_hPipe, &Message, Message.nBytes, &cbWritten, NULL);                }            }        }    }    Real_LeaveCriticalSection(&s_csPipe);}

  

如果写操作完成,会使正在等待的线程池中的一个线程结束对GetQueuedCompletionStatus的等待

DWORD WINAPI WorkerThread(LPVOID pvVoid){    PCLIENT pClient;    BOOL b;    LPOVERLAPPED lpo;    DWORD nBytes;    HANDLE hCompletionPort = (HANDLE)pvVoid;    for (BOOL fKeepLooping = TRUE; fKeepLooping;) {        pClient = NULL;        lpo = NULL;        nBytes = 0;        b = GetQueuedCompletionStatus(hCompletionPort,                                      &nBytes, (PULONG_PTR)&pClient, &lpo, INFINITE);        if (!b || lpo == NULL) {            fKeepLooping = FALSE;            MyErrExit("GetQueuedCompletionState");            break;        }        else if (!b) {            if (pClient) {                if (GetLastError() == ERROR_BROKEN_PIPE) {                    LogMessageV(SYELOG_SEVERITY_INFORMATION, "Client closed pipe.");                }                else {                    LogMessageV(SYELOG_SEVERITY_ERROR,                                "GetQueuedCompletionStatus failed %d [%p]",                                GetLastError(), pClient);                }                CloseConnection(pClient);            }            continue;        }        if (pClient->fAwaitingAccept) {            InterlockedIncrement(&s_nActiveClients);            pClient->fAwaitingAccept = FALSE;            b = ReadFile(pClient->hPipe,                         &pClient->Message,                         sizeof(pClient->Message),                         &nBytes,                         pClient);            if (!b) {                if (GetLastError() != ERROR_IO_PENDING) {                    LogMessageV(SYELOG_SEVERITY_ERROR,                                "ReadFile failed %d.", GetLastError());                    continue;                }            }            CreatePipeConnection(hCompletionPort);        }        else {            if (nBytes < offsetof(SYELOG_MESSAGE, szMessage)) {                CloseConnection(pClient);            }            if (pClient->Message.fTerminate) {                LogMessageV(SYELOG_SEVERITY_NOTICE,                            "Client requested terminate on next connection close.");                s_fExitAfterOne = TRUE;            }            LogMessage(&pClient->Message, nBytes);            b = ReadFile(pClient->hPipe,                         &pClient->Message,                         sizeof(pClient->Message),                         &nBytes,                         pClient);            if (!b && GetLastError() == ERROR_BROKEN_PIPE) {                CloseConnection(pClient);            }        }    }    return 0;}

并且将写的结果通过Overlapped结构体传递给该线程,从而向log文件中添加内容。

 

转载于:https://www.cnblogs.com/long123king/p/3977618.html

你可能感兴趣的文章
接口测试框架(一)
查看>>
CDI Event解析
查看>>
Wiggle SortII
查看>>
LeetCode 218: The Skyline Problem
查看>>
Codeforces 582B Once Again
查看>>
JVM加载class文件的原理机制
查看>>
struts2 上传文件 parseRequest()解析request为空 解决办法
查看>>
template.helper 多参数
查看>>
多继承时的构造函数调用的顺序
查看>>
RadioButton布局图片+文字 实现tabhost效果
查看>>
2.22考试
查看>>
[HEOI2012]采花
查看>>
C#中应用程序的垃圾回收器管理和内存的分配与释放
查看>>
C# Newtonsoft.Json不序列字段
查看>>
HDU 4336 Card Collector
查看>>
实验3
查看>>
MVC分页更有效率
查看>>
access中设置不等于
查看>>
hdu 1221 Rectangle and Circle
查看>>
Android 四大组件之四(ContentProvider)
查看>>