




已閱讀5頁,還剩6頁未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第28章文件與I/O8.mmapmmap可以把磁盤文件的一部分直接映射到內(nèi)存,這樣文件中的位置直接就有對應(yīng)的內(nèi)存地址,對文件的讀寫可以直接用指針來做而不需要read/write函數(shù)。#include void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off); int munmap(void *addr, size_t len);該函數(shù)各參數(shù)的作用圖示如下:圖28.4.mmap函數(shù)如果addr參數(shù)為NULL,內(nèi)核會(huì)自己在進(jìn)程地址空間中選擇合適的地址建立映射。如果addr不是NULL,則給內(nèi)核一個(gè)提示,應(yīng)該從什么地址開始映射,內(nèi)核會(huì)選擇addr之上的某個(gè)合適的地址開始映射。建立映射后,真正的映射首地址通過返回值可以得到。len參數(shù)是需要映射的那一部分文件的長度。off參數(shù)是從文件的什么位置開始映射,必須是頁大小的整數(shù)倍(在32位體系統(tǒng)結(jié)構(gòu)上通常是4K)。filedes是代表該文件的描述符。prot參數(shù)有四種取值: PROT_EXEC表示映射的這一段可執(zhí)行,例如映射共享庫 PROT_READ表示映射的這一段可讀 PROT_WRITE表示映射的這一段可寫 PROT_NONE表示映射的這一段不可訪問flag參數(shù)有很多種取值,這里只講兩種,其它取值可查看mmap(2) MAP_SHARED多個(gè)進(jìn)程對同一個(gè)文件的映射是共享的,一個(gè)進(jìn)程對映射的內(nèi)存做了修改,另一個(gè)進(jìn)程也會(huì)看到這種變化。 MAP_PRIVATE多個(gè)進(jìn)程對同一個(gè)文件的映射不是共享的,一個(gè)進(jìn)程對映射的內(nèi)存做了修改,另一個(gè)進(jìn)程并不會(huì)看到這種變化,也不會(huì)真的寫到文件中去。如果mmap成功則返回映射首地址,如果出錯(cuò)則返回常數(shù)MAP_FAILED。當(dāng)進(jìn)程終止時(shí),該進(jìn)程的映射內(nèi)存會(huì)自動(dòng)解除,也可以調(diào)用munmap解除映射。munmap成功返回0,出錯(cuò)返回-1。下面做一個(gè)簡單的實(shí)驗(yàn)。$ vi hello(編輯該文件的內(nèi)容為“hello”)$ od -tx1 -tc hello 0000000 68 65 6c 6c 6f 0a h e l l o n0000006現(xiàn)在用如下程序操作這個(gè)文件(注意,把fd關(guān)掉并不影響該文件已建立的映射,仍然可以對文件進(jìn)行讀寫)。#include #include #include int main(void)int *p;int fd = open(hello, O_RDWR);if (fd 0) perror(open hello);exit(1);p = mmap(NULL, 6, PROT_WRITE, MAP_SHARED, fd, 0);if (p = MAP_FAILED) perror(mmap);exit(1);close(fd);p0 = 0x30313233;munmap(p, 6);return 0;然后再查看這個(gè)文件的內(nèi)容:$ od -tx1 -tc hello 0000000 33 32 31 30 6f 0a 3 2 1 0 o n 0000006請讀者自己分析一下實(shí)驗(yàn)結(jié)果。mmap函數(shù)的底層也是一個(gè)系統(tǒng)調(diào)用,在執(zhí)行程序時(shí)經(jīng)常要用到這個(gè)系統(tǒng)調(diào)用來映射共享庫到該進(jìn)程的地址空間。例如一個(gè)很簡單的hello world程序:#include int main(void)printf(hello worldn);return 0;用strace命令執(zhí)行該程序,跟蹤該程序執(zhí)行過程中用到的所有系統(tǒng)調(diào)用的參數(shù)及返回值:$ strace ./a.out execve(./a.out, ./a.out, /* 38 vars */) = 0brk(0) = 0x804a000access(/etc/ld.so.nohwcap, F_OK) = -1 ENOENT (No such file or directory)mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fca000access(/etc/ld.so.preload, R_OK) = -1 ENOENT (No such file or directory)open(/etc/ld.so.cache, O_RDONLY) = 3fstat64(3, st_mode=S_IFREG|0644, st_size=63628, .) = 0mmap2(NULL, 63628, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fba000close(3) = 0access(/etc/ld.so.nohwcap, F_OK) = -1 ENOENT (No such file or directory)open(/lib/tls/i686/cmov/libc.so.6, O_RDONLY) = 3read(3, 177ELF11100000000030301000260a1., 512) = 512fstat64(3, st_mode=S_IFREG|0644, st_size=1339816, .) = 0mmap2(NULL, 1349136, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7e70000mmap2(0xb7fb4000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x143) = 0xb7fb4000mmap2(0xb7fb7000, 9744, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7fb7000close(3) = 0mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7e6f000set_thread_area(entry_number:-1 - 6, base_addr:0xb7e6f6b0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1) = 0mprotect(0xb7fb4000, 4096, PROT_READ) = 0munmap(0xb7fba000, 63628) = 0fstat64(1, st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), .) = 0mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fc9000write(1, hello worldn, 12hello world) = 12exit_group(0) = ?Process 8572 detached可以看到,執(zhí)行這個(gè)程序要映射共享庫/lib/tls/i686/cmov/libc.so.6到進(jìn)程地址空間。也可以看到,printf函數(shù)的底層確實(shí)是調(diào)用write。 8.mmapmmap可以把磁盤文件的一部分直接映射到內(nèi)存,這樣文件中的位置直接就有對應(yīng)的內(nèi)存地址,對文件的讀寫可以直接用指針來做而不需要read/write函數(shù)。#include void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off); int munmap(void *addr, size_t len);該函數(shù)各參數(shù)的作用圖示如下:圖28.4.mmap函數(shù)如果addr參數(shù)為NULL,內(nèi)核會(huì)自己在進(jìn)程地址空間中選擇合適的地址建立映射。如果addr不是NULL,則給內(nèi)核一個(gè)提示,應(yīng)該從什么地址開始映射,內(nèi)核會(huì)選擇addr之上的某個(gè)合適的地址開始映射。建立映射后,真正的映射首地址通過返回值可以得到。len參數(shù)是需要映射的那一部分文件的長度。off參數(shù)是從文件的什么位置開始映射,必須是頁大小的整數(shù)倍(在32位體系統(tǒng)結(jié)構(gòu)上通常是4K)。filedes是代表該文件的描述符。prot參數(shù)有四種取值: PROT_EXEC表示映射的這一段可執(zhí)行,例如映射共享庫 PROT_READ表示映射的這一段可讀 PROT_WRITE表示映射的這一段可寫 PROT_NONE表示映射的這一段不可訪問flag參數(shù)有很多種取值,這里只講兩種,其它取值可查看mmap(2) MAP_SHARED多個(gè)進(jìn)程對同一個(gè)文件的映射是共享的,一個(gè)進(jìn)程對映射的內(nèi)存做了修改,另一個(gè)進(jìn)程也會(huì)看到這種變化。 MAP_PRIVATE多個(gè)進(jìn)程對同一個(gè)文件的映射不是共享的,一個(gè)進(jìn)程對映射的內(nèi)存做了修改,另一個(gè)進(jìn)程并不會(huì)看到這種變化,也不會(huì)真的寫到文件中去。如果mmap成功則返回映射首地址,如果出錯(cuò)則返回常數(shù)MAP_FAILED。當(dāng)進(jìn)程終止時(shí),該進(jìn)程的映射內(nèi)存會(huì)自動(dòng)解除,也可以調(diào)用munmap解除映射。munmap成功返回0,出錯(cuò)返回-1。下面做一個(gè)簡單的實(shí)驗(yàn)。$ vi hello(編輯該文件的內(nèi)容為“hello”)$ od -tx1 -tc hello 0000000 68 65 6c 6c 6f 0a h e l l o n0000006現(xiàn)在用如下程序操作這個(gè)文件(注意,把fd關(guān)掉并不影響該文件已建立的映射,仍然可以對文件進(jìn)行讀寫)。#include #include #include int main(void)int *p;int fd = open(hello, O_RDWR);if (fd 0) perror(open hello);exit(1);p = mmap(NULL, 6, PROT_WRITE, MAP_SHARED, fd, 0);if (p = MAP_FAILED) perror(mmap);exit(1);close(fd);p0 = 0x30313233;munmap(p, 6);return 0;然后再查看這個(gè)文件的內(nèi)容:$ od -tx1 -tc hello 0000000 33 32 31 30 6f 0a 3 2 1 0 o n 0000006請讀者自己分析一下實(shí)驗(yàn)結(jié)果。mmap函數(shù)的底層也是一個(gè)系統(tǒng)調(diào)用,在執(zhí)行程序時(shí)經(jīng)常要用到這個(gè)系統(tǒng)調(diào)用來映射共享庫到該進(jìn)程的地址空間。例如一個(gè)很簡單的hello world程序:#include int main(void)printf(hello worldn);return 0;用strace命令執(zhí)行該程序,跟蹤該程序執(zhí)行過程中用到的所有系統(tǒng)調(diào)用的參數(shù)及返回值:$ strace ./a.out execve(./a.out, ./a.out, /* 38 vars */) = 0brk(0) = 0x804a000access(/etc/ld.so.nohwcap, F_OK) = -1 ENOENT (No such file or directory)mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fca000access(/etc/ld.so.preload, R_OK) = -1 ENOENT (No such file or directory)open(/etc/ld.so.cache, O_RDONLY) = 3fstat64(3, st_mode=S_IFREG|0644, st_size=63628, .) = 0mmap2(NULL, 63628, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fba000close(3) = 0access(/etc/ld.so.nohwcap, F_OK) = -1 ENOENT (No such file or directory)open(/lib/tls/i686/cmov/libc.so.6, O_RDONLY) = 3read(3, 177ELF11100000000030301000260a1., 512) = 512fstat64(3, st_mode=S_IFREG|0644, st_size=1339816, .) = 0mmap2(NULL, 1349136, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7e70000mmap2(0xb7fb4000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x143) = 0xb7fb4000mmap2(0xb7fb7000, 9744, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7fb7000close(3) = 0mmap2(NULL, 4
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 精準(zhǔn)掌握2025年物理考試試題及答案
- 新能源汽車動(dòng)力電池技術(shù)題目及答案
- 家具設(shè)計(jì)的市場戰(zhàn)略考慮試題及答案
- 最難智商測試題及答案
- 家具行業(yè)多元化設(shè)計(jì)探討試題及答案
- 教師教書育人反思與策略試題及答案
- 施工圖識讀與分析試題及答案
- 環(huán)保宣傳面試真題及答案
- 2025南航招聘空姐面試常見問題及答案
- 城市軌道交通建設(shè)規(guī)劃與環(huán)境保護(hù)措施研究報(bào)告
- 法理斗爭1全文
- 醫(yī)療美容診所規(guī)章制度上墻
- 2024年山東省青島市城陽區(qū)中考生物模擬試卷
- 汽車機(jī)械式變速器分類的術(shù)語及定義
- 24春國家開放大學(xué)《建筑測量》形考任務(wù)實(shí)驗(yàn)1-6參考答案
- 云南省勞務(wù)派遣勞動(dòng)合同書
- 瑜伽與冥想練習(xí)
- 心臟介入術(shù)后穿刺部位并發(fā)癥的預(yù)防及護(hù)理講解
- 鄰近鐵路營業(yè)線施工安全監(jiān)測技術(shù)規(guī)程 (TB 10314-2021)
- 智能化屠宰場建設(shè)方案設(shè)計(jì)
- 地下管道工程施工合同
評論
0/150
提交評論