高级I/O(七)--readv和writev函数
From: http://blog.chinaunix.net/uid-26822401-id-3158225.html
readv和write函數(shù)讓我們在單個函數(shù)調用里從多個不連續(xù)的緩沖里讀入或寫出。這些操作被稱為分散讀(scatter read)和集合寫(gather write)。
兩個函數(shù)的第二個參數(shù)都是一個iovec結構體數(shù)組的指針:
struct iovec {
? void *iov_base;? /* starting address of buffer */
? size_t iov_len;? /* size of buffer */
};
iov數(shù)組里的元素數(shù)量由iovcnt指定。它限制于IOV_MAX(第二章)。下圖顯示了這兩個函數(shù)的參數(shù)和iovec結構體的關系:
writev函數(shù)把緩沖的輸出數(shù)據(jù)按順序集合到一起:iov[0]、iov[1]、到iov[iovcnt-1];writev返回輸出字節(jié)的總數(shù)量,它應該等于所有緩沖長度的和。
readv函數(shù)把數(shù)據(jù)按順序分散到緩沖里,問題在處理下一個緩沖時填滿第一個。readv返回被讀的字節(jié)總數(shù)。如果沒有更多數(shù)據(jù)和碰到文件末尾時返回0的計數(shù)。
這兩個函數(shù)起源于4.2BSD,后來加入到SVR4。這兩個函數(shù)被SUS的XSI擴展包含。
盡管SUS定義了緩沖地址為一個void *,然而許多未跟上標準的實現(xiàn)仍使用char *代替。
在20.8節(jié)里,函數(shù)_db_writeidx里,我們需要連續(xù)地寫兩個緩沖到一個文件。第二個要輸出的緩沖是一個傳給調用者的參數(shù),而第一個緩沖是我們創(chuàng)建的,包含第二個緩沖的長度和文件里其它信息的一個文件偏移量。我們可以有三種方法做這個。
1、調用write兩次,一個緩沖一次;
2、分配一個我們自己的緩沖,它足夠大來包含兩個緩沖,然后把兩者拷貝到新緩沖。我們然后為這個新緩沖調用write一次。
3、調用writev來輸出兩個緩沖。
我們在20.8節(jié)使用的解決方案是使用writev,但是把它跟其它兩種方案比較是有指導性的。
下表顯示了提到的三種方法的結果。?
| 操作 | Linux (Intel x86) | Mac OS X (PowerPC) | ||||
| 用戶 | 系統(tǒng) | 時鐘 | 用戶 | 系統(tǒng) | 時鐘 | |
| 兩次write | 1.29 | 3.15 | 7.39 | 1.60 | 17.40 | 19.84 |
| 緩沖拷貝,然后一次write | 1.03 | 1.98 | 6.47 | 1.10 | 11.09 | 12.54 |
| 一次writev | 0.70 | ?2.72 | 6.41 | 0.86 | 13.58 | 14.72 |
我們測量的測試程序輸出一個100字節(jié)的頭,接著一個200字節(jié)的數(shù)據(jù)。這被完成1048576次,產生一個300M的文件。測試程序有三個分離的條件--上表中每個測量的技術是一個。我們使用times(8.16節(jié))來得到用戶CUP時間,系統(tǒng)CPU系統(tǒng)和掛鐘時間,在write前后。所有三個時間以秒顯示。
正如我們意料的,系統(tǒng)時間當我們調用兩次write時增加,對比于一次的write或writev。這和3.9節(jié)的測量結果對應。
接著,注意CPU時間的總和(用戶加上系統(tǒng)),當我們執(zhí)行緩沖拷貝接著單個write比單個writev調用要少。對于單個write,我們在用戶層拷貝緩沖到一個分段運輸?shù)木彌_,然后在我們調用write時內核會把數(shù)據(jù)拷貝到它內部的緩沖。對于writev,我們應該做更少的拷貝,因為內核只需要直接把數(shù)據(jù)拷貝到它的分段運輸緩沖里。然而,為如此少的數(shù)據(jù)使用writev的固定花費,比所得要大。當我們需要拷貝的數(shù)據(jù)量增加時,在我們程序里拷貝緩沖會便耗時,而writev替代地將更具吸引力。
小必不要被上表中Linux相對于Mac的性能影響太多。這兩個電腦非常不同:它們有不同的處理器架構、不同的RAM量、不同速度的磁盤。為了公平比較兩個操作系統(tǒng),我們需要使用相同的硬件。
總而言之,我們應該總是嘗試使用所需的最少次數(shù)的系統(tǒng)調用來完成工作。如果我們寫少量數(shù)據(jù),那么我們將發(fā)現(xiàn)自己拷貝數(shù)據(jù)和使用單個write而不是使用writev會更不耗時。然而,我們可能發(fā)現(xiàn),性能的好處比不上需要管理我們自己的分段運輸緩沖的復雜性代價。
總結
以上是生活随笔為你收集整理的高级I/O(七)--readv和writev函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 花式看超级碗 人工智能、大数据在碗里
- 下一篇: 提取二维矩阵中分块后指定的块