官术网_书友最值得收藏!

3.11 高級(jí)主題:fcntl和mmap

本節(jié)我們將討論的主題你可能會(huì)想跳過(guò),因?yàn)樗鼈兒苌贂?huì)被用到。話雖如此,但我們還是把它放在這里供你參考,因?yàn)樵诮鉀Q一些棘手問(wèn)題時(shí),它們可以提供比較簡(jiǎn)單的解決方案。

3.11.1 fcntl系統(tǒng)調(diào)用

fcntl系統(tǒng)調(diào)用對(duì)底層文件描述符提供了更多的操縱方法。

利用fcntl系統(tǒng)調(diào)用,你可以對(duì)打開(kāi)的文件描述符執(zhí)行各種操作,包括對(duì)它們進(jìn)行復(fù)制、獲取和設(shè)置文件描述符標(biāo)志、獲取和設(shè)置文件狀態(tài)標(biāo)志,以及管理建議性文件鎖等。

對(duì)不同操作的選擇是通過(guò)選取命令參數(shù)cmd不同的值來(lái)實(shí)現(xiàn)的,其取值定義在頭文件fcntl.h中。根據(jù)所選擇命令的不同,系統(tǒng)調(diào)用可能還需要第三個(gè)參數(shù)arg。

? fcntl(fildes, F_DUPFD, newfd):這個(gè)調(diào)用返回一個(gè)新的文件描述符,其數(shù)值等于或大于整數(shù)newfd。新文件描述符是描述符fildes的一個(gè)副本。根據(jù)已打開(kāi)文件數(shù)目和newfd值的情況,它的效果可能和系統(tǒng)調(diào)用dup(fildes)完全一樣。

? fcntl(fildes, F_GETFD):這個(gè)調(diào)用返回在fcntl.h頭文件里定義的文件描述符標(biāo)志,其中包括FD_CLOEXEC,它的作用是決定是否在成功調(diào)用了某個(gè)exec系列的系統(tǒng)調(diào)用之后關(guān)閉該文件描述符。

? fcntl(fildes, F_SETFD, flags):這個(gè)調(diào)用用于設(shè)置文件描述符標(biāo)志,通常僅用來(lái)設(shè)置FD_CLOEXEC。

? fcntl(fildes, F_GETFL)和fcntl(fildes, F_SETFL, flags):這兩個(gè)調(diào)用分別用來(lái)獲取和設(shè)置文件狀態(tài)標(biāo)志和訪問(wèn)模式。你可以利用在fcntl.h頭文件中定義的掩碼O_ ACCMODE來(lái)提取出文件的訪問(wèn)模式。其他標(biāo)志包括那些當(dāng)open調(diào)用使用O_CREAT打開(kāi)文件時(shí)作為第三參數(shù)出現(xiàn)的標(biāo)志。注意,你不能設(shè)置所有的標(biāo)志,特別是不能通過(guò)fcntl設(shè)置文件的權(quán)限。

你還可以通過(guò)fcntl實(shí)現(xiàn)建議性文件鎖。詳細(xì)信息請(qǐng)參考fcntl手冊(cè)頁(yè)的第二節(jié),或者閱讀本書的第7章,我們將在那里討論文件鎖。

3.11.2 mmap函數(shù)

UNIX提供了一個(gè)有用的功能以允許程序共享內(nèi)存,Linux內(nèi)核從2.0版本開(kāi)始已經(jīng)把這一功能包括進(jìn)來(lái)。mmap(內(nèi)存映射)函數(shù)的作用是建立一段可以被兩個(gè)或更多個(gè)程序讀寫的內(nèi)存。一個(gè)程序?qū)λ龀龅男薷目梢员黄渌绦蚩匆?jiàn)。

這一功能還可以用在文件的處理上。你可以使某個(gè)磁盤文件的全部?jī)?nèi)容看起來(lái)就像是內(nèi)存中的一個(gè)數(shù)組。如果文件由記錄組成,而這些記錄又能夠用C語(yǔ)言中的結(jié)構(gòu)來(lái)描述的話,你就可以通過(guò)訪問(wèn)結(jié)構(gòu)數(shù)組來(lái)更新文件的內(nèi)容了。

這要通過(guò)使用帶特殊權(quán)限集的虛擬內(nèi)存段來(lái)實(shí)現(xiàn)。對(duì)這類虛擬內(nèi)存段的讀寫會(huì)使操作系統(tǒng)去讀寫磁盤文件中與之對(duì)應(yīng)的部分。

mmap函數(shù)創(chuàng)建一個(gè)指向一段內(nèi)存區(qū)域的指針,該內(nèi)存區(qū)域與可以通過(guò)一個(gè)打開(kāi)的文件描述符訪問(wèn)的文件的內(nèi)容相關(guān)聯(lián)。

你可以通過(guò)傳遞off參數(shù)來(lái)改變經(jīng)共享內(nèi)存段訪問(wèn)的文件中數(shù)據(jù)的起始偏移值。打開(kāi)的文件描述符由fildes參數(shù)給出。可以訪問(wèn)的數(shù)據(jù)量(即內(nèi)存段的長(zhǎng)度)由len參數(shù)設(shè)置。

你可以通過(guò)addr參數(shù)來(lái)請(qǐng)求使用某個(gè)特定的內(nèi)存地址。如果它的取值是零,結(jié)果指針就將自動(dòng)分配。這是推薦的做法,否則會(huì)降低程序的可移植性,因?yàn)椴煌到y(tǒng)上的可用地址范圍是不一樣的。

prot參數(shù)用于設(shè)置內(nèi)存段的訪問(wèn)權(quán)限。它是下列常數(shù)值的按位OR結(jié)果。

? PROT_READ:允許讀該內(nèi)存段。

? PROT_WRITE:允許寫該內(nèi)存段。

? PROT_EXEC:允許執(zhí)行該內(nèi)存段。

? PROT_NONE:該內(nèi)存段不能被訪問(wèn)。

flags參數(shù)控制程序?qū)υ搩?nèi)存段的改變所造成的影響,可以使用的選項(xiàng)如表3-7所示。

表3-7

msync函數(shù)的作用是:把在該內(nèi)存段的某個(gè)部分或整段中的修改寫回到被映射的文件中(或者從被映射文件里讀出)。

內(nèi)存段需要修改的部分由作為參數(shù)傳遞過(guò)來(lái)的起始地址addr和長(zhǎng)度len確定。flags參數(shù)控制著執(zhí)行修改的具體方式,可以使用的選項(xiàng)如表3-8所示。

表3-8

munmap函數(shù)的作用是釋放內(nèi)存段:

下面的程序mmap.c演示了如何利用mmap和數(shù)組方式的存取操作來(lái)修改一個(gè)結(jié)構(gòu)化數(shù)據(jù)文件。注意,2.0版本之前的Linux內(nèi)核不完全支持mmap的這種用法。這個(gè)程序在Sun Solaris和其他操作系統(tǒng)上也能夠正確運(yùn)行。

實(shí)驗(yàn) 使用mmap函數(shù)

(1)我們先定義一個(gè)RECORD數(shù)據(jù)結(jié)構(gòu),然后創(chuàng)建出NRECORDS個(gè)記錄,每個(gè)記錄中保存著它們各自的編號(hào)。然后把這些記錄都追加到文件records.dat里去。

(2)接著,我們把第43條記錄中的整數(shù)值由43修改為143,并把它寫入第43條記錄中的字符串。

(3)現(xiàn)在把這些記錄映射到內(nèi)存中,然后訪問(wèn)第43條記錄,把它的整數(shù)值修改為243(同時(shí)更新該記錄中的字符串),使用的還是內(nèi)存映射的方法。

在第13章中,你將學(xué)習(xí)另外一種共享內(nèi)存機(jī)制:System V共享內(nèi)存。

主站蜘蛛池模板: 麻城市| 革吉县| 探索| 曲靖市| 辽阳县| 睢宁县| 龙江县| 桐梓县| 梅州市| 崇义县| 青冈县| 宜兴市| 财经| 措美县| 洪湖市| 剑河县| 文登市| 宁蒗| 大荔县| 汉川市| 香格里拉县| 临颍县| 舟山市| 山阳县| 彰化市| 巫溪县| 绥化市| 东兰县| 丰顺县| 广州市| 德保县| 高密市| 泰顺县| 上思县| 新竹县| 辰溪县| 保亭| 弋阳县| 石城县| 兖州市| 海盐县|