windows 异步 IO

来源:互联网 发布:java汽车租赁题 编辑:程序博客网 时间:2024/05/24 06:35

同步 IO:线程存在 IO 操作的时候,他会等待IO 操作完成之后才会继续执行后续操作,此时线程会被挂起,知道 IO 完成,线程才可以重新调度。

异步 IO:IO 的操作在后台进行,并不阻塞线程的继续运行,IO 的操作和线程运行同时进行。


同步 IO 由于线程的挂起,运行 发生大量的上下文切换,导致程序的性能降低。

如何选择同步还是异步呢? 
主要有这么几个指标供参考 
1. 并发数量 
2. 接收字节数 
3. 处理请求所需CPU时间 

并发数 
并发低的时候同步IO与异步IO差别不大 
并发高时差别会比较明显,这要表现在 
1. 开启线程数:如并发1000时,同步IO要开启1000个线程,1000个线程要占用很多内存,这是其一,其二1000个线程间切换的时间也是很可观的;异     步IO则可避免这个问题 

接收字节数 
接收字节越少被阻塞的概率越低,同步IO与异步IO的差别就越小 
接收字节越多被阻塞的概率就越大,异步IO的优势越明显,能够同时服务更多的客户端请求 

处理请求所需CPU时间 

同步阻塞IO 
服务端在调用read()时,如果网卡缓冲区中没有数据则程序停止向下执行,直到网卡缓冲区中有数据。

同步的非阻塞IO是这样的 
服务端调用read()后,网卡缓冲区中如果没有数据可读就返回 ,服务器采用循环的方式再去读取 

    可以看出CPU大部分被浪费了 

异步非阻塞IO 
服务端调用read()方法,若网卡缓冲区中无数据则返回,程序继续向下执行。当缓冲区中有数据时,系统会通知应用程序。 

windows 中异步 IO,其中一种方法就是 CreateFile 创建设备是设定 FILE_FLAG_OVERLAPPED 风格。

使用 ReadFile 读文件,和 WriteFile 写文件的时候都要 使用 OVERLAPPED 结构体。

OVERLAPPED 结构中有些成员都需要我们初始化。


ypedef struct _OVERLAPPED {  ULONG_PTR Internal;  ULONG_PTR InternalHigh;  union {    struct {      DWORD Offset;      DWORD OffsetHigh;    };    PVOID  Pointer;  };  HANDLE    hEvent;} OVERLAPPED, *LPOVERLAPPED;

offset 和 offsetHigh  指定我们从哪里开始 IO 操作。

hEvent 事件句柄,初始化为 无信号,IO 操作完成之后 系统会设置为有信号。如果我们调用 GetOverlappedResult 函数之后,hEvent 会被设置为无信号。

HANDLE hread = CreateFile(TEXT("D:\\readme.txt"), GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);if(hread == INVALID_HANDLE_VALUE){printf("CreateFile failed %lu\n", GetLastError());return 1;}HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);OVERLAPPED oap;oap.hEvent = hEvent;oap.Offset = 0;oap.OffsetHigh = 0;DWORD _bytes = 0;while(1){UINT8 buffer[MAX_PATH + 1] = {0};if(!ReadFile(hread, buffer, MAX_PATH , NULL, &oap)){if(GetLastError() == ERROR_IO_PENDING){if(!GetOverlappedResult(hread, &oap, &_bytes, TRUE)){printf("failed %lu\n", GetLastError());return ;}if(_bytes == 0)return ;oap.Offset += _bytes;}else{printf("failed %lu\n", GetLastError());}}}





0 0
原创粉丝点击