存储映射I/O(一)
一、存儲映射I/O
存儲映射I/O使一個磁盤文件與存儲空間中的一個緩沖區映射,于是當從緩沖區中取數據,就相當于讀文件中的相應字節。于此類似,將數據存入緩沖區,則相應的字節就自動寫入文件,這樣,就可在不不適用read和write函數的情況下,使用地址(指針)完成I/O操作。
使用這種方法,首先應通知內核,將一個指定文件映射到存儲區域中,這個映射工作可以通過mmap函數來實現。
?
二、主要應用函數
1. mmap函數原型:
#include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);返回值:若成功,返回映射區的起始位置;若出錯,返回MAP_FALLED參數:
? ? ? ? addr:? ? 建立映射區的首地址,由于Linux內核指定,使用時,直接傳遞NULL
? ? ? ? lengrh: 欲創建映射區的大小
? ? ? ? prot:? ? ?映射區權限PROT_READ、PROT_WRITE、PROT_READ |? PROT_WRITE
? ? ? ? flag:? ? ?標志位參數(常用于設定更新物理區、設置共享、創建匿名映射區)
? ? ? ? ? ? ? ? ? ? ? ?MAP_SHARED:會將映射區所做的操作反映到物理設備(磁盤)上。
? ? ? ? ? ? ? ? ? ? ? ? MAP_PRIVATE:映射區所做的修改不會反映到物理設備。
? ? ? ? fd:? ? ? ? ?用來建立映射區的文件描述符。
? ? ? offset:? ? ?映射文件的偏移量(4k的整數倍)
?
使用mmap時務必注意以下事項:
- 創建映射區的過程,隱含著一次對映射文件的讀操作。
- 當MAP_SHARED時,要求:映射區的權限應 <= 文件打開的權限(處于對映射區的保護)。而MAP_PRIVATE則無所謂,因為mmap中的權限是對內存的限制。
- 映射區的釋放與文件關閉無關,只要映射區建立成功,文件可以立即關閉。
- 特別注意。當映射區文件大下為0時, 不能創建映射區。所以:用于映射區的文件必須要有實際大小!!mmap使用時常常會出現總線錯誤,通常是由于共享文件存儲空間大小引起的。(文件的大小不能小于映射區的大小)
- mummap傳入地址一定是mmap的返回地址。堅決杜絕指針++操作。
- 文件偏移量必須為4k的整數倍
- mmap創建映射區錯概率非常高,一定要檢查返回值,確保映射區建立成功在進行后續操作。
?
示意圖:
?
三、程序清單
1. 測試代碼:
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/wait.h>int main() {int fd1, fd2;pid_t pid;char buf[1024];char *str = "----------test for shared fd in parent child process-----";pid = fork();if(pid < 0) {perror("fork error");exit(1);} else if(pid == 0) {fd1 = open("test.txt", O_RDWR);if(fd1 < 0) {perror("open error");exit(1);}write(fd1, str, strlen(str));printf("child wrote over....");} else {fd2 = open("test.txt", O_RDWR);if(fd2 < 0) {perror("open error");exit(1);}sleep(1);int len = read(fd2, buf, sizeof(buf));write(STDOUT_FILENO, buf, len);wait(NULL);}return 0; }輸出結果:
?
2 測試代碼:
#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/mman.h>int main() {int len, ret;char *p = NULL;int fd = open("mytest.txt", O_CREAT | O_RDWR, 0644);if(fd < 0) {perror("open error: ");exit(1);}len = ftruncate(fd, 4);p = mmap(NULL, 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if(p == MAP_FAILED) {perror("mmap error:");exit(1);}strcpy(p, "abc"); //寫數據ret = munmap(p, 4);if(ret == -1) {perror("mmap error:");exit(1);}close(fd);return 0; }輸出結果:
總結
以上是生活随笔為你收集整理的存储映射I/O(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POSIX信号量
- 下一篇: lol卡牌大师是短手英雄还是长手英雄