導航:首頁 > 操作系統 > linuxmmap實現

linuxmmap實現

發布時間:2022-07-31 13:32:57

A. linux怎麼用mmap映射物理地址

存儲管理單元 MMU(Memory Manage Unit, 存儲管理單元)和物理內存之間進行地址轉換 在CPU和物理內存之間進行地址轉換,將地址從邏輯空間映映射到物理地址空間。 選 B

B. linux c怎麼實現從文件的最後一行一行向前讀文件

下面的例子使用mmap讀最後20行(假設最後20行不會超過1024位元組)
/*-
* Copyright (C), 1988-2014, mymtom
*
* vi:set ts=4 sw=4:
*/
#ifndef lint
static const char rcsid[] = "$Id$";
#endif /* not lint */
/**
* @file last20.c
* @brief
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
char *memchrr(const void *v1, const char *v2, int c)
{
char *s1, *s2;
char *p;
s1 = (char *)v1;
s2 = (char *)v2;
for (p = s2; p >= s1; --p) {
if (*p == c)
return p;
}
return NULL;
}
#define READSIZE 1024
int main(int argc, char *argv[])
{
int ret;
FILE *fp;
char *addr;
size_t len;
int prot;
int flags;
int fd;
off_t off;
off_t rem;
long pagesize;
struct stat buf;
pagesize = sysconf(_SC_PAGESIZE);
fp = fopen("last20.c", "rb");
fd = fileno(fp);
ret = fstat(fd, &buf);
if (buf.st_size <= READSIZE || buf.st_size <= pagesize) {
off = 0;
len = buf.st_size;
} else {
off = buf.st_size - READSIZE;
rem = off % pagesize;
off = off - rem;
len = READSIZE + rem;
}
/*
printf("size=%d READSIZE=%d off=%d len=%d\n",
(int)buf.st_size, (int)READSIZE, (int)off, (int)len);
*/
prot = PROT_READ;
flags = MAP_PRIVATE;
addr = mmap(NULL, len, prot, flags, fd, off);
fclose(fp);
{
int i, n;
char *head, *tail;
size_t size;
char line[1024];
tail = addr + len - 1;
n = 20;
for (i = 0; i < n; ++i) {
head = memchrr(addr, tail - 1, '\n');
if (head == NULL) {
size = tail - addr;
memcpy(line, addr, size);
line[size] = '\0';
} else {
size = tail - head - 1;
memcpy(line, head + 1, size);
line[size] = '\0';
tail = head;
}
printf("%s\n", line);
if (head == NULL) {
break;
}
}
}
munmap(addr, len);
return 0;
}
運行結果為:
./last20 | tac | cat -n
line[size] = '\0';
} else {
size = tail - head - 1;
memcpy(line, head + 1, size);
line[size] = '\0';
tail = head;
}
printf("%s\n", line);
if (head == NULL) {
break;
}
}
}
munmap(addr, len);
return 0;
}

C. 如何在linux下用mmap映射超大文件,並讀

manpage裡面的東西:

void *mmap(void *start, size_t length, int prot, int flags,
int fd, off_t offset);

The mmap() function asks to map length bytes starting at offset offset from the file (or other object) specified by the file descriptor fd into memory,

就是說,從offset位置開始,把文件fd的length位元組映射到地址start上。

如果是64位的應用,4G是沒有問題的,32位的應用不能。

D. linux共享內存和mmap的區別

共享內存的創建
根據理論:
1. 共享內存允許兩個或多個進程共享一給定的存儲區,因為數據不需要來回復制,所以是最快的一種進程間通信機制。共享內存可以通過mmap()映射普通文件(特殊情況下還可以採用匿名映射)機制實現,也可以通過系統V共享內存機制實現。應用介面和原理很簡單,內部機制復雜。為了實現更安全通信,往往還與信號燈等同步機制共同使用。

mmap的機制如:就是在磁碟上建立一個文件,每個進程存儲器裡面,單獨開辟一個空間來進行映射。如果多進程的話,那麼不會對實際的物理存儲器(主存)消耗太大。

shm的機制:每個進程的共享內存都直接映射到實際物理存儲器裡面。

結論:

1、mmap保存到實際硬碟,實際存儲並沒有反映到主存上。優點:儲存量可以很大(多於主存)(這里一個問題,需要高手解答,會不會太多拷貝到主存裡面???);缺點:進程間讀取和寫入速度要比主存的要慢。

2、shm保存到物理存儲器(主存),實際的儲存量直接反映到主存上。優點,進程間訪問速度(讀寫)比磁碟要快;缺點,儲存量不能非常大(多於主存)

使用上看:如果分配的存儲量不大,那麼使用shm;如果存儲量大,那麼使用shm。

參看網路:http://ke..com/view/1499209.htm
mmap就是一個文件操作

看這些網路的描述:
mmap()系統調用使得進程之間通過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間後,進程可以向訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作。 成功執行時,mmap()返回被映射區的指針,munmap()返回0。失敗時,mmap()返回MAP_FAILED[其值為(void *)-1],munmap返回-1。errno被設為以下的某個值 EACCES:訪問出錯EAGAIN:文件已被鎖定,或者太多的內存已被鎖定EBADF:fd不是有效的文件描述詞EINVAL:一個或者多個參數無效 ENFILE:已達到系統對打開文件的限制ENODEV:指定文件所在的文件系統不支持內存映射ENOMEM:內存不足,或者進程已超出最大內存映射數量 EPERM:權能不足,操作不允許ETXTBSY:已寫的方式打開文件,同時指定MAP_DENYWRITE標志SIGSEGV:試著向只讀區寫入 SIGBUS:試著訪問不屬於進程的內存區參數fd為即將映射到進程空間的文件描述字,

一般由open()返回,同時,fd可以指定為-1,此時須指定 flags參數中的MAP_ANON,表明進行的是匿名映射(不涉及具體的文件名,避免了文件的創建及打開,很顯然只能用於具有親緣關系的進程間通信)

相關文章參考:
mmap函數是unix/linux下的系統調用,來看《Unix Netword programming》卷二12.2節有詳細介紹。
mmap系統調用並不是完全為了用於共享內存而設計的。它本身提供了不同於一般對普通文件的訪問方式,進程可以像讀寫內存一樣對普通文件的操作。而Posix或系統V的共享內存IPC則純粹用於共享目的,當然mmap()實現共享內存也是其主要應用之一。
mmap系統調用使得進程之間通過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間後,進程可以像訪問普通內存一樣對文件進行訪問,不必再 調用read(),write()等操作。mmap並不分配空間, 只是將文件映射到調用進程的地址空間里, 然後你就可以用memcpy等操作寫文件, 而不用write()了.寫完後用msync()同步一下, 你所寫的內容就保存到文件里了. 不過這種方式沒辦法增加文件的長度, 因為要映射的長度在調用mmap()的時候就決定了.

簡單說就是把一個文件的內容在內存裡面做一個映像,內存比磁碟快些。
基本上它是把一個檔案對應到你的virtual memory 中的一段,並傳回一個指針。

重寫總結:
1、mmap實際就是操作「文件」。
2、映射文件,除了主存的考慮外。shm的內存共享,效率應該比mmap效率要高(mmap通過io和文件操作,或「需要寫完後用msync()同步一下」);當然mmap映射操作文件,比直接操作文件要快些;由於多了一步msync應該可以說比shm要慢了吧???
3、另一方面,mmap的優點是,操作比shm簡單(沒有調用比shm函數復雜),我想這也是許多人喜歡用的原因,包括nginx。

缺點,還得通過實際程序測試,確定!!!

修正理解(這也真是的,這個網站沒辦法附加;只能重寫了):
今天又細心研究了一下,發現網路這么一段說明:
2、系統調用mmap()用於共享內存的兩種方式:
(1)使用普通文件提供的內存映射:適用於任何進程之間;此時,需要打開或創建一個文件,然後再調用mmap();典型調用代碼如下:
fd=open(name, flag, mode);
if(fd<0)
...
ptr=mmap(NULL, len , PROT_READ|PROT_WRITE, MAP_SHARED , fd , 0); 通過mmap()實現共享內存的通信方式有許多特點和要注意的地方,我們將在範例中進行具體說明。
(2)使用特殊文件提供匿名內存映射:適用於具有親緣關系的進程之間;由於父子進程特殊的親緣關系,在父進程中先調用mmap(),然後調用fork()。那麼在調用fork()之後,子進程繼承父進程匿名映射後的地址空間,同樣也繼承mmap()返回的地址,這樣,父子進程就可以通過映射區域進行通信了。注意,這里不是一般的繼承關系。一般來說,子進程單獨維護從父進程繼承下來的一些變數。而mmap()返回的地址,卻由父子進程共同維護。
看了一下windows「內存映射文件」:http://ke..com/view/394293.htm
內存映射文件與虛擬內存有些類似,通過內存映射文件可以保留一個地址空間的區域,同時將物理存儲器提交給此區域,只是內存文件映射的物理存儲器來自一個已經存在於磁碟上的文件,而非系統的頁文件,而且在對該文件進行操作之前必須首先對文件進行映射,就如同將整個文件從磁碟載入到內存。由此可以看出,使用內存映射文件處理存儲於磁碟上的文件時,將不必再對文件執行I/O操作,這意味著在對文件進行處理時將不必再為文件申請並分配緩存,所有的文件緩存操作均由系統直接管理,由於取消了將文件數據載入到內存、數據從內存到文件的回寫以及釋放內存塊等步驟,使得內存映射文件在處理大數據量的文件時能起到相當重要的作用。另外,實際工程中的系統往往需要在多個進程之間共享數據,如果數據量小,處理方法是靈活多變的,如果共享數據容量巨大,那麼就需要藉助於內存映射文件來進行。實際上,內存映射文件正是解決本地多個進程間數據共享的最有效方法。

這里再總結一次:
1、mmap有兩種方式,一種是映射內存,它把普通文件映射為實際物理內存頁,訪問它就和訪問物理內存一樣(這也就和shm的功能一樣了)(同時不用刷新到文件)
2、mmap可以映射文件,不確定會不會像windows「內存映射文件」一樣的功能,如果是,那麼他就能映射好幾G甚至好幾百G的內存數據,對大數據處理將提供強大功能了???
3、shm只做內存映射,和mmap第一個功能一樣!只不過不是普通文件而已,但都是物理內存。

E. linux中mmap函數怎麼用

mmap系統調用並不是完全為了用於共享內存而設計的。它本身提供了不同於一般對普通文件的訪問方式,進程可以像讀寫內存一樣對普通文件的操作。
用open系統調用打開文件, 並返回描述符fd.
用mmap建立內存映射, 並返回映射首地址指針start.
對映射(文件)進行各種操作, 顯示(printf), 修改(sprintf).
用munmap(void *start, size_t lenght)關閉內存映射.
用close系統調用關閉文件fd. 推薦你一本《linux就該這么學》書,看看吧會對你有用的

F. 使用mmap(linux系統調用)追加文件內容

如果你想體驗Linux系統,我覺得最好的辦法是安裝了Linux操作系統,再好的園林綠化,模擬工具不能讓你真正體驗到了Linux的真正威力。一般可以安裝Vista系統的配置非常高,可以安裝虛擬機軟體的Windows平台,虛擬機內安裝了Linux系統。在這種情況下,有一個完整的Linux系統(帶獨立的桌面環境,文件系統,內存空間等,和一台電腦沒有區別),而要像在Windows下運行的Windows應用程序,不會將您的Windows產生任何危害。
常見的虛擬機軟體Vmware的,現在最新的版本是6.0,很不錯,推薦,以及微軟的VirtualPC,功能也很不錯,但我還沒有用完。

G. linux設備驅動物理內存映射

int video_qsb_mmap(struct file *file,struct vm_area_struct *vma)
{
int ret;
u32 size = vma->vm_end - vma->vm_start;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_flags |= VM_RESERVED;
if(frm_num<qsb_dev.mmap_num)
{
ret = remap_pfn_range(vma,vma->vm_start,align_addr>>PAGE_SHIFT,qsb_dev.stride*1944,vma->vm_page_prot); align_addr=PAGE_ALIGN(align_addr+2592*1944);
if(ret != 0)
{ return -EAGAIN; }
frm_num++; }
return 0;
}

這是我自己的函數,我是在UBOOT里規定系統只能用前192M,其它的由應用層調用MMAP函數實現映射,貼過來格式亂了,你參考參考,是可以用的。大概就是申請1張圖片的大小,並進行頁對齊。不懂的問,你查查這幾個函數的作用參數照著寫應該就可以實現你得目的了。

H. Linux關於地址空間和MMAP映射有何特點

Linux採用
虛擬
內存技術,系統中的所有進程之間以虛擬方式共享內存。對每個進程來說,它們好像都可以訪問整個系統的所有物理內存。更重要的是,即使單獨一個進程,它擁有的地址空間也可以遠遠大於系統物理內存。
進程地址空間由每個進程中的線性地址區組成,每個進程都有一個32位或64位的平坦(flat)空間,空間的具體大小取決於體系結構。「平坦」指地址空間范圍是一個獨立的連續區間。通常情況下,每個進程都有唯一的這種平坦空間,而且每個進程的地址空間之間彼此互不相干。兩個不同的進程可以在它們各自地址空間的相同地址內存存放不同的數據。但是進程之間也可以選擇共享地址空間,我們稱這樣的進程為線程。
在地址空間中,我們更為關心的是進程有權訪問的虛擬內存地址區間,比如08048000~0804c000。這些可被訪問的合法地址區間被成為內存區域(memory area),通過內核,進程可以給自己的地址空間動態地添加或減少內存區域。
進程只能訪問有效范圍內的內存地址。每個內存區域也具有相應進程必須遵循的特定訪問屬性,如只讀、只寫、可執行等屬性。如果一個進程訪問了不在有效范圍中的地址,或以不正確的方式訪問有效地址,那麼內核就會終止該進程,並返回「段錯誤」信息。
?
內存區域可以包含各種內存對象,如下:
?
可執行文件代碼的內存映射,成為代碼段(text section)。
?
可執行文件的已初始化全局變數的內存映射,成為數據段(data section)。
?
包含未初始化全局變數的零頁(也就是bss段)的內存映射。零頁是指頁面中的數據全部為0。
?
用於進程用戶空間棧的零頁的內存映射。
?
每一個諸如C庫或動態鏈接程序等共享庫的代碼段、數據段和bss也會被載入進程的地址空間。
?
任何內存映射文件。
?
任何共享內存段。
?
任何匿名的內存映射,比如由malloc()分配的內存。
進程地址空間的任何有效地址都只能位於唯一的區域,這些內存區域不能相互覆蓋。可以看到,在執行的進程中,每個不同的內存片斷都對應一個獨立的內存區域:棧、對象代碼、全局變數、被映射的文件等等。
內核使用內存描述符表示進程的地址空間。內存描述符由mm_struct結構體表示,定義在文件中,該結構包含了和進程地址空間有關的全部信息。
VMA
內存區域由vm_area_struct結構體描述,定義在文件中,內存區域在內核中也經常被稱作虛擬內存區域或者VMA。
VMA標志是一種位標志,它定義在vm_area_struct結構中(該結構中的vm_flags子域)。和物理頁的訪問許可權不同,VMA標志反映了內核處理頁面索需要遵守的行為准則,而不是硬體要求。VM_IO標志內存區域中包含對設備I/O空間的映射。該標志通常在設備驅動程序執行 mmap()函數進行I/O空間映射時才被設置,同時該標志也表示該內存區域不能被包含在任何進程的存放轉存(core mp)中。VM_RESERVED標志內存區域不能被換出,它也是在設備驅動程序進行映射時被設置。
vm_area_struct結構體中的vm_ops域指向與指定內存區域相關的操作函數表,內核使用表中的方法操作VMA。
mmap()和do_mmap():創建地址區間
內核使用do_mmap()函數創建一個新的線性地址區間。但是說給函數創建一個新VMA並不非常准確,因為如果創建的地址區間和一個已經存在的地址區間相鄰,並且它們具有相同的訪問許可權的話,那麼兩個區間將合並為一個。如果不能合並,那麼就確實需要創建一個新的VMA了。但無論哪種情況,do_mmap()函數都會將一個地址區間加入到進程的地址空間中——無論是擴展已經存在的內存區域還是創建一個新的區域。
do_mmap()函數聲明在文件中,原型如下:
unsigned long do_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long offset)
在用戶空間可以通過mmap()函數調用獲取內核函數do_mmap()的功能。mmap()系統調用原型如下:
void *mmap2(void *start, size_t length,
int prot, int flags,
int fd, off_t pgoff)
do_munmap()函數從特定的進程地址空間中刪除指定地址區間,該函數在文件中聲明:
int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
系統調用munmap()給用戶空間程序提供了一種從自身地址空間中刪除指定地址區間的方法,它和系統調用mmap()的作用相反:
int munmap(void *start, size_t length)
mmap設備操作
對於驅動程序來說,內存映射可以提供給用戶程序直接訪問設備內存的能力。映射一個設備,意味著使用戶空間的一段地址關聯到設備內存上。無論何時,只要程序在分配的地址范圍內進行讀取或者寫入,實際上就是對設備的訪問。
並不是所有的設備都能進行mmap抽象。例如,串口設備和其他面向流的設備就無法實現這種抽象。mmap的另一個限制是映射都是以 PAGE_SIZE為單位的。內核只能在頁表一級處理虛擬地址;因此,被映射的區域必須是PAGE_SIZE的整數倍,而且必須位於起始於 PAGE_SIZE整數倍地址的物理內存內。如果區域的大小不是頁大小的整數倍,內核就通過生成一個稍微大一些的區域來容納它。
mmap方法是file_operations結構中的一員,並且在執行mmap系統調用時就會調用該方法。在調用實際方法之前,內核會完成很多工作,而且該方法的原型與系統調用的原型由很大區別。關於Linux命令的介紹,看看《linux就該這么學》,具體關於這一章地址3w(dot)linuxprobe/chapter-02(dot)html
文件操作聲明如下:
int (*mmap) (struct file * filp, struct vm_area_struct *vma);
其中vma參數包含了用於訪問設備的虛擬地址區間的信息。大部分工作已經由內核完成了,要實現mmap,驅動程序只要為這一地址范圍構造合適的頁表即可,如果需要的話,就用一個新的操作集替換vma->vm_ops。
有兩種建立頁表的方法:使用remap_page_range函數可一次建立所有的頁表,或者通過nopage VMA方法每次建立一個頁表。
構造用於映射一段物理地址的新頁表的工作是由remap_page_range完

I. Linux驅動mmap

使用共享內存前,調用msync()試試

閱讀全文

與linuxmmap實現相關的資料

熱點內容
重生細胞安卓版沒鍵盤怎麼玩 瀏覽:992
小米nfc手機刷加密卡 瀏覽:288
linux如何下載文件 瀏覽:806
linuxrpm依賴 瀏覽:368
匯率pdf 瀏覽:353
帶分數的演算法思維 瀏覽:115
如何讓伺服器支持asp文件 瀏覽:48
python網站自動簽到腳本 瀏覽:888
程序員和語言框架哪個重要 瀏覽:776
文件伺服器上面有什麼 瀏覽:383
需求不清是程序員面臨的真正挑戰 瀏覽:952
放療有關的演算法 瀏覽:750
java和python交互 瀏覽:647
貴州網路伺服器機櫃雲主機 瀏覽:267
未來番禺程序員待遇 瀏覽:213
安卓安智部落沖突密碼怎麼改 瀏覽:648
http協議單片機 瀏覽:75
pdfdocument 瀏覽:558
gcc編譯vi文件 瀏覽:65
安卓連airpods怎麼找耳機 瀏覽:929