linux文件IO与内存映射:分散/聚集IO技术(scatter-gather)
前言
根據(jù)上文我們學(xué)習(xí)到的用戶空間的IO緩沖區(qū),操作系統(tǒng)為了減少系統(tǒng)調(diào)用的次數(shù),節(jié)省系統(tǒng)開銷,提出了用戶空間的IO緩沖區(qū),即為用戶空間的文件讀寫開辟一段可以利用setvbuf配置大小的內(nèi)存空間來作為文件IO緩沖區(qū)。
描述
為了在以上IO緩沖區(qū)的基礎(chǔ)上更進(jìn)一步得減少系統(tǒng)調(diào)用的次數(shù),提出了分散/聚合IO技術(shù),總體上是使用了單個(gè)向量的IO操作代替了多個(gè)向量的IO操作。
讀文多個(gè)件的時(shí)候?qū)膒age cache中讀到的內(nèi)容先讀入到一個(gè)IO緩沖區(qū)數(shù)據(jù)結(jié)構(gòu)中,再由一個(gè)緩沖區(qū)分別分散返回到多個(gè)文件緩沖區(qū)中;寫文件的過程與讀文件的過程剛好相反,即將多個(gè)文件緩沖區(qū)的內(nèi)容聚合寫到一個(gè)緩沖區(qū)中,寫入page cache中,從而更高得提升系統(tǒng)調(diào)用效率。
實(shí)現(xiàn)
實(shí)現(xiàn)scatter-gather技術(shù)的系統(tǒng)調(diào)用原型如下:
-
頭文件
<sys/uio.h> -
函數(shù)使用:
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
ssize_t writev(int fd, const struct iovec *iov, int iovcnt); -
函數(shù)參數(shù)
fd:打開的文件描述符
iov: IO向量數(shù)據(jù)結(jié)構(gòu)內(nèi)容如下,每個(gè)結(jié)構(gòu)體成員代表一個(gè)buffer:struct iovec {void *iov_base; /* Starting address */size_t iov_len; /* Number of bytes to transfer */};iovcnt:IO向量的個(gè)數(shù)這兩個(gè)系統(tǒng)調(diào)用的底層仍然是使用read/write系統(tǒng)調(diào)用,只是對(duì)IO 緩沖區(qū)做了聚合,支持多個(gè)IO緩沖區(qū)內(nèi)容聚合到同一個(gè)IO向量中
代碼如下:
writev.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/uio.h>
#include <fcntl.h>int main(int argc, char *argv[])
{ssize_t count = 0;int fd, i = 0;char *buf[]={"buffer1\n","buffer2\n","buffer3\n"};fd = open(argv[1], O_WRONLY|O_CREAT, 0666);if (-1 == fd) {printf("open failed \n");_exit(-1);}//將三個(gè)IO緩沖區(qū)的文件聚合為一個(gè)IO向量struct iovec iov[3];for (i ; i < 3; ++i) {iov[i].iov_base = buf[i];iov[i].iov_len = sizeof(buf[i]) + 1;printf("iovec[%d] size is %ld \n",i,iov[i].iov_len);}//寫入一個(gè)文件count = writev(fd, iov, 3);if (-1 == count) {printf("writev failed\n");_exit(-1);}close(fd);return 0;
}
readv.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/uio.h>
#include <fcntl.h>int main(int argc, char *argv[])
{ssize_t count = 0;int fd, i = 0;char buf1[9],buf2[9],buf3[9];//生成一個(gè)文件,可以傳入聚合IO緩沖區(qū)的文件fd = open(argv[1], O_RDONLY,0666);if (-1 == fd) {printf("open failed \n");_exit(-1);}//對(duì)IO向量中的各個(gè)IO緩沖區(qū)進(jìn)行地址和內(nèi)容大小賦值struct iovec iov[3];iov[0].iov_base = buf1;iov[0].iov_len = sizeof(buf1); iov[1].iov_base = buf2;iov[1].iov_len = sizeof(buf2); iov[2].iov_base = buf3;iov[2].iov_len = sizeof(buf3); //從page cache讀入的一個(gè)向量會(huì)分散到三個(gè)緩沖區(qū)中count = readv(fd,iov,3);if (-1 == count) {printf("writev failed\n");_exit(-1);}for (i ; i < 3; ++i) {printf(" %s",(char *)(iov[i].iov_base));}prinft("buf1 %s\n",buf1);prinft("buf2 %s\n",buf2);prinft("buf3 %s\n",buf3);close(fd);return 0;
}
編譯輸出如下:
gcc writev.c -o writev
gcc readv.c -o readv
zhang@ubuntu:~/Desktop/cpp_practice$ ./writev writevfile
iovec[0] size is 9
iovec[1] size is 9
iovec[2] size is 9
zhang@ubuntu:~/Desktop/cpp_practice$ ./readv writevfile buffer1buffer2buffer3
buf1 buffer1buf2 buffer2buf3 buffer3
總結(jié)
以上是生活随笔為你收集整理的linux文件IO与内存映射:分散/聚集IO技术(scatter-gather)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux文件IO与内存映射:用户空间的
- 下一篇: 补车牌多少钱啊?