【Win32多线程】异步I/O技术(Overlapped I/O),避免使用多线程

Windows下串口通信编程详解 Windows API串口编程详解 文章目录 (一)Windows API串口通信编程概述 (二)Windows串口通信相关API函数 2.1打开和关闭串口 1.打开串口 CreateFile()函数声明如下: 2.关闭串口 CloseHandle函数声明如下: 2.2串口配置和串口属性 1.串口配置 GetCommState()函数声明如下: BuildCommDCB函数,函数声明如下: 2.缓冲区控制 PurgeComm()函数的声明如下: 2.3读写串口 1.读串口操作 ReadFile()函数声明如 阅读详情

讨论:1.激发的文件handles
      2.激发的event对象
      3.异步过程调用
      4.I/O completion ports(重要)适用于高负载服务器

----Win32文件操作函数
 
   win32中有上那个基本的函数用来执行I/O,他们是:
    CreateFile(),ReadFile(),WriteFile();
   没有哪个函数用来关闭文件,只要调用CloseHandle()即可。

CreateFile()可以用来打开各式各样的资源:包括文件,串口和并行口,Named pipes,Console.
它的原型如下:
HANDLE CreateFile(
  LPCTSTR lpFileName,                         // file name
  DWORD dwDesiredAccess,                      // access mode存取模式(读或写)
  DWORD dwShareMode,                          // share mode
  LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD
  DWORD dwCreationDisposition,                // how to create 如何产生
  DWORD dwFlagsAndAttributes,                 // file attributes 文件属性(使用overlapped I/O的关键)
  HANDLE hTemplateFile                        // handle to template file一个临时文件,将拥有全部的属性拷贝
);

C runtime library不能使用overlapped I/O.Overlapped I/O的基本型式是以ReadFile()和WriteFile()完成的。这两个函数的原型如下:
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指针,指向overlapped info
);

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  指针,指向overlapped info
);

这两个函数很像C runtime 函数的fread 和fwrite(),差别在于最后一个参数lpOverlapped.如果第六个参数设为
FILE_FLAG_OVERLAPPED,则必须在lpOverlapped参数中提供一个指针,指向一个OVERLAPPED结构。

---OVERLAPPED结构
它执行两个重要的功能,第一,它像一把钥匙,用以识别一个目前正在进行的overlapped操作。第二,它在你和系统之间提供了一个共享区域,参数可以在该区域中双向传递。
typedef struct _OVERLAPPED {
    ULONG_PTR  Internal;
    ULONG_PTR  InternalHigh;
    DWORD  Offset;
    DWORD  OffsetHigh;
    HANDLE hEvent;
} OVERLAPPED;

由于OVERLAPPED结构的生命周期超越ReadFile()和WriteFile()函数。所以把这个结构放在局部变量不是安全的。应该放在heap上。

---被激发的File Handles

最简单的overlapped I/O类型,就是使用它自己文件handle作为同步机制。
首先,用FILE_FLAG_OVERLAPPED告诉Win32你不要使用默认的同步I/O。然后设立一个OVERLAPPED结构,其中内含“I/O请求”的所有必要的参数,并以此来识别这个“ I/O请求”,直到它完成为止。接下来,调用ReadFile()并以OVERLAPPED结构的地址作为最后一个参数。这时候,Win32会在后台处理你的请求。你的程序可以干其他的事情了。

   如果需要等待overlapped I/O的执行结果,作为WaitForMultipleObjects()的一部分,在handle数组中加上这个文件的handle.文件handle是一个核心对象。一旦操作完毕即被激发。当完成操作之后,

调用GetOverlappedResult()确定结果如何。
BOOL GetOverlappedResult(
  HANDLE hFile,                       // handle to file, pipe, or device
  LPOVERLAPPED lpOverlapped,          // overlapped structure 一个指针,指向OVERLAPPED结构
  LPDWORD lpNumberOfBytesTransferred, // bytes transferred表示真正被传送的字节
  BOOL bWait                          // wait option是否表示要等待操作完成
);


文件读取示例:

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

//
// Constants
//
#define READ_SIZE       512

//
// Function prototypes
//
void CheckOsVersion();


int main()
{
    BOOL rc;
    HANDLE hFile;
    DWORD numread;
    OVERLAPPED overlap;
    char buf[READ_SIZE];
    char szPath[MAX_PATH];

    CheckOsVersion();

    GetWindowsDirectory(szPath, sizeof(szPath));
    strcat(szPath, "\\WINHLP32.EXE");
    // Open the file for overlapped reads
    hFile = CreateFile( szPath,
                    GENERIC_READ,
                    FILE_SHARE_READ|FILE_SHARE_WRITE,
                    NULL,
                    OPEN_EXISTING,
                    FILE_FLAG_OVERLAPPED,
                    NULL
                );
    if (hFile == INVALID_HANDLE_VALUE)
    {
        printf("Could not open %s\n", szPath);
        return -1;
    }

    // Initialize the OVERLAPPED structure
    memset(&overlap, 0, sizeof(overlap));
    overlap.Offset = 1500;

    // Request the data
    rc = ReadFile(
                hFile,
                buf,
                READ_SIZE,
                &numread,
                &overlap
            );
    printf("Issued read request\n");

    // Was the operation queued?
    if (rc)
    {
        // The data was read successfully
        printf("Request was returned immediately\n");
    }
    else
    {
        if (GetLastError() == ERROR_IO_PENDING)
        {
            // We could do something else for awhile here...

            printf("Request queued, waiting...\n");
            WaitForSingleObject(hFile, INFINITE);//这个调用其实是多余,因为GetOverlappedResult就可以等待                                                      overlapped操作的完

成。
            printf("Request completed.\n");

            rc = GetOverlappedResult(
                                    hFile,
                                    &overlap,
                                    &numread,
                                    FALSE
                                );
            printf("Result was %d\n", rc);
        }
        else
        {
   // We should check for memory and quota
   // errors here and retry. See the samples
   // IoByEvnt and IoByAPC.

            // Something went wrong
            printf("Error reading file\n");
        }
    }

    CloseHandle(hFile);

    return EXIT_SUCCESS;
}

//
// 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, "IoByFile must be run under Windows NT.\n");
  exit(EXIT_FAILURE);
    }

}


Q:Overlapped I/O总是异步的执行吗?
虽然你要求overlapped操作,但它并不一定就是overlapped。如果数据已经被放进cache中,或如果操作系统认为它可以很快速的取得那份数据,那么文件操作就会在ReadFile()返回之前完成。而ReadFile()将传回TRUE.这种情况下,文件handle处于激发状态,而对文件的操作可以视作就像overlapped一样。
  如果你要求一个文件操作为overlapped,而操作系统吧这个“操作请求”放到队列中等待执行,那么ReadFile()和WriteFile()都会传回FALSE表示失败。你必须调GetLastError()并确定它传回ERROR_IO_PENDING,那意味着“overlapped  I/O请求”被放进队列之中等待执行。GetLastError()也可能传回其他的值,例如ERROR_HANDLE_EOF,那么就代表一个错误。
OVERLAPPED结构体有能力处理64位的偏移值,因此面对巨大的文件也不怕。为了等待文件操作的完成,把文件的handle交给WaitForSingleObject().一旦overlapped操作完成,该文件的handle就会成为激发状态。

---被激发的Event对象
   用文件的handle作为激发机制,就没办法说出到底哪一个overlapped操作完成了。Win32有一个很好的解决办法。
OVERLAPPED结构中的最后一个栏位,是一个event handle.如果你使用文件handle作为激发对象,那么此栏设置为NULL.当使用event作为激发对象时,则赋值为event对象。系统核心会在overlapped操作

完成的时候,自动将此event对象给激发起来。由于每一个overlapped操作都有它自己独一无二的OVERLAPPED结构。所以每一个结构都有它独一无二的一个event对象,用来代表该操作。

Q:如何为overlapped I/O产生一个event对象?
你所使用的event对象必须是手动重置而非自动重置。如果使用自动重置,就有可能产生race condition,因为系统核心有可能在你有机会等待该event对象之前,先激发它。event对象的激发状态不能够保存的。于是这个event状态将遗失,而你的Wait...()函数永远不返回。但是一个手动重置的event,一旦激发,就一直处于激发状态。

 使用event对象搭配overlapped I/O,可以对同一个文件发出多个读取操作和多个写入操作,每一个操作有自己的event对象;然后在调用WaitForMultipleObjects()来等待其中之一完成。

使用Event和overlapped I/O实现文件读取示例:

/* Demonstrates how to use event objects instead of
 * file handles to signal multiple outstanding
 * overlapped operation 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
//
int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount);
void CheckOsVersion();


//
// Global variables
//

// Need to keep the events in their own array
// so we can wait on them.
HANDLE  ghEvents[MAX_REQUESTS];
// Keep track of each individual I/O operation
OVERLAPPED gOverlapped[MAX_REQUESTS];
// Handle to the file of interest.
HANDLE ghFile;
// Need a place to put all this data
char gBuffers[MAX_REQUESTS][READ_SIZE];


int main()
{
    int i;
    BOOL rc;
    char szPath[MAX_PATH];

    CheckOsVersion();

    GetWindowsDirectory(szPath, sizeof(szPath));
    strcat(szPath, "\\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;
    }

    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.
    MTVERIFY( WaitForMultipleObjects(
               MAX_REQUESTS, ghEvents, TRUE, INFINITE
        ) != WAIT_FAILED );

    // Describe what just happened.
    for (i=0; i<MAX_REQUESTS; i++)
    {
        DWORD dwNumread;

        rc = GetOverlappedResult(
                                ghFile,
                                &gOverlapped[i],
                                &dwNumread,
                                FALSE
                            );
        printf("Read #%d returned %d. %d bytes were read.\n",
                    i, rc, dwNumread);
        CloseHandle(gOverlapped[i].hEvent);
    }

    CloseHandle(ghFile);

    return EXIT_SUCCESS;
}


/*
 * Call ReadFile to start an overlapped request.
 * Make sure we handle errors that are recoverable.
 * Properly set up the event object for this operation.
 */
int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount)
{
    int i;
    BOOL rc;
    DWORD dwNumread;
    DWORD err;

    MTVERIFY(
        ghEvents[nIndex] = CreateEvent(
                     NULL,    // No security
                     TRUE,    // Manual reset - extremely important!
                     FALSE,   // Initially set Event to non-signaled state
                     NULL     // No name
                    )
    );
    gOverlapped[nIndex].hEvent = ghEvents[nIndex];
    gOverlapped[nIndex].Offset = dwLocation;

    for (i=0; i<MAX_TRY_COUNT; i++)
    {
        rc = ReadFile(
            ghFile,
            gBuffers[nIndex],
            dwAmount,
            &dwNumread,
            &gOverlapped[nIndex]
        );

        // Handle success
        if (rc)
        {
            printf("Read #%d completed immediately.\n", nIndex);
            return TRUE;
        }

        err = GetLastError();

        // Handle the error that isn't an error. rc is zero here.
        if (err == ERROR_IO_PENDING)
        {
            // asynchronous i/o is still in progress 
            printf("Read #%d queued for overlapped I/O.\n", nIndex);
            return TRUE;
        }

        // 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("ReadFile 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, "IoByEvnt must be run under Windows NT.\n");
  exit(EXIT_FAILURE);
    }

}

对于以Remote Access Service连接到一个服务器,现在可以记录这些操作过程,并做成overlapped I/O,然后在住消息循环中使用MsgWaitForMultipleObjects()以便在取得数据后有所反应。

-----------异步过程调用(Asynchronous Procedure Calls,APCs)
使用overlapped I/O配合event对象,会产生两个基础性问题。

第一,使用WaitForMultipleObjects(),你只能够等待最多MAXIMUM_WAIT_OBJECTS个对象。在Win32 SDK中,最大值为64。如果要等待64个以上的对象,就会出现问题。

第二,你必须不断根据“哪一个handle被激发”而计算如果反应。你必须分配表格和WaitForMultipleObjects()的handles数组结合起来。以上两个问题可以用异步过程调用来解决。
  只要使用“Ex”版本的ReadFile()和WriteFile(),就可以调用这个机制。这两个函数允许你指定一个额外的参数,是一个callback函数地址。当一个overlapped I/O完成时,系统应该调用该callback函数。这个callback函数称为I/O completion routine.

Q:一个I/O completion routine何时被调用?
  你的线程必须在所谓"alertable"状态下才行。如果线程不处于“alertable”状态,那么对I/O completion routine的调用会暂时被保存下来。因此,当一个线程终于进入“alertable”状态时,可能已经有一大堆储备的APCs等待被处理。

  如果线程因为下面五个函数处于等待状态,其“alertable”标记被设为TRUE,则该线程就是处于"alertable"状态:
  SleepEx(),WaitForSingleObjectEx();WaitForMultipleObjectsEx(),MsgWaitForMultipleObjectsEx();
SignalObjectAndWait();
只有在程序处于“alertable”状态下,APCs才会被调用。

I/O completion routine的形式:
VOID CALLBACK FileIOCompletionRoutine(
  DWORD dwErrorCode,                // completion code 0表示操作完成,ERROR_HANDLE_EOF表示操作已经到文件尾                                                  端。
  DWORD dwNumberOfBytesTransfered,  // number of bytes transferred真正被传输的字节数
  LPOVERLAPPED lpOverlapped         // I/O information buffer
);

 

Q:如何把一个用户自定义的数据传递给I/O completion routine?
使用APCs时,OVERLAPPED机构体重的hEvent位不需要用来放置一个event handle.hEvent栏位可以由程序员自由使用。最大的用途就是:首先配置一个结构,描述数据来自哪里,或是要对数据进行一些什么操作,然后将hEvent栏位设定为指向该结构。


overlapped I/O与APCs的应用示例:

/* 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 finished
HANDLE  ghEvent;
// Keep track of each individual I/O operation
OVERLAPPED gOverlapped[MAX_REQUESTS];
// Handle to the file of interest.
HANDLE ghFile;
// Need a place to put all this data
char 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, "\\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);
    }

}


Q:如何把C++成员函数当做一个 I/O completion routine?
  一个C++成员函数不能拿来做一个I/O completion routine,除非它是static函数。如果它是static函数,它就没有this指针,也就不能直接调用那些需要this 指针的成员函数。
解决的方法是存储一个指针,指向用户自定义数据,然后经由此指针调用一个C++成员函数。由于static成员函数是类的一部分,还是可以调用private成员函数。与如何把C++成员函数当做一个线程函数类似。

另外一个I/O completion ports非常重要,对产生高效率的服务器很受欢迎,这里略,详细参考相关文献资料。

Overlapped模型深入分析(原理篇)   Overlapped I/O模型深入分析简述:     Overlapped I/O也称Asynchronous  I/O,异步I/O模型。异步I/O和同步I/O不同,同步I/O时,程序被挂起,一直到I/O处理完,程序才能获得控制。异步I/O,调用一个函数告诉OS,进行I/O操作,不等I/O结束就立即返回,继续程序执行,操作系统完成I/O之后,通知消息给你。Overlapped I 阅读详情

相关推荐

IOCP---完成端口(CompletionPort)

假若—个应用程序同时需要管理为数众多的套接字,那么“完成端口”模型。往往可以达到最佳的系统性能,然而不幸的是,该模型只适用于以下操作系统(微软的):Windows NT和Windows 2000操作系统。因其设计的复杂性,只有在应用程序需要同时管理数百乃至上千个套接字的时候、而且希望随着系统内安装的CPU数量的增多、应用程序的性能也可以线性提升,才应考虑采用“完成端口”模型。要记住的一个基本准则是...

y果子 880

OVERLAPPED 与 FILE_FLAG_OVERLAPPED

OVERLAPPED 与 FILE_FLAG_OVERLAPPEDoverlapped I/O Overlapped介绍利用win32所谓的overlapped I/O特征,可以并行处理I/O操作,并且当任何一个I/O完成时,你的程序会收到一个通告。其它操作系统把这个特征称为nonblockeingI/O或者asynchronous I/O。Overlapped I/O是win32的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这项技术使你的程序在I/O进行中仍然能够继续处理事物。Ove

6580

《Win32多线程程序设计》(12)---overlapped I/O

文字版电子书-----请点击这里 overlapped I/O  是Win32 的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这项技术使你的程序在I/O 进行过程中仍然能够继续处理事务。 i 激发的文件handles i 激发的event  对象 i 异步过程调用(Asynchronous Procedure Calls,APCs) i I/O comple

一零一六的博客专栏 1196

重叠IO overlapped I/O 运用详解

I/O设备处理必然让主程序停下来干等I/O的完成, 对这个问题有 方法一:使用另一个线程进行I/O。这个方案可行,但是麻烦。 即 CreateThread(…………);创建一个子线程做其他事情。 Readfile(^…………);阻塞方式读数据。 方法二:使用overlapped I/O。 overlapped I/O是WIN32的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这项技术使你的程序在I/O进行过程中仍然能够继续处理事务。事实上,操作系统

qq_38883139的博客 844

深入Windows RS232串口编程:从API原理到异步I/O实战

串口通信作为嵌入式、工控和仪器仪表领域的基础通讯方式,其核心在于实现设备间的可靠数据交换。其工作原理基于异步串行传输协议,通过配置波特率、数据位和校验位等参数确保数据准确收发。掌握底层串口编程技术,对于开发高可靠性的数据采集、设备控制和工业自动化系统具有重要价值。在实际应用中,开发者常需处理二进制数据帧、超时机制和复杂的硬件握手信号。本文聚焦于Windows平台,通过解析CreateFile、ReadFile、WriteFile等核心API,并深入探讨异步重叠I/O(Overlapped I/O)模式,指导

weixin_30764771的博客 508

揭秘C#异步背后:Overlapped如何精准定位你的Task?

摘要: 本文深入剖析了C#异步IO中Overlapped寻址机制的核心原理。作者通过首次使用FileStream.ReadAsync时遇到的Task"消失"问题,引出对Windows API中OVERLAPPED结构体的探讨。文章详细解析了NativeOverlapped作为Win32与C#桥梁的关键作用,揭示了ThreadPoolBoundHandleOverlapped如何通过EventHandle字段关联Task对象。通过伪代码和源码分析,阐述了从Win32回调到C# Task完成

墨夶的博客 786

设备I/O之OVERLAPPED

OVERLAPPED,顾名思义为重叠,乍一看会很奇怪,重叠?谁跟谁重叠?似乎在WIN32的Programming中没有这个概念呀?要讨论这个问题就要追溯到对设备I/O的访问中  在WIN32中,用户不能象以前那样直接对硬件进行访问,使得这一层对开发者而言是个"黑盒",而是提供了一组对应的API的接口.让开发者基于提供的接口进行开发,而把低层的访问交给了Driver或者内核.  在WIN32中,设备

龙虾的博客 2978

shopro 商城,2025年新申请的微信支付提示失败,支付提示 Get Wechat Public Cert Error 问题的修复办法

shopro 商城,最近新申请的微信支付商户 支付提示 Get Wechat Public Cert Error 问题的修复办法

行走的卡路里 1244

Overlapped I/O模型深度解析:从理论到实践实现

为了克服传统阻塞I/O的瓶颈,overlapped I/O作为一种异步I/O技术应运而生。它允许I/O操作在后台进行,而不阻塞调用线程。应用程序可以继续执行其他任务,直到I/O操作完成。

和舒貌的博客 1253

SageMath下载与安装

SageMath的下载与安装

旺旺的碎冰冰~的博客 7491

U8-固定资产月末结账报错:BOF或EOF中有一个是真

度了下,发现此问题一般是由于fa_Vtsobject表缺少对应月份的记录导致,补上即可,但是查看发现此表记录正常。 跟踪后发现定位到以下语句: select * from AccInformation where cSysID = N'FA' and cName =N'bVoucherApply'上述语句执行后没有任何记录显示,但是在正常的账套执行是有记录的,那有可能就是记录丢失导致,执行以下

guizhouakun的博客 5916

Win 32 多线程程序设计学习笔记之六:异步I/O(Overlapped I/O)

某些时候 overlapped I/O 可以取代多线程的功用。然而,overlapped I/O 加上completion ports,常被设计为多线程处理,以便在一个“受制于 I/O 的程序”(所谓 I/O bound 程序)中获得高效率。         overlapped I/O 是 Win32 的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这项技术使你的程序在I/

1541

SCS 43. 利用Scissor算法从单细胞数据中挖掘临床表型关联的细胞亚群

本文详细介绍了Scissor算法在单细胞转录组数据分析中的应用,该算法能够精准挖掘与临床表型关联的细胞亚群。通过建立单细胞RNA测序数据与临床预测模型的直接关联,Scissor避免了传统聚类方法的局限性,为疾病机制研究和个性化医疗提供了新工具。文章还涵盖了数据预处理、模型选择、结果验证等实战技巧。

weixin_28736335的博客 490

设备I/O之OVERLAPPED(zz)

设备I/O之OVERLAPPEDOVERLAPPED,顾名思义为重叠,乍一看会很奇怪,重叠?谁跟谁重叠?似乎在WIN32的Programming中没有这个概念呀?要讨论这个问题就要追溯到对设备I/O的访问中  在WIN32中,用户不能象以前那样直接对硬件进行访问,使得这一层对开发者而言是个"黑盒",而是提供了一组对应的API的接口.让开发者基于提供的接口进行开发,而把低层的访问交给了Dri

xiaoxiongli的专栏 791

把 ABAP 接到外部世界的几条路, 从 Web Service 到 RFC、BAPI 与 IDoc 的完整理解

摘要: ABAP 的连接能力是其长期成为企业核心的关键,不仅支持通用协议(HTTP、SOAP、XML),还保留了 SAP 特有的技术(RFC、BAPI、IDoc)。Web Service 是跨系统通信的主轴,依赖 SOAP/WSDL 实现契约化协作,而 Enterprise Service 更强调业务语义的复用与治理。经典技术如 RFC 和 BAPI 因高效稳定仍广泛使用,尤其适合紧耦合场景。ABAP 通过分层工具箱(如代理生成、服务注册)实现灵活集成,平衡新旧技术,满足多样化的企业连接需求。 (字数:15

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 138

【Bluetooth蓝牙开发】九、BLE协议之GATT

1、开篇词 2、蓝牙开发入门 3、蓝牙协议栈总览 4、蓝牙协议栈——物理层 5、蓝牙协议栈——链路层 6、蓝牙协议栈——传输层 7、蓝牙协议栈——L2CAP协议 8、蓝牙协议栈——ATT协议 9、蓝牙协议栈——GATT协议 10、蓝牙通信流程分析 11、蓝牙协议栈——Bluez交叉编译 12、蓝牙调试工具汇总

Donge's Blog 4760

Win32多线程 -- 异步IO(overlapped IO)

一. 异步(overlapped) IO之被激发的File Handle 1.1Win32 IO操作函数 Win32 之中有三个基本的函数用来执行 I/O CreateFile() ReadFile() WriteFile() 没有另外哪一个函数用来关闭文件,只要调用 CloseHandle 即可。 CreateFile 可以用来打开各式各样的资源,包括(但不限制于): -> 文件(硬盘、软盘、光盘或其他) -> 串行口和并行口(serial a...

cfz751740465的博客 1826

AUTOSAR从入门到精通-【应用实战篇】车载HMI-ADAS

ADAS是高级驾驶辅助系统(Advanced Driving Assistance System)简称ADAS。ADAS高级驾驶辅助系统是利用安装于车上的各式各样的传感器, 在第一时间收集车内外的环境数据, 进行静、动态物体的辨识、侦测与追踪等技术上的处理, 从而能够让驾驶者在最快的时间察觉可能发生的危险, 以引起注意和提高安全性的主动安全技术。

lin_xiu的博客 1434

Windows Overlapped I/O 操作

详细说明:该函数检测指定的对象的当前状态,若为nonsignaled则调用者线程将处于等待状态,在此状态下消耗少量的处理器时间直到对象状态改变为signaled或超时。bWaitAll参数如果为TRUE,则只有当等待的所有内核对象为已通知状态时函数才返回,如果为FALSE,则只要一个内核对象为已通知状态,则该函数返回。第二个参数指明了需要等待的时间(毫秒),可以传递INFINITE指明要无限期等待下去,如果第二个参数为0,那么函数就测试同步对象的状态并立即返回。如果该函数失败,返回WAIT_FAILED。

phenixyf的专栏 679

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Windows Overlapped I/O 应用 实例操作详解

overlapped I/O是WIN32的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。事实上,操作系统内部正是以线程来I/O完成overlapped I/O。2:调用WaitForMultipleObjects(MAX_REQUESTS, ghEvents, TRUE, INFINITE) 当任何一个用户的读操作完成时,函数停止阻塞。使用另一个线程进行I/O。如果采用 overlapped,那么ReadFile()、WriteFile()的第5个参数必须提供一个指针,

phenixyf的专栏 1088

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

串口之OVERLAPPED结构体详解

typedef struct _OVERLAPPED {    DWORD Internal;    DWORD InternalHigh;    DWORD Offset;    DWORD OffsetHigh;   HANDLE hEvent; } OVERLAPPED Internal: 预留给操作系统使用。它指定一个独立于系统的状态,当GetOverlappedResul

一蓑烟雨任平生 也无风雨也无晴 9949

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

关于OVERLAPPED之用法

<br />http://blog.youkuaiyun.com/yuanjing810324/archive/2010/05/12/5583794.aspx<br /><br /><br /><br />OVERLAPPED,顾名思义为重叠,乍一看会很奇怪,重叠?谁跟谁重叠?<br />似乎在WIN32的Programming中没有这个概念呀?要讨论这个问题就要追溯<br />到对设备I/O的访问中  在WIN32中,用户不能象以前那样直接对硬件进行访问,使得这一层<br />对开发者而言是个"黑盒",而是提供了一组

weibojishu1984的专栏 1175
上一篇: 【Win32多线程】如何初始化一个新线程,停止一个执行中的线程,调整线程优先权?
下一篇: 【win32多线程】数据的一致性问题,即多个线程读写数据问题
xiaoding133
博客等级 码龄19年 415粉丝 159原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值