天天看點

《UNIXLinux程式設計教程》一3.8 readv()和writev()函數

read()和write()系統調用每次在檔案和程序的位址空間之間傳送一塊連續的資料。但是,應用有時也需要将分散在記憶體多處地方的資料連續寫到檔案中,或者反之。在這種情況下,如果要從檔案中讀一片連續的資料至程序的不同區域,使用read()則要麼一次将它們讀至一個較大的緩沖區中,然後将它們分成若幹部分複制到不同的區域,要麼調用read()若幹次分批将它們讀至不同區域。同樣,如果想将程式中不同區域的資料塊連續地寫至檔案,也必須進行類似的處理。

unix提供了另外兩個函數—readv()和writev(),它們隻需一次系統調用就可以實作在檔案和程序的多個緩沖區之間傳送資料,免除了多次系統調用或複制資料的開銷。readv()稱為散布讀,即将檔案中若幹連續的資料塊讀入記憶體分散的緩沖區中。writev()稱為聚集寫,即收集記憶體中分散的若幹緩沖區中的資料寫至檔案的連續區域中。

參數fildes是檔案描述字。iov是一個結構數組,它的每個元素指明存儲器中的一個緩沖區。結構類型iovec有下述成員,分别給出緩沖區的起始位址和位元組數:

參數iovcnt指出數組iov的元素個數,元素個數至多不超過iov_max。linux中定義iov_max的值為1024。

圖3-4說明了參數iovcnt、iov及其所指數組與這兩個函數的關系。writev()依次将iov[0]、iov[1]、...、 iov[iovcnt–1]指定的存儲區中的資料寫至fildes指定的檔案。writev()的傳回值是寫出的資料總位元組數,正常情況下它應當等于所有資料塊長度之和。

《UNIXLinux程式設計教程》一3.8 readv()和writev()函數

readv()則将fildes指定檔案中的資料按iov[0]、iov[1]、...、iov[iovcnt–1]規定的順序和長度,分散地讀到它們指定的存儲位址中。readv()的傳回值是讀入的總位元組數。如果沒有資料可讀和遇到了檔案尾,其傳回值為0。

有了這兩個函數,當想要集中寫出某張連結清單時,隻需讓iov數組的各個元素包含連結清單中各個表項的位址和其長度,然後将iov和它的元素個數作為參數傳遞給writev(),這些資料便可一次寫出。