最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

一篇帶你深入理解mmap 0拷貝技術(shù)(從這五點(diǎn)入手~)

2022-05-30 14:57 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

1、前言

  • 環(huán)境:處理器架構(gòu):arm64內(nèi)核源碼:linux-5.11ubuntu版本:20.04.1代碼閱讀工具:vim+ctags+cscope

  • 我們知道,linux系統(tǒng)中用戶(hù)空間和內(nèi)核空間是隔離的,用戶(hù)空間程序不能隨意的訪問(wèn)內(nèi)核空間數(shù)據(jù),只能通過(guò)中斷或者異常的方式進(jìn)入內(nèi)核態(tài),一般情況下,我們使用copy_to_user和copy_from_user等內(nèi)核api來(lái)實(shí)現(xiàn)用戶(hù)空間和內(nèi)核空間的數(shù)據(jù)拷貝,但是像顯存這樣的設(shè)備如果也采用這樣的方式就顯的效率非常底下,因?yàn)橛脩?hù)經(jīng)常需要在屏幕上進(jìn)行繪制,要消除這種復(fù)制的操作就需要應(yīng)用程序直接能夠訪問(wèn)顯存,但是顯存被映射到內(nèi)核空間,應(yīng)用程序是沒(méi)有訪問(wèn)權(quán)限的,如果顯存也能同時(shí)映射到用戶(hù)空間那就不需要拷貝操作了,于是字符設(shè)備中提供了mmap接口,可以將內(nèi)核空間映射的那塊物理內(nèi)存再次映射到用戶(hù)空間,這樣用戶(hù)空間就可以直接訪問(wèn)不需要任何拷貝操作,這就是我們今天要說(shuō)的0拷貝技術(shù)。

  • 下面是正常情況下用戶(hù)空間和內(nèi)核空間數(shù)據(jù)訪問(wèn)圖示:

【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺(jué)得比較好的學(xué)習(xí)書(shū)籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。∏?00名進(jìn)群領(lǐng)取,額外贈(zèng)送一份價(jià)值699的內(nèi)核資料包(含視頻教程、電子書(shū)、實(shí)戰(zhàn)項(xiàng)目及代碼)? ??

2.、體驗(yàn)一下

  • 首先我們通過(guò)一個(gè)例子來(lái)感受一下:

  • 驅(qū)動(dòng)代碼:

注:驅(qū)動(dòng)代碼中使用misc框架來(lái)實(shí)現(xiàn)字符設(shè)備,misc框架會(huì)處理如創(chuàng)建字符設(shè)備,創(chuàng)建設(shè)備等通用的字符設(shè)備處理,我們只需要關(guān)心我們的實(shí)際的邏輯即可(內(nèi)核中大量使用misc設(shè)備框架來(lái)使用字符設(shè)備操作集如ioctl接口,像實(shí)現(xiàn)系統(tǒng)虛擬化kvm模塊,實(shí)現(xiàn)安卓進(jìn)程間通信的binder模塊等)。 0copy_demo.c

應(yīng)用代碼:test.c

Makefile文件:

編譯驅(qū)動(dòng)代碼和應(yīng)用代碼,然后拷貝到qemu中運(yùn)行:

  • 執(zhí)行了以上步驟可以發(fā)現(xiàn)最終內(nèi)核中出現(xiàn)了我在應(yīng)用程序中寫(xiě)入的“hello world!!!“ 字符串,應(yīng)用程序也能成功讀取到(當(dāng)然本文講解的0拷貝實(shí)現(xiàn)的驅(qū)動(dòng)接口是mmap,而我們讀取使用的是read接口,里面我們用copy_to_user來(lái)實(shí)現(xiàn)的,當(dāng)然我們可以直接操作mmap映射的內(nèi)存不需要任何拷貝操作)。

  • 查看應(yīng)用程序的內(nèi)存映射發(fā)現(xiàn),/dev/misc_dev設(shè)備被映射到了ffff8aa91000-ffff8aa92000這段用戶(hù)空間地址范圍,而且權(quán)限為rw-s(可讀可寫(xiě)共享)。

  • 寫(xiě)到這里可能大家還是有點(diǎn)不明白那我來(lái)解釋下:

  1. 用戶(hù)空間不能直接訪問(wèn)內(nèi)核空間數(shù)據(jù)(不能直接讀寫(xiě)),一旦訪問(wèn)發(fā)生缺頁(yè)異常,產(chǎn)生段錯(cuò)誤,必須通過(guò)read這樣的接口來(lái)訪問(wèn),而read這樣的接口會(huì)通過(guò)系統(tǒng)調(diào)用的方式寫(xiě)入到內(nèi)核態(tài),然后通過(guò)copy_to_user這樣的內(nèi)核api來(lái)拷貝內(nèi)核空間數(shù)據(jù)到用戶(hù)空間之后才能正常訪問(wèn)。

  2. 通過(guò)mmap這種方式之后,用戶(hù)進(jìn)程可以直接訪問(wèn)這塊內(nèi)存,memcpy訪問(wèn)的也只不過(guò)是用戶(hù)空間地址,由于訪問(wèn)的時(shí)候已經(jīng)分配好了物理頁(yè)面和建立好了物理頁(yè)到虛擬頁(yè)的映射,所有不會(huì)發(fā)生缺頁(yè)異常,也不會(huì)發(fā)生用戶(hù)態(tài)到內(nèi)核態(tài)的陷入動(dòng)作。

  3. 用戶(hù)態(tài)進(jìn)程正常訪問(wèn)內(nèi)核態(tài)數(shù)據(jù)需要首先通過(guò)系統(tǒng)調(diào)用等方式陷入內(nèi)核,進(jìn)行數(shù)據(jù)拷貝,然后再次回到用戶(hù)態(tài),用戶(hù)態(tài)和內(nèi)核態(tài)直接的進(jìn)出需要進(jìn)行上下文切換,需要2次上下文切換,需要一定的開(kāi)銷(xiāo),而mmap映射好之后以后訪問(wèn)都不需要進(jìn)行上下文切換。

  4. mmap映射這種方法由于物理頁(yè)面通過(guò)頁(yè)面共享更加節(jié)省內(nèi)存,而用戶(hù)態(tài)和內(nèi)核態(tài)內(nèi)存拷貝需要兩份物理頁(yè)面。

3、實(shí)現(xiàn)原理

  • 我們發(fā)現(xiàn)通過(guò)mmap映射之后,我們?cè)趹?yīng)用程序中可以直接讀寫(xiě)這段內(nèi)存,不需要任何用戶(hù)空間和內(nèi)核空間的拷貝動(dòng)作,大大提高了內(nèi)存訪問(wèn)效率,那么就是是如何實(shí)現(xiàn)的呢?下面我們來(lái)揭開(kāi)它神秘的面紗:

  • 實(shí)現(xiàn)0拷貝功不可沒(méi)的是mmap接口中的remap_pfn_range內(nèi)核api,它將內(nèi)核空間映射的物理內(nèi)存重新映射到了用戶(hù)空間,下面我們來(lái)看這個(gè)函數(shù)的實(shí)現(xiàn):remap_pfn_range函數(shù)參數(shù)如下:

  • vma為需要映射的進(jìn)程的vma(進(jìn)程調(diào)用mmap的時(shí)候內(nèi)核會(huì)找到一個(gè)合適的vma), addr為vma中的一個(gè)起始映射地址(這是用戶(hù)空間的一個(gè)虛擬地址),pfn為頁(yè)幀號(hào)(在驅(qū)動(dòng)的mmap接口中會(huì)將內(nèi)核空間的地址轉(zhuǎn)化為物理地址的頁(yè)幀號(hào)),size為需要映射的大小,prot為映射的權(quán)限(一般取mmap時(shí)傳遞的權(quán)限如rw)

  • remap_pfn_range實(shí)現(xiàn)主要如下代碼段:

  • 解釋下:remap_pfn_range函數(shù)會(huì)查找進(jìn)程的頁(yè)表,然后填寫(xiě)頁(yè)表,會(huì)將映射的物理頁(yè)幀號(hào)和訪問(wèn)權(quán)限填寫(xiě)到進(jìn)程的對(duì)應(yīng)頁(yè)表中,這會(huì)遍歷進(jìn)程的各級(jí)頁(yè)表找到最終的頁(yè)表項(xiàng)然后進(jìn)行填寫(xiě),具體過(guò)程自行查看代碼。

  • 我們需要注意的是:

  1. 一般情況下,用戶(hù)程序調(diào)用mmap只是申請(qǐng)?zhí)摂M內(nèi)存(即是獲得一塊沒(méi)有使用用戶(hù)空間內(nèi)存,使用vma描述),實(shí)際的物理頁(yè)表都是通過(guò)進(jìn)程訪問(wèn)的時(shí)候缺頁(yè)異常的方式來(lái)申請(qǐng)的,但是本場(chǎng)景中是物理頁(yè)面已經(jīng)申請(qǐng)好了,進(jìn)程訪問(wèn)時(shí)不會(huì)再發(fā)生缺頁(yè)異常,不會(huì)申請(qǐng)物理頁(yè)面。

  2. 同樣,物理頁(yè)面到用戶(hù)空間虛擬頁(yè)面的映射也在調(diào)用mmap的時(shí)候,驅(qū)動(dòng)調(diào)用mmap接口的remap_pfn_range映射好了,也不需要在訪問(wèn)的時(shí)候發(fā)生缺頁(yè)異常來(lái)建立映射。所以,只要用戶(hù)進(jìn)程通過(guò)mmap映射之后就可以正常訪問(wèn),訪問(wèn)過(guò)程中不會(huì)發(fā)生缺頁(yè)異常,映射虛擬頁(yè)對(duì)應(yīng)的物理頁(yè)面已經(jīng)在驅(qū)動(dòng)中申請(qǐng)好映射好。

  • 下面給出mmap映射原理的圖示:

4、應(yīng)用場(chǎng)景

  • 最后,我們來(lái)看下使用framebuffer的lcd對(duì)0拷貝的使用情況:


lcd驅(qū)動(dòng)代碼中會(huì)設(shè)置好最終注冊(cè)framebuffer:

  • 可以看到當(dāng)系統(tǒng)支持framebuffer設(shè)備時(shí),在fbmem_init中會(huì)創(chuàng)建framebuffer設(shè)備類(lèi)關(guān)聯(lián)字符設(shè)備操作集fb_fops,lcd的驅(qū)動(dòng)代碼中會(huì)調(diào)用register_framebuffer創(chuàng)建framebuffer設(shè)備(就會(huì)創(chuàng)建出了/dev/fdx 設(shè)備節(jié)點(diǎn)),應(yīng)用程序就可以通過(guò)mmap來(lái)映射framebuffer設(shè)備到用戶(hù)空間,然后進(jìn)行屏幕繪制操作,不需要任何數(shù)據(jù)拷貝。

5.總結(jié)

  • 可以看的出,通過(guò)mmap實(shí)現(xiàn)0拷貝非常簡(jiǎn)單,只需要在驅(qū)動(dòng)的mmap接口中調(diào)用remap_pfn_range來(lái)將內(nèi)核空間映射的那塊物理頁(yè)再次映射到用戶(hù)空間即可,這就實(shí)現(xiàn)了用戶(hù)空間和內(nèi)核空間的數(shù)據(jù)共享,這和用戶(hù)進(jìn)程之間的共享內(nèi)存機(jī)制非常相似,都需要操作進(jìn)程的頁(yè)表將這段物理內(nèi)存映射到進(jìn)程虛擬地址空間。


一篇帶你深入理解mmap 0拷貝技術(shù)(從這五點(diǎn)入手~)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
鱼台县| 内丘县| 视频| 东安县| 铜鼓县| 河池市| 白城市| 黄骅市| 岢岚县| 万山特区| 临清市| 巴彦县| 海淀区| 台州市| 维西| 昔阳县| 壶关县| 台前县| 缙云县| 镇赉县| 通城县| 颍上县| 正定县| 洪洞县| 静安区| 黄石市| 肃北| 宣武区| 天门市| 扶沟县| 岳普湖县| 峡江县| 海门市| 文成县| 江油市| 交口县| 宜兴市| 辛集市| 金坛市| 都兰县| 乌苏市|