新聞中心
內(nèi)存映射是Linux C應(yīng)用程序開(kāi)發(fā)中的重要技術(shù)之一。它可以在用戶空間和內(nèi)核空間間建立一種映射關(guān)系,并使得程序可以直接訪問(wèn)內(nèi)核中的某些數(shù)據(jù)結(jié)構(gòu)和文件系統(tǒng)。本文將介紹在,并闡述它們的實(shí)現(xiàn)原理和使用方法。

創(chuàng)新互聯(lián)于2013年開(kāi)始,先為宜豐等服務(wù)建站,宜豐等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為宜豐企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。
1.匿名內(nèi)存映射
匿名內(nèi)存映射是一種最簡(jiǎn)單的內(nèi)存映射技術(shù),它可以在程序內(nèi)部映射一塊未命名的內(nèi)存區(qū)域。使用該技術(shù)需要調(diào)用mmap函數(shù),并指明所需的映射地址、映射大小、映射方式等參數(shù)。
匿名內(nèi)存映射在Linux C應(yīng)用開(kāi)發(fā)中常用于創(chuàng)建共享內(nèi)存區(qū)域,使得多個(gè)進(jìn)程可以共享同一塊內(nèi)存,并進(jìn)行數(shù)據(jù)交換。在匿名內(nèi)存映射技術(shù)中,當(dāng)一個(gè)進(jìn)程寫入共享內(nèi)存時(shí),其它進(jìn)程都可以立即看到這個(gè)變化。
2.文件內(nèi)存映射
文件內(nèi)存映射是Linux C應(yīng)用中另一個(gè)常用的內(nèi)存映射技術(shù),它可以將文件映射到進(jìn)程的地址空間,并可直接在內(nèi)存中讀寫文件。使用該技術(shù)需要調(diào)用mmap函數(shù),指定所需映射的文件和映射方式等參數(shù)。
文件內(nèi)存映射在Linux C應(yīng)用開(kāi)發(fā)中廣泛應(yīng)用于文件操作和數(shù)據(jù)結(jié)構(gòu)處理等場(chǎng)景。在文件內(nèi)存映射技術(shù)中,使用者可以直接訪問(wèn)內(nèi)存中的數(shù)據(jù),而無(wú)需進(jìn)行文件讀寫操作,極大地方便了應(yīng)用程序的開(kāi)發(fā)和實(shí)現(xiàn)。
3.共享內(nèi)存映射
共享內(nèi)存映射是Linux C應(yīng)用中非常常用的內(nèi)存映射技術(shù)之一,它可以將內(nèi)存區(qū)域映射到多個(gè)進(jìn)程中,并實(shí)現(xiàn)數(shù)據(jù)共享。共享內(nèi)存映射技術(shù)需要調(diào)用shm_open和mmap這兩個(gè)函數(shù)。
共享內(nèi)存映射技術(shù)在Linux C應(yīng)用程序開(kāi)發(fā)中廣泛應(yīng)用于多進(jìn)程協(xié)作和數(shù)據(jù)共享等場(chǎng)景。通過(guò)共享內(nèi)存映射技術(shù),多個(gè)進(jìn)程可以共享一個(gè)變量或數(shù)據(jù)結(jié)構(gòu),從而實(shí)現(xiàn)進(jìn)程間數(shù)據(jù)交換和通信。
4.循環(huán)緩沖區(qū)內(nèi)存映射
循環(huán)緩沖區(qū)內(nèi)存映射是一種特殊的內(nèi)存映射技術(shù),它是通過(guò)內(nèi)存映射方式實(shí)現(xiàn)循環(huán)隊(duì)列的操作。使用該技術(shù)需要調(diào)用mmap函數(shù),并指明所需的映射地址、大小、映射方式等參數(shù)。
循環(huán)緩沖區(qū)內(nèi)存映射技術(shù)在Linux C應(yīng)用中廣泛應(yīng)用于數(shù)據(jù)傳輸和隊(duì)列處理等場(chǎng)景。該技術(shù)能夠?qū)崿F(xiàn)高效的數(shù)據(jù)傳輸和存儲(chǔ),從而提高程序的效率和性能。
結(jié)語(yǔ)
內(nèi)存映射技術(shù)是Linux C應(yīng)用程序開(kāi)發(fā)中非常重要的技術(shù)之一。本文介紹了在Linux C應(yīng)用中常用的幾種內(nèi)存映射技術(shù),包括匿名內(nèi)存映射、文件內(nèi)存映射、共享內(nèi)存映射和循環(huán)緩沖區(qū)內(nèi)存映射,并闡述了它們的實(shí)現(xiàn)原理和使用方法。通過(guò)內(nèi)存映射技術(shù),我們可以更加高效地處理數(shù)據(jù)和實(shí)現(xiàn)多進(jìn)程協(xié)作,從而提高程序的效率和性能。
相關(guān)問(wèn)題拓展閱讀:
- 怎么理解linux下內(nèi)存的三級(jí)映射?請(qǐng)大俠指教
- 內(nèi)存映射的相關(guān)信息
怎么理解linux下內(nèi)存的三級(jí)映射?請(qǐng)大俠指教
邏輯地址-線性地址-物理睜豎激地址
分段纖談,分頁(yè)
再詳細(xì)點(diǎn)需要閱讀書(shū)籍吧,這個(gè)也不光是linux,而是386硬悉襪件決定的,建議看下匯編方面的。
內(nèi)存映射的相關(guān)信息
4.1示例代碼
通過(guò)前面的理論分析,我們通過(guò)編寫一個(gè)簡(jiǎn)單的程序,來(lái)分析內(nèi)核是如何把線性地址映射到物理地址的。
#cattest.c
#include
voidtest(void)
{
printf(hello,world.\n);
}
intmain(void)
{
test();
}
這段代碼很簡(jiǎn)單,我們故意要main調(diào)用test函數(shù),就是想看下test函數(shù)的虛擬地址是如何映射成物理地址的。
4.2段式映射分析
我們先編譯,在反匯編下test文件
#gcc-otesttest.c
#objdump-dtest
:
:55push%ebp
:89e5mov%esp,%ebp
804836b:83ec08sub$0x8,%esp
804836e:83ec0csub$0xc,%esp
:push$0x
:e835ffffffcall80482b0
804837b:83c410add$0x10,%esp
804837e:c9leave
804837f:c3ret
:
:55push%ebp
:89e5mov%esp,%ebp
:83ec08sub$0x8,%esp
:83e4f0and$0xfffffff0,%esp
:bmov$0x0,%eax
804838e:83c00fadd$0xf,%eax
:83c00fadd$0xf,%eax
:c1e804shr$0x4,%eax
:c1e004shl$0x4,%eax
804839a:29c4sub%eax,%esp
804839c:e8c7ffffffcall
80483a1:c9leave
80483a2:c3ret
80483a3:90nop
從上述結(jié)果可以看到,ld給test()函數(shù)分配的地址為0x.在elf格式的可執(zhí)行文件代碼中,ld的實(shí)際位置總是從0x開(kāi)始安排程序
的代碼段,對(duì)每個(gè)程序都是這樣。至于程序在執(zhí)行時(shí)在物理內(nèi)存中的實(shí)際位置就要由內(nèi)核在為其建立內(nèi)存映射時(shí)臨時(shí)做出安排,具體地址則
取決段虧于當(dāng)時(shí)所分配到的物理內(nèi)存頁(yè)面。假設(shè)該程序已經(jīng)運(yùn)行,整個(gè)映射機(jī)制都已經(jīng)建立好,尺燃派并且CPU正在執(zhí)行main()中的call這條指
令,要轉(zhuǎn)移到虛擬地址0x去運(yùn)行.下面將詳細(xì)介紹這個(gè)虛擬地址轉(zhuǎn)換為物理地址的映射過(guò)程.
首先是段式映射階段。由于0x是一個(gè)程序的入口,更重要的是在執(zhí)行的過(guò)程中是由CPU中的指令計(jì)數(shù)器EIP所指向的,所以在代碼段中
。因此,i386CPU使用代碼段寄存器CS的當(dāng)前值作為段式映射的選擇子,也就是用它作為在段描述表的下標(biāo).那么CS的值是多少呢?
用GDB調(diào)試下test:
(gdb)inforeg
eax0x1016
ecx0x11
edx0x9d915c
ebx0x9d6ff
esp0xbfedb4800xbfedb480
ebp0xbfedb4880xbfedb488
esi0xbfedb
edi0xbfedb4c
eip0x804836e0x804836e
eflags0x282642
cs0x73115
ss0x7b123
ds0x7b123
es0x7b123
fs0x00
gs0x3351
可以看到CS的值為0x73,我們把它分解成二進(jìn)制:
更低2位為3,說(shuō)明RPL的值為3,應(yīng)為我們這個(gè)程序本省就是在用戶空間,RPL的值自然為3.
第3位為0表示這個(gè)下標(biāo)在GDT中。
高13位為14,所以段描述符在GDT表的第14個(gè)表項(xiàng)中,我陵賀們可以到內(nèi)核代碼中去驗(yàn)證下:
在i386/a/segment.h中:
#defineGDT_ENTRY_DEFAULT_USER_CS14
#define__USER_CS(GDT_ENTRY_DEFAULT_USER_CS*8+3)
可以看到段描述符的確就是GDT表的第14個(gè)表項(xiàng)中。
我們?nèi)DT表看看具體的表項(xiàng)值是什么,GDT的內(nèi)容在arch/i386/kernel/head.S中定義:
ENTRY(cpu_gdt_table)
.quad0x00/*NULLdescriptor*/
.quad0x00/*0x0breserved*/
.quad0x00/*0x13reserved*/
.quad0x00/*0x1breserved*/
.quad0x00/*0x20unused*/
.quad0x00/*0x28unused*/
.quad0x00/*0x33TLSentry1*/
.quad0x00/*0x3bTLSentry2*/
.quad0x00/*0x43TLSentry3*/
.quad0x00/*0x4breserved*/
.quad0x00/*0x53reserved*/
.quad0x00/*0x5breserved*/
.quad0x00cf9a000000ffff/*0x60kernel4GBcodeat0x*/
.quad0x00cfffff/*0x68kernel4GBdataat0x*/
.quad0x00cffa000000ffff/*0x73user4GBcodeat0x*/
.quad0x00cffffff/*0x7buser4GBdataat0x*/
.quad0x00/*0x80TSSdescriptor*/
.quad0x00/*0x88LDTdescriptor*/
/*SegmentsusedforcallingPnPBIOS*/
.quad0x00c09a/*0x9032-bitcode*/
.quad0x00809a/*0x9816-bitcode*/
.quad0x00/*0xa016-bitdata*/
.quad0x00/*0xa816-bitdata*/
.quad0x00/*0xb016-bitdata*/
/*
*TheAPMsegmentshavebytegranularityandtheirbases
*andlimitsaresetatruntime.
*/
.quad0x00409a/*0xb8APMCScode*/
.quad0x00009a/*0xc0APMCS16code(16bit)*/
.quad0x00/*0xc8APMDSdata*/
.quad0x00/*0xd0-unused*/
.quad0x00/*0xd8-unused*/
.quad0x00/*0xe0-unused*/
.quad0x00/*0xe8-unused*/
.quad0x00/*0xf0-unused*/
.quad0x00/*0xf8-GDTentry31:double-faultTSS*/
.quad0x00cffa000000ffff/*0x73user4GBcodeat0x*/
我們把這個(gè)值展開(kāi)成二進(jìn)制:
根據(jù)上述對(duì)段描述符表項(xiàng)值的描述,可以得出如下結(jié)論:
B0-B15,B16-B31是0,表示基地址全為0.
L0-L15,L16-L19是1,表示段的上限全是0xffff.
G位是1表示段長(zhǎng)度單位均為4KB。
D位是1表示對(duì)段的訪問(wèn)都是32位指令
P位是1表示段在內(nèi)存中。
DPL是3表示特權(quán)級(jí)是3級(jí)
S位是1表示為代碼段或數(shù)據(jù)段
type為1010表示代碼段,可讀,可執(zhí)行,尚未收到訪問(wèn)
這個(gè)描述符指示了段從0地址開(kāi)始的整個(gè)4G虛存空間,邏輯地址直接轉(zhuǎn)換為線性地址。
所以在經(jīng)過(guò)段式映射后就把邏輯地址轉(zhuǎn)換成了線性地址,這也是在linux中,為什么邏輯地址等同于線性地址的原因了。
4.3頁(yè)式映射分析
現(xiàn)在進(jìn)入頁(yè)式映射的過(guò)程了,Linux系統(tǒng)中的每個(gè)進(jìn)程都有其自身的頁(yè)面目錄PGD,指向這個(gè)目錄的指針保存在每個(gè)進(jìn)程的mm_struct數(shù)據(jù)結(jié)構(gòu)
中。每當(dāng)調(diào)度一個(gè)進(jìn)程進(jìn)入運(yùn)行的時(shí)候,內(nèi)核都要為即將運(yùn)行的進(jìn)程設(shè)置好控制寄存器cr3,而MMU的硬件則總是從cr3中取得指向當(dāng)前頁(yè)面目
錄的指針。當(dāng)我們?cè)诔绦蛑幸D(zhuǎn)移到地址0x去的時(shí)候,進(jìn)程正在運(yùn)行,cr3早以設(shè)置好,指向我們這個(gè)進(jìn)程的頁(yè)面目錄了。先將線性
地址0x展開(kāi)成二進(jìn)制:
1000
對(duì)照線性地址的格式,可見(jiàn)更高10位為二進(jìn)制的,也就是十進(jìn)制的32,所以MMU就以32為下標(biāo)在其頁(yè)面目錄中找到其目錄項(xiàng)。這個(gè)
目錄項(xiàng)的高20位指向一個(gè)頁(yè)面表,CPU在這20位后添上12個(gè)0就得到頁(yè)面表的指針。找到頁(yè)面表以后,CPU再來(lái)看線性地址中的中間10位,
,即十進(jìn)制的72.于是CPU就以此為下標(biāo)在頁(yè)表中找相應(yīng)的表項(xiàng)。表項(xiàng)值的高20位指向一個(gè)物理內(nèi)存頁(yè)面,在后邊添上12個(gè)0就得到物
理頁(yè)面的開(kāi)始地址。假設(shè)物理地址在0x620230的,線性地址的更低12位為0x368.那么test()函數(shù)的入口地址就為0x620230+0x368=0x620238
linux c內(nèi)存映射的介紹就聊到這里吧,感謝你花時(shí)間閱讀本站內(nèi)容,更多關(guān)于linux c內(nèi)存映射,Linux C應(yīng)用中常用的內(nèi)存映射技術(shù),怎么理解linux下內(nèi)存的三級(jí)映射?請(qǐng)大俠指教,內(nèi)存映射的相關(guān)信息的信息別忘了在本站進(jìn)行查找喔。
香港服務(wù)器選創(chuàng)新互聯(lián),2H2G首月10元開(kāi)通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務(wù)提供商,擁有超過(guò)10年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn)。專業(yè)提供云主機(jī)、虛擬主機(jī)、域名注冊(cè)、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。
網(wǎng)頁(yè)標(biāo)題:LinuxC應(yīng)用中常用的內(nèi)存映射技術(shù)(linuxc內(nèi)存映射)
瀏覽路徑:http://fisionsoft.com.cn/article/dhdjddj.html


咨詢
建站咨詢
