日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程笔记5

發布時間:2023/12/2 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程笔记5 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第六章:Overlapped I/O,在你身后變戲法

1.overlapped I/O 是 Win32 的一項技術,你可以要求操作系統為你傳送數據,并且在傳送完畢時通知你。這項技術使你的程序在I/O 進行過程中仍然能夠繼續處理事務。事實上,操作系統內部正是以線程來完成 overlapped I/O。

2.Win32文件操作函數

(1)CreateFile()可以用來打開文件、串行口和并行口、Named pipes、Console。

HANDLE CreateFile(
LPCTSTR lpFileName, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 指向文件名稱
DWORD dwDesiredAccess, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 存取模式(讀或寫)
DWORD dwShareMode, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 共享模式(share mode)
LPSECURITY_ATTRIBUTES lpSecurityAttributes, ?// 指向安全屬性結構
DWORD dwCreationDisposition, ? ? ? ? ? ? ? ? ? ? ? ? ?// 如何產生
DWORD dwFlagsAndAttributes, ? ? ? ? ? ? ? ? ? ? ? ? ?// 文件屬性
HANDLE hTemplateFile ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// 一個臨時文件,將擁有全部的屬性拷貝
);

注:overlapped I/O性質:可以在同一時間讀寫文件的許多部分;多個overlapped請求,執行次序無法保證;overlapped I/O的基本型式是以ReadFile()和WriteFile()完成的。

(2)ReadFile()

BOOL ReadFile(
HANDLE hFile, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 欲讀之文件
LPVOID lpBuffer, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 接收數據之緩沖區
DWORD nNumberOfBytesToRead, ? ? ? ? // 欲讀取的字節個數
LPDWORD lpNumberOfBytesRead, ? ? ? ?// 實際讀取的字節個數的地址
LPOVERLAPPED lpOverlapped ? ? ? ? ? ? ? // 指針,指向 overlapped info
);

(3)WriteFile()

BOOL WriteFile(
HANDLE hFile, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 欲寫之文件
LPCVOID lpBuffer, ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 儲存數據之緩沖區
DWORD nNumberOfBytesToWrite, ? ? ? // 欲寫入的字節個數
LPDWORD lpNumberOfBytesWritten, ? // 實際寫入的字節個數的地址
LPOVERLAPPED lpOverlapped ? ? ? ? ? ? // 指針,指向 overlapped info
);

如果CreateFile() 的第6個參數被指定為FILE_FLAG_ OVERLAPPED,就必須在上述的 lpOverlapped 參數中提供一個指針,指向一個 OVERLAPPED 結構。

(4)OVERLAPPED結構

typedef struct _OVERLAPPED {
DWORD Internal; ? ? ? ?//通常保留。當GetOverlappedResult傳回False,并且GetLastError并非傳回ERROR_IO_PENDING,則內含一個視系統而定的狀態。
DWORD InternalHigh; //通常被保留,當GetOverlappedResult傳回True,則內含“被傳輸數據的長度”
DWORD Offset; ? ? ? ? ?//讀、寫偏移位置,從文件頭開始算起。若目標設備不支持文件位置,忽略
DWORD OffsetHigh; ? //64位文件偏移中較高32位。若目標設備不支持文件位置,忽略
HANDLE hEvent; ? ? ? //manual reset event,overlapped I/O完成時被激發。ReadFileEX,WriteFileEX忽略這個欄位,彼時被用來傳遞一個用戶自定義的指針。
} OVERLAPPED, *LPOVERLAPPED;

OVERLAPPED 結構執行兩個重要的功能。第一,它像一把鑰匙,用以識別每一個目前正在進行的 overlapped 操作。第二,它在你和系統之間提供了一個共享區域,參數可以在該區域中雙向傳遞。

通常overlapped結構存放在heap中。

3.被激發的File Handles

(1)異步IO的步驟:CreateFile指定FILE_FLAG_OVERLAPPED;設立一個OVERLAPPED結構,調用ReadFile、WriteFile帶上這個參數。

(2)文件handle是一個核心對象,一旦操作完畢即被激發。

(3)GetOverlappedResult()

BOOL GetOverlappedResult(
HANDLE hFile, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//文件設備的handle
LPOVERLAPPED lpOverlapped, ? ? ? ? ? ? ? ? //一個指針,指向overlapped結構
LPDWORD lpNumberOfBytesTransferred, ?//一個指針,指向DWORD,保存真正被傳輸的字節數。
BOOL bWait ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//是否要等待操作完成,TRUE表示等待。
);

(4)雖然你要求一個overlapped 操作,但它并不一定就是 overlapped!如果數據已經被放進 cache中,或如果操作系統認為它可以很快速地取得那份數據,那么文件操作就會在ReadFile() 返回之前完成,而 ReadFile() 將傳回 TRUE。

(5)一個文件操作為 overlapped,而操作系統把“操作請求”放到隊列中等待執行, ReadFile() 和、WriteFile()都會傳回 FALSE 以示失敗。這個行為并不是很直觀, 你必須調用GetLastError() 并確定它傳回 ERROR_IO_PENDING,那意味著“overlappedI/O 請求”被放進隊列之中等待執行。GetLastError() 也可能傳回其他的值,例如 ERROR_HANDLE_EOF,那就真正代表一個錯誤了。

4.被激發的event對象

(1)所使用的 event 對象必須是手動重置(manual-reset)而非自動重置(auto-reset)。

(2)IOBYEVENT例子。

5.異步過程調用(Asynchronous Procedure Calls,APCs)

(1)使用overlapped I/O與event搭配的兩個問題:

<1>WaitForMultipleObjects最多等待64個對象。

<2>必須不斷的根據“哪一個handle被激發”而計算如何反應。

(2)使用Ex版的ReadFile和WriteFile,可以使用異步過程調用機制。只有當線程處于alertable狀態時,APCs才會被調用。當線程因為以下5個函數而處于等待狀態,且線程的“alertable”標記被設為TRUE,則線程處于alertable狀態:

SleepEx()

WaitForSingleObjectEx()

WaitForMultipleObjectEx()

MsgWaitForMultipleObjectsEx()

SignalObjectAndWait();

(3)用于 overlapped I/O 的 APCs 是一種所謂的 user mode APCs。WindowsNT 另有一種所謂的 kernel mode APCs。Kernel mode APCs 也會像 usermode APCs 一樣被保存起來,但一個 kernel mode APC 一定會在下一個timeslice 被調用,不管線程當時正在做什么。 Kernel mode APCs 用來處理系統機能,不在應用程序的控制之中。

(4)提供的 I/O completion routine 應該有這樣的型式:

VOID WINAPI FileIOCompletionRoutine(
DWORD dwErrorCode, ? //0表示操作完成,ERROR_HANDLE_EOF表示操作已經到了文件尾端。
DWORD dwNumberOfBytesTransferred,//真正被傳輸的數據字節數
LPOVERLAPPED lpOverlapped//指向overlapped結構,此結構由開啟overlapped I/O操作的函數提供
);

(5)使用 APCs 時,OVERLAPPED 結構中的 hEvent 欄位不需要用來放置一個 event handle。Win32 文件上說此時 hEvent 欄位可以由程序員自由運用。那么最大的用途就是:首先配置一個結構,描述數據來自哪里,或是要對數據進行一些什么操作,然后將 hEvent 欄位設定指向該結構

(6)在C++ 中產生一個I/O Completion Routines:儲存一個指針,指向用戶自定義數據(一個對象),然后經由此指針調用一個 C++ 成員函數。由于 static 成員函數是類的一部分,你還是可以調用 private 成員函數。

6.對文件進行overlapped I/O的缺點

(1)似乎 Windows NT 是以“I/O 請求”的大小來決定要不要將此請求先記錄下來。所以對于數據量小的操作,overlapped I/O的效率反而更低。

(2)解決辦法:以少量的線程負責所有的硬盤 I/O,然后把這些線程的I/O 請求,保持在一個隊列之中。這種效率比較高。

(3)有兩種情況,overlapped I/O 總是同步執行,甚至即使 FILE_FLAG_NO_BUFFERING 已經指定。第一種情況是你進行一個寫入操作而造成文件的擴展。第二種情況是你讀寫一個壓縮文件。

7.I/O Completion Ports

(1)APCs的缺點:最大的問題就是,有好幾個 I/O APIs 并不支持 APCs,如listen() 和 WaitCommEvent() 便是兩個例子。APCs 的另一個問題是,只有發出“overlapped 請求”的那個線程才能夠提供 callback 函數,然而在一個“scalable”(譯注)系統中,最好任何線程都能夠服務 events。

(2)產生一個I/O Completion Port

HANDLE CreateIoCompletionPort(
HANDLE FileHandle, ? ? ? ? ? ? ? ? ? ? ? ?//文件或設備的handle,若為INVALID_HANDLE_VALUE,則產生一個沒有和任何handle關聯的port。
HANDLE ExistingCompletionPort, ? ? ?//若此欄位被指定,則FileHandle被加到此port上。指定Null產生一個新的port。
DWORD CompletionKey, ? ? ? ? ? ? ? ? ?//用戶自定義的一個數值,將被交給提供服務的線程。此值和FileHanlde有關聯。
DWORD NumberOfConcurrentThreads//與此I/O completion port 有關聯的線程個數。
);

(3)與一個文件handle產生關聯

  再次使用CreateIoCompletionPort接口。

(4)在一個I/O Completion Port上等待

BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort, ? ? ? ? ? ? ? ? ? ? ? ?//將在其上等待completion port。
LPDWORD lpNumberOfBytesTransferred, ?//指向DWORD,收到“被傳輸的數據字節數”。
LPDWORD lpCompletionKey, ? ? ? ? ? ? ? ? ? //指向DWORD,該DWORD將收到由CreateIoCompletionPort定義的key。
LPOVERLAPPED *lpOverlapped, ? ? ? ? ? ? ? //overlapped結構指針的地址。
DWORD dwMilliseconds ? ? ? ? ? ? ? ? ? ? ? ? ?//等待的最長時間,時間終了,lpOverlapped被設為NULL,函數傳回FALSE。
);

在completion port上等待的線程是以先進后出的次序提供服務。

(5)避免Completion Packets

設定一個 OVERLAPPED 結構,內含一個合法的手動重置(manual-reset)event 對象,放在 hEvent 欄位。然后把該 handle 的最低位設為 1。

overlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

overlap.hEvent = (HANDLE)((DWORD)overlap.hEvent | 0x1);

WriteFile(hFile, buffer, 128,& dwBytesWritten, &overlap);

8.對Sockets使用Overlapped I/O

分析ECHO例子,多實踐socket IOCP。

轉載于:https://www.cnblogs.com/programmer-wfq/p/4646151.html

總結

以上是生活随笔為你收集整理的多线程笔记5的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。