1. 程式人生 > >Linux 記憶體對映函式 mmap()函式詳解

Linux 記憶體對映函式 mmap()函式詳解

start:要進行同步的對映的記憶體區域的起始地址。
length:要同步的記憶體區域的大小
flag:flags可以為以下三個值之一: 
MS_ASYNC : 請Kernel快將資料寫入。 
MS_SYNC : 在msync結束返回前,將資料寫入。 
MS_INVALIDATE : 讓核心自行決定是否寫入,僅在特殊狀況下使用

三、使用者空間和驅動程式的記憶體對映3.1、基本過程  首先,驅動程式先分配好一段記憶體,接著使用者程序通過庫函式mmap()來告訴核心要將多大的記憶體對映到核心空間,核心經過一系列函式呼叫後呼叫對應的驅動程式的file_operation中指定的mmap函式,在該函式中呼叫
remap_pfn_range()來建立對映關係。
3.2、對映的實現 首先在驅動程式分配一頁大小的記憶體,然後使用者程序通過mmap()將使用者空間中大小也為一頁的記憶體對映到核心空間這頁記憶體上。對映完成後,驅動程式往這段記憶體寫10個位元組資料,使用者程序將這些資料顯示出來。驅動程式:
#include <linux/miscdevice.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/moduleparam.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/ioctl.h>
 #include <linux/cdev.h>
 #include <linux/string.h>
 #include <linux/list.h>
 #include <linux/pci.h>
 #include <linux/gpio.h>
 
 
 #define DEVICE_NAME "mymap"
 
 
 static unsigned char array[10]={0,1,2,3,4,5,6,7,8,9};
 static unsigned char *buffer;
 
 
 static int my_open(struct inode *inode, struct file *file)
 {
     return 0;
 }
 
 
 static int my_map(struct file *filp, struct vm_area_struct *vma)
 {    
     unsigned long page;
     unsigned char i;
     unsigned long start = (unsigned long)vma->vm_start;
     //unsigned long end =  (unsigned long)vma->vm_end;
     unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
 
     //得到實體地址
     page = virt_to_phys(buffer);    
     //將使用者空間的一個vma虛擬記憶體區對映到以page開始的一段連續物理頁面上
     if(remap_pfn_range(vma,start,page>>PAGE_SHIFT,size,PAGE_SHARED))//第三個引數是頁幀號,由實體地址右移PAGE_SHIFT得到
         return -1;
 
     //往該記憶體寫10位元組資料
     for(i=0;i<10;i++)
         buffer[i] = array[i];
     
     return 0;
 }
 
 
 static struct file_operations dev_fops = {
     .owner    = THIS_MODULE,
     .open    = my_open,
     .mmap   = my_map,
 };
 
 static struct miscdevice misc = {
     .minor = MISC_DYNAMIC_MINOR,
     .name = DEVICE_NAME,
     .fops = &dev_fops,
 };
 
 
 static int __init dev_init(void)
 {
     int ret;    
 
     //註冊混雜裝置
     ret = misc_register(&misc);
     //記憶體分配
     buffer = (unsigned char *)kmalloc(PAGE_SIZE,GFP_KERNEL);
     //將該段記憶體設定為保留
     SetPageReserved(virt_to_page(buffer));
 
     return ret;
 }
 
 
 static void __exit dev_exit(void)
 {
     //登出裝置
     misc_deregister(&misc);
     //清除保留
     ClearPageReserved(virt_to_page(buffer));
     //釋放記憶體
     kfree(buffer);
 }
 
 
 module_init(dev_init);
 module_exit(dev_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("
[email protected]
");

應用程式:

相關推薦

Linux 記憶體對映函式 mmap函式

start:要進行同步的對映的記憶體區域的起始地址。 length:要同步的記憶體區域的大小 flag:flags可以為以下三個值之一: MS_ASYNC : 請Kernel快將資料寫入。 MS_SYNC : 在msync結束返回前,將資料寫入。 MS_INVALIDATE : 讓核心自行決定是否寫入,

程序間通訊——mmap函式

mmap可以把磁碟檔案的一部分直接對映到記憶體,這樣檔案中的位置直接就有對應的記憶體地址,對檔案的讀寫可以直接使用指標來做,而不需要read/write函式。 void *mmap(void *addr,size_t length,int port,int f

Xshell6遠程訪問linux及Xftp6遠程針對linux系統中文件操作附圖文

all 遠程訪問 要點 href show gb2312 editor apt-get 用戶名   1、首先我們需要先做好前期準備工作,需要到XManager6官網上將Xshell及Xftp下載並安裝,安裝過程一直下一步就好了。這裏是其官網:http://www.xshel

InputStream read方法

  在Java7中,InputStream被定義為一個抽象類,相應的,該類下的read()方法也是一個抽象方法,這也就意味著必須有一個類繼承InputStream並且實現這個read方法。   查閱Java7 API,我們可以看到,在InputStream中定

socket引數

sock_raw(注意一定要在root下使用)原始套接字程式設計可以接收到本機網絡卡上的資料幀或者資料包,對與監聽網路的流量和分析是很有作用的.一共可以有3種方式建立這種socket 1.socket(AF_INET, SOCK_RAW, IPPROTO_TCP|IPP

transform用法

/*//////////////////////////////// template < class InputIterator, class OutputIterator, class UnaryOperator > OutputIt

linux中fork函式原創!!例項講解

    所以打印出結果:    0 parent 2043 3224 3225    0 child  3224 3225    0    第二步:假設父程序p3224先執行,當進入下一個迴圈時,i=1,接著執行fork,系統中又新增一個程序p3226,對於此時的父程序,p2043->p3224(當前程

Linux 程序間通訊方式 pipe函式

Linux 程序間通訊方式有以下幾種: 1-》管道(pipe)和有名管道(fifo). 2-》訊息佇列 3-》共享記憶體 4-》訊號量 5-》訊號(signal) 6-》套接字(sicket) 在這裡我們看一下第一種====管道(pipe)。有名管道(fifo)見其它文章。

Linux伺服器程式設計之:truncate函式+案例說明

1.依賴標頭檔案 #include<unistd.h> #include<sys/types.h> 2.函式定義: int truncate(const char *path,off_t length); int ftruncate(int fd,o

Linux下getopt()、getopt_long、getopt_long_only函式的簡單使用

我們的主角----getopt()函式。英雄不問出處,getopt()函式的出處就是unistd.h標頭檔案(哈哈),寫程式碼的時候千萬不要忘記把他老人家include上。再來看一下這傢伙的原型(不是六耳獼猴):int getopt(int argc,char * const

linux中fork函式

【IT168 技術】  一個程序,包括程式碼、資料和分配給程序的資源。fork()函式通過系統呼叫建立一個與原來程序幾乎完全相同的程序,也就是兩個程序可以做完全相同的事,但如果初始引數或者傳入的變數不同,兩個程序也可以做不同的事。   一個程序呼叫fork()函式後,系

Pandas 讀excel函式read_excel官方文件

http://pandas.pydata.org/pandas-docs/stable/io.html#reading-excel-files Excel files The read_excel() method can read Excel 2003 (.xls) and Excel 2

pandas stack函式可用於轉置,但功能絕不僅僅限於轉置。真正的轉置是df.T

實際上轉置是df.T http://pandas.pydata.org/pandas-docs/stable/reshaping.html#reshaping-and-pivot-tables  Reshaping and Pivot Tables R

【轉】Python 內建函式 locals 和globals

Python 內建函式 locals() 和globals() 轉自: https://blog.csdn.net/sxingming/article/details/52061630

模式對話方塊和非模式對話方塊、accept函式、exec函式,Accepted訊號區別

一.非模式對話方塊   非模式對話方塊是和同一個程式中其它視窗操作無關的對話方塊。在字處理軟體中查詢和替換對話方塊通常是非模式的來允許同時與應用程式主視窗和對話方塊進行互動。呼叫show()來顯示非模式對話方塊。show()立即返回,這樣呼叫程式碼中的控制流將會繼續。   非模式

Python:range函式

range() 函式 range(stop) 用來生成0~stop區間內的整數,直到stop為 止(不包含stop) range(start, stop[,step]) 用來生成start~stop區 間內的整數,直到stop為止(不包含s

np.nonzero函式用法

返回陣列中不為0的元素的下標。 陣列中元素可為布林、整型和浮點型,返回值為元祖 一.一維陣列 1.陣列元素為布林型別 a=np.array([True,False,True,False]) b=np.nonzero(a) print(b) 輸出結果為(array([0, 2], dtype

python中的encode和decode函式

前言: 我們知道,計算機是以二進位制為單位的,也就是說計算機只識別0和1,也就是我們平時在電腦上看到的文字,只有先變成0和1,計算機才會識別它的意思。這種資料和二進位制的轉換規則就是編碼。計算機的發展中,有ASCII碼,GBK,Unicode,utf-8編碼。我們先從編碼的發展史瞭解一下編碼的進化過程。

python中的open函式

定義: python open() 函式用於開啟一個檔案,建立一個 file 物件,相關的方法才可以呼叫它進行讀寫 引數: 模式 描述 r 以只讀方式開啟檔案。檔案的指標將會放在檔案的開頭。這是預設模式。 rb 以

函式指標指向函式的指標和指標函式的區別

函式指標和指標函式的區別: 一、【函式指標】 在程式執行中,函式程式碼是程式的演算法指令部分,它們和陣列一樣也佔用儲存空間,都有相應的地址。可以使用指標變數指向陣列的首地址,也可以使用指標變數指向函式程式碼的首地址,指向函式程式碼首地址的指標變數稱為函式指標。 1、函式指標定義 函式型別(*