Chapter 15 MMAP與DMA.

Slides:



Advertisements
Similar presentations
第一單元 建立java 程式.
Advertisements

LinkIt ONE開發板的簡介.
OSDI.
Chapter 13 MMAP與DMA.
Chapter 15 MMAP與DMA 許名宏.
Chapter 6 時序.
校園網路管理實電務 電子計算機中心 謝進利.
Linux File System Li-Shien Chen.
陳維魁 博士 儒林圖書公司 第九章 資料抽象化 陳維魁 博士 儒林圖書公司.
Hadoop 單機設定與啟動 step 1. 設定登入免密碼 step 2. 安裝java step 3. 下載安裝Hadoop
主題五 CPU Learning Lab.
題目:十六對一多工器 姓名:李國豪 學號:B
TCP協定 (傳輸層).
第一篇 Unix/Linux 操作介面 第 1 章 Unix/Linux 系統概論 第 2 章 開始使用 Unix/Linux
中国科学技术大学计算机系 陈香兰(0512- ) Spring 2011
第二章 LINUX存储管理 LINUX的分页管理机制.
Google Data API Spreadsheet
C 程式設計— 檔案處理 台大資訊工程學系 資訊系統訓練班.
C語言簡介 日期 : 2018/12/2.
類別(class) 類別class與物件object.
SQL Stored Procedure SQL 預存程序.
CH.8 硬體管理.
ASP.NET基本設計與操作 建國科技大學 資管系 饒瑞佶 2007年.
中国科学技术大学计算机系 陈香兰(0512- ) Spring 2011
TCP/IP介紹 講師:陳育良 2018/12/28.
2017 Operating Systems 作業系統實習 助教:陳主恩、林欣穎 實驗室:720A.
Linux操作系统分析 中国科学技术大学计算机系 陈香兰(0512- )
雲端運算的基石(2) 虛擬化技術實作(XP篇─上)
檔案與磁碟的基本介紹.
Java 程式設計 講師:FrankLin.
Ch9 Communicating with Hardware
私立南山高中 信息組 電腦研習 電腦資料的備份 中華民國 99年4月20日 星期二.
Chap3 Linked List 鏈結串列.
網路安全技術 OSI七層 學生:A 郭瀝婷 指導教授:梁明章.
Chapter 13 MMAP與DMA.
Topic Introduction—RMI
第一單元 建立java 程式.
第一章 直角坐標系 1-3 函數圖形.
第9章 虛擬記憶體 (virtual memory)
EPSON 點矩陣印表機LQ-300+ 發票紙張格式設定.
Chapter 7 掌控記憶體.
緩衝區溢位攻擊 學生:A 羅以豪 教授:梁明章
SOCKET( ).
C qsort.
Chapter 7 掌控記憶體.
第六章 記憶體.
MicroSim pspice.
第二章 类型、对象、运算符和表达式.
Linux CentOS 6.0 安裝教學 講師:趙力緯.
流程控制:Switch-Case 94學年度第一學期‧資訊教育 東海大學物理系.
陣列與結構.
Chapter 15 檔案存取 LabVIEW中的檔案存取函數也可將程式中的資料儲存成Excel或Word檔。只要將欲存取的檔案路徑位址透過LabVIEW中的路徑元件告訴檔案存取函數後,LabVIEW便可將資料存成Excel或Word檔;當然也可以將Excel或Word檔的資料讀入LabVIEW的程式中。
一、簡介 電腦硬體設計:純硬體電路(hardware)及韌體電 路(firmware)兩種方式。
2018 Operating Systems 作業系統實習 助教:林欣穎 實驗室:720A.
C 程式設計— 檔案處理 台大資訊工程學系 資訊系統訓練班.
資料表示方法 資料儲存單位.
第十二章 位运算.
MultiThread Introduction
第四章 陣列、指標與參考 4-1 物件陣列 4-2 使用物件指標 4-3 this指標 4-4 new 與 delete
中国科学技术大学计算机系 陈香兰(0551- ) Spring 2009
獨孤派作業系統 main memory 中正大學 作業系統實驗室 指導教授:羅習五.
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
SQLite資料庫 靜宜大學資管系 楊子青.
Chapter 4 Multi-Threads (多執行緒).
快取映射 之直接對映 計算整理.
Develop and Build Drives by Visual C++ IDE
Department of Computer Information Science, NCTU
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
InputStreamReader Console Scanner
Presentation transcript:

Chapter 15 MMAP與DMA

15.1 Linux的記憶體管理 主要是描述用於控管記憶體的各種資料結構,相當冗長.有了必要的基礎知識後,我們就可以開始使用這些結構.

15.1.1 位址的分類(1/4) 作業系統的分類上,Linux是一種虛擬記憶系統. 虛擬記憶系統將邏輯世界(軟體)與現實世界(硬體)分隔開來,最大的好處是軟體可配置的空間超過RAM的實際容量. 另一項優點是核心可在執行期改變行程的部分記憶空間. Linux系統上不只有兩種位址(虛擬、實體),而且每種位址都有其特殊用途. 但核心原始程式裡沒有明確定義何種位址適用何種情況,所以必須相當謹慎小心.

15.1.1 位址的分類(3/4) 使用者虛擬位址(User Virtual Address) 簡稱為虛擬位址,位址寬度隨CPU架構而定 實體位址(Physical Address) CPU與記憶體間的位址,寬度依CPU而定,但不一定與CPU暫存器相符 匯流排位址(Bus Address) 週邊匯流排與記憶體的位址,具有高度的平台相依性 核心邏輯位址(Kernel Logical Address) 構成核心的正常位址空間,他們對應到所有主記憶體,而且通常被當作實體位址來使用。邏輯位址與實體位址只差距一段固定偏移量,通常存放在unsigned long或void *型別變數上。kmalloc()所傳回的記憶體,就是以邏輯位址來定位。 核心虛擬位址(Kernel Virtual Address) 核心虛擬位址跟邏輯位址不同之處,在於核心虛擬位址與實體位址不一定有直接對應關係,虛擬位址通常存放在指標變數中。vmalloc()配置而來的記憶體位址是以虛擬位址來表示。

15.1.1 位址的分類(4/4) <asm/page.h>定義了兩個可換算位址的巨集. __va()可將實體位址換算回邏輯位址,但僅限於低記憶體的實體位址才有效,因為高記憶體沒有邏輯位址

15.1.2 高低記憶體 核心邏輯位址與核心虛擬位址之間的差異,再配備超大量記憶體的32-bits系統上才凸顯出來. 低記憶體(Low memory) 存在kernel-space裡,可用邏輯位址來定位的記憶體 高記憶體(High memory) 沒有邏輯位址的記憶體,因為系統上安裝超過32-bits定址範圍的實體記憶體. 高低記憶體之間的分界線 核心在開機期間依據BIOS提供的資訊來決定的.在i386系統,分界通常位於1GB以下.這是核心自己設下的限制,因為核心必須將32-bit位址空間劃分成kernel-space與user-space兩大部份.

15.1.3 記憶體對應表與struct page(1/2) page結構紀錄了關於實體記憶頁的一切資訊.系統上的每一頁記憶體,都有一個專屬的struct page,幾個重要欄位如下. atomic_t count; 此記憶頁的用量計次.當count降為0時,記憶頁會被釋放回自由串列. void *virtual; 本記憶頁對應的核心虛擬位址;若無對應的虛擬位址則指向NULL. unsigned long flags; 一組描述記憶頁狀態的位元旗標.如PG_locked、PG_reserved. /usr/src/kernels/linux-2.6.36/include/linux/mm.h

15.1.3 記憶體對應表與struct page(2/2) 為了方便在struct page指標與虛擬位址之間轉換,Linux定義了一組方便的函式與巨集: struct page *virt_to_page(void *kaddr); 將核心邏輯位址轉換成對應的struct page指標. void *page_address(struct page *page); 傳回指定的page的核心虛擬位址.位於記憶體的記憶頁除非已事先映射到虛擬位址空間,否則沒有虛擬位址. #include <linux/highmem.h> void *kmap(struct page *page); kmap()可傳回系統上任何記憶頁的核心虛擬位址. Page在低記憶體→傳回該記憶頁的邏輯位址 Page在高記憶體→將他映射到特殊的虛擬空間 void kunmap(struct page *page); 將kmap()所建立的特殊對應解除 /usr/src/kernels/linux-2.6.36/include/linux/highmem.h

15.1.4 虛擬記憶區(Virtual Memory Areas)(1/6) 核心需要一個較高層級的機制,才能處理行程所見到的記憶體佈局.在Linux,這機制稱為虛擬記憶區(virtual memory areas),通常簡稱為區域或VMA. 用來管理使用者行程的虛擬位址空間的各個區域 行程空間的虛擬位址空間,由下列區域構成: 一個存放程式碼(executable binary)的區域,通常稱為text 多個存放資料的區域 每一個有效的記憶體對映(memory mapping),各有一個區域.

15.1.4 虛擬記憶區(Virtual Memory Areas)(2/6) 例:以下是init行程VMA的分布情形。cat /proc/1/maps 08048000-0804e000 r-xp 00000000 03:01 64652 /sbin/init text 0804e000-0804f000 rw-p 00006000 03:01 64652 /sbin/init data 0804f000-08053000 rwxp 00000000 00:00 0 zero-mapped BSS 40000000-40015000 r-xp 00000000 03:01 96278 /lib/ld-2.3.2.so text 40015000-40016000 rw-p 00014000 03:01 96278 /lib/ld-2.3.2.so data 40016000-40017000 rw-p 00000000 00:00 0 BSS for ld.so 42000000-4212e000 r-xp 00000000 03:01 80290 /lib/tls/libc-2.3.2.so text 4212e000-42131000 rw-p 0012e000 03:01 80290 /lib/tls/libc-2.3.2.so data 42131000-42133000 rw-p 00000000 00:00 0 BSS for libc bffff000-c0000000 rwxp 00000000 00:00 0 Stack segment ffffe000-fffff000 ---p 00000000 00:00 0 vsyscall page 各欄位的格式如下: start-end|perm|offset|major:minor|inode|imagename

15.1.4 虛擬記憶區(Virtual Memory Areas)(3/6) 上面每一欄除了imagename之外,都分別對應到struct vm_area_struct裡的欄位,這些欄位意義如下: start-end VMA前後邊界的虛擬位址 perm VMA的存取位元遮罩(r、w、x、p/s) offset 檔案從何處開始映射到此VMA的起點 major:minor 持有映射檔的裝置的主次編號 inode 被映射檔案的inode編號 imagename 被映射檔案(通常是可執行檔)的名稱 要實作mmap作業方法的驅動程式,必須填寫一個VMA結構,放在要求映射裝置的行程的位址空間裡

15.1.4 虛擬記憶區(Virtual Memory Areas)(4/6) 我們看看struct vm_area_struct(定義在<linux/mm.h>)裡幾個最重要的欄位(很相似/proc/*/maps),因為驅動程式的mmap作業方法可能會需要用到這些欄位. 驅動程式不能任意建立新的VMA,否則會破壞整個組織(串列與樹狀). unsigned long vm_start; unsigned long vm_end; 此VMA涵蓋的虛擬位址範圍. struct file *vm_file; 如果VMA的映射對象是檔案,則vm_file指向該檔案的struct file結構.

14.1.4 虛擬記憶區(Virtual Memory Areas)(5/6) unsigned long vm_pgoff; 此區域在檔案的相對位置(以page為單位). unsigned long vm_flags; 一組描述VMA屬性的旗標.VM_IO表示此VMA映射到I/O region, VM_RESERVED要求記憶體管理系統不要將此VMA交換到磁碟上. struct vm_operations_struct *vm_ops; 一組可供核心用來操作VMA的函式. void *vm_private_data; 供驅動程式用於儲存私有資訊的欄位.

15.1.4 虛擬記憶區(Virtual Memory Areas)(6/6) vm_operations_struct它紀錄了處理行程記憶體所需的三項作業方法:open、close與nopage如下所述. void (*open)(struct vm_area_struct *area); 核心會呼叫open作業方法,讓實作VMA的子系統有機會初始VMA 調整用量計次...等. void (*close)(struct vm_area_struct *area); 當VMA被摧毀,核心會呼叫它的close作業方法. struct page *(*nopage)(struct vm_area_struct *vma,unsigned long address,int type); 行程試圖讀取某個VMA記憶頁,但記憶頁不在主記憶體裡,則VMA的nopage作業方法會被呼叫。nopage從磁碟上的交換區讀回記憶頁內容,然後傳回一個指向實體記憶頁的struct page指標.若VMA沒定義自己的nopage方法,則核心會配置一個空的記憶頁

15.2 mmap作業方法(1/2) 就驅動程式的觀點而言,記憶映射可用來提供直接存取裝置記憶體的能力給user-space應用程式. 觀察X Window System server的VMA如何映射到/dev/mem,有助於理解mmap()系統呼叫的典型用法. cat /proc/731/maps 000a0000-000c0000 rwxs 000a0000 03:01 282652 /dev/mem 000f0000-00100000 r-xs 000f0000 03:01 282652 /dev/mem 00400000-005c0000 r-xp 00000000 03:01 1366927 /usr/X11R6/bin/Xorg 006bf000-006f7000 rw-p 001bf000 03:01 1366927 /usr/X11R6/bin/Xorg 2a95828000-2a958a8000 rw-s fcc00000 03:01 282652 /dev/mem 2a958a8000-2a9d8a8000 rw-s e8000000 03:01 282652 /dev/mem a0000:VGA卡的視訊記憶體的標準位置 e8000000:位於系統記憶體的頂端,直接對應到顯卡上的視訊記憶體 從/proc/iomem也可看出顯示卡上的各段I/O記憶體

15.2 mmap作業方法(2/2) 由於X server時常需要傳輸大量資料到視訊記憶體,如果將視訊記憶體直接映射到user-space,則應用程式可以直接填寫視訊記憶體,所以傳輸效率得以大幅提升. mmap作業方法屬於file_operations結構的一部分,由mmap()系統呼叫觸發. void *mmap(void *start,size_t length,int port,int flags,int fd,off_t offset); int (*mmap)(struct filp *filp,struct vm_area_struct *vma); 要支援mmap()系統呼叫的驅動程式,只需對該段虛擬位址範圍建立適當的分頁表 製作分頁表:全部交給remap_page_ranfe()函式一次搞定.

15.2.1 使用remap_pfn_range() 要將某段虛擬位址映射到某段實體位址,必須另外產生新的分頁表,這個任務就交給它來完成. int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_addr,unsigned long pfn, unsigned long size, pgprot_t); 映射成功傳回0,失敗傳回錯誤碼 vma 記憶頁所要映射到的VMA virt_addr 要被重新映射的虛擬位址 size 映射區規模(byte為單位) prot 新VMA的保護方式.驅程能使用 vma->vm_page_port找到的值.

15.2.2 簡單的mmap實作 簡單線性的映射作法,讓應用程式可透過user-space的某段虛擬位址來存取裝置記憶體 static int simple_remap_mmap(struct file *filp, struct vm_area_struct *vma) { if (remap_pfn_range(vma, vma->vm_start, vm->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; vma->vm_ops = &simple_remap_vm_ops; simple_vma_open(vma); return 0; }

15.2.3 增添新的VMA作業方法 void simple_vma_open(struct vm_area_struct *vma) { printk(KERN_NOTICE "Simple VMA open, virt %lx, phys %lx\n", vma->vm_start, vma->vm_pgoff << PAGE_SHIFT); } void simple_vma_close(struct vm_area_struct *vma) printk(KERN_NOTICE "Simple VMA close.\n"); static struct vm_operations_struct simple_remap_vm_ops = { .open = simple_vma_open, .close = simple_vma_close, };

15.3直接I/O 大部分的I/O作業,透過kernel-space的緩衝區做緩衝,隔離了user-space與實際裝置。好處:讓程式比較好寫,提升效能。 但在傳輸大量資料時,讓user-space直接與裝置I/O做溝通反而會比較好。

15.3.1實做直接I/O的關鍵函式 宣告於<linux/mm.h> int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start, int len, int write, int force, struct page **pages, struct vm_area_struct **vmas); struct task_struct *tsk :指向要執行I/O的task_struct, struct mm_struct *mm:指向的mm_struct即是形成的虛擬位址空間的所有VMA unsigned long start:user-space緩衝區的起始位址 int len:該緩衝區的長度 int write:非零值,映射的記憶頁是供write存取用 int force:不理會指定記憶頁的保護旗標,對驅動程式應設為零 struct page **pages:指向user-space緩衝區的struct page串列 此函式的回傳值:實際映射的記憶頁數量。

15.3.2釋放記憶頁 完成直接I/O作業→釋放user-space記憶頁 1.檢查記憶頁是否為保留頁:PageReserved(); 2.若改變了記憶頁內容→使用SetPageDirty(struct page *page)將記憶頁做標記,否則核心會直接釋放該記憶頁,而不寫回儲存裝置 3.將page從page cache釋放→page_cache_release(struct page *page); 無論是否有改變記憶頁內容,最後都應做釋放的動作! <linux/page-flags.h>:SetPageDirty(struct page *page)

15.3.3非同步I/O 非同步I/O讓user-space可不必等到I/O作業完成,就發起其他I/O作業。