首页
/
每日頭條
/
科技
/
ios查看靜态庫中的文件
ios查看靜态庫中的文件
更新时间:2026-10-23 07:17:35

文件内存映射(mmap)之前看過很多文章提及到,但是都沒有寫iOS中具體的實現,隻是都說對于大文件讀寫效率比較高等。所以作者就專門研究了以下mmap技術,并且實現了一下

mmap

文件映射是将文件的磁盤扇區映射到進程的虛拟内存空間的過程。一旦被映射,您的應用程序就會訪問這個文件,就好像它完全駐留在内存中一樣(不占用内存,使用的是虛拟内存)。當您從映射的文件指針讀取數據時,将在适當的數據中的内核頁面并将其返回給您的應用程序。

疑問

那大家就會想了,既然不消耗内存,那豈不是都用mmap就行了,這樣多好啊,又不占内存。其實不然,并不是所有的場景都适合使用mmap的

适合的場景

  • 您有一個很大的文件,其内容您想要随機訪問一個或多個時間。

  • 您有一個小文件,它的内容您想要立即讀入内存并經常訪問。這種技術最适合那些大小不超過幾個虛拟内存頁的文件。(頁是地址空間的最小單位,虛拟頁和物理頁的大小是一樣的,通常為4KB。)

  • 您需要在内存中緩存文件的特定部分。文件映射消除了緩存數據的需要,這使得系統磁盤緩存中的其他數據空間更大。

當随機訪問一個非常大的文件時,通常最好隻映射文件的一小部分。映射大文件的問題是文件會消耗活動内存。如果文件足夠大,系統可能會被迫将其他部分的内存分頁以加載文件。将多個文件映射到内存中會使這個問題更加複雜。

  • 您希望從開始到結束的順序從頭到尾讀取一個文件。

  • 這個文件有幾百兆字節或者更大。将大文件映射到内存中會快速地填充内存,并可能導緻分頁,這将抵消首先映射文件的好處。對于大型順序讀取操作,禁用磁盤緩存并将文件讀入一個小内存緩沖區。

  • 該文件大于可用的連續虛拟内存地址空間。對于64位應用程序來說,這不是什麼問題,但是對于32位應用程序來說,這是一個問題。

  • 該文件位于可移動驅動器上。

  • 該文件位于網絡驅動器上。

  • ios查看靜态庫中的文件(iOS文件内存映射詳解)1

    實現

    這個代碼實現的功能就是首先讀取存儲在我們沙盒的文件,然後在該文件的上繼續寫入數據(追加數據)

    #import "ViewController.h"

    #import #import int MapFile( char * inPathName, void ** outDataPtr, size_t * outDataLength );

    void ProcessFile( char * inPathName )

    {

    size_t dataLength;

    void * dataPtr;

    void *start;

    if( MapFile( inPathName, &dataPtr, &dataLength ) == 0 )

    {

    start = dataPtr;

    dataPtr = dataPtr 3;

    memcpy(dataPtr, "CCCC", 4);

    // Unmap files:

    munmap(start, 7);

    }

    }

    // MapFile

    // Exit: outDataPtra pointer to the mapped memory region

    // outDataLength size of the mapped memory region

    // return value an errno value on error (see sys/errno.h)

    // or zero for success

    //

    int MapFile( char * inPathName, void ** outDataPtr, size_t * outDataLength )

    {

    int outError;

    int fileDescriptor;

    struct stat statInfo;

    // Return safe values on error.

    outError = 0;

    *outDataPtr = NULL;

    *outDataLength = 0;

    // open the file.

    fileDescriptor = open( inPathName, O_RDWR, 0 );

    if( fileDescriptor < 0 )

    {

    outError = errno;

    }

    else

    {

    // We now know the file exists. Retrieve the file size.

    if( fstat( fileDescriptor, &statInfo ) != 0 )

    {

    outError = errno;

    }

    else

    {

    ftruncate(fileDescriptor, statInfo.st_size 4);//增加文件大小

    fsync(fileDescriptor);//刷新文件

    *outDataPtr = mmap(NULL,

    statInfo.st_size 4,

    PROT_READ|PROT_WRITE,

    MAP_FILE|MAP_SHARED,

    fileDescriptor,

    0);

    if( *outDataPtr == MAP_FAILED )

    {

    outError = errno;

    }

    else

    {

    // On success, return the size of the mapped file.

    *outDataLength = statInfo.st_size;

    }

    }

    // Now close the file. The kernel doesn’t use our file descriptor.

    close( fileDescriptor );

    }

    return outError;

    }

    @interface ViewController ()

    @property (weak, nonatomic) IBOutlet UITextView *mTV;

    @end

    @implementation ViewController

    - (void)viewDidLoad {

    [super viewDidLoad];

    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;

    NSString *str = @"AAA";

    NSError *error;

    NSString *filePath = [NSString stringWithFormat:@"%@/text.txt",path];

    [str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];

    if (error) {

    NSLog(@"%@",error);

    }

    ProcessFile(filePath.UTF8String);

    NSString *result = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];

    self.mTV.text = result;

    }

    @end

    最重要的就是2個函數:

    • mmap()

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

    start:映射區的開始地址,設置為0時表示由系統決定映射區的起始地址。 length:映射區的長度。//長度單位是 以字節為單位,不足一内存頁按一内存頁處理 prot:期望的内存保護标志,不能與文件的打開模式沖突。是以下的某個值,可以通過or運算合理地組合在一起 PROT_EXEC //頁内容可以被執行 PROT_READ //頁内容可以被讀取 PROT_WRITE //頁可以被寫入 PROT_NONE //頁不可訪問 flags:指定映射對象的類型,映射選項和映射頁是否可以共享。它的值可以是一個或者多個以下位的組合體 fd:有效的文件描述詞。一般是由open()函數返回,其值也可以設置為-1,此時需要指定flags參數中的MAP_ANON,表明進行的是匿名映射。 off_toffset:被映射對象内容的起點。

    這裡的參數我們要重點關注3個length、prot、flags。 length代表了我們可以操作的内存大小; prot代表我們對文件的操作權限。這裡傳入了讀寫權限,而且注意要與open()保持一緻,所以open()函數傳入了O_RDWR可讀寫權限;。 flags要寫MAP_FILE|MAP_SHARED,我一開始隻寫了MAP_FILE,能讀,但是不能寫。

    • munmap()

    int munmap(void* start,size_t length);

    這裡對原來文件追加寫入數據要注意一點,讀取原來文件之後,我們隻有原來文件大小的可寫區域。例如以上例子原文件中是AAA,這時我們要寫入CCCC,做覆蓋寫入的話我們隻能寫入CCC。所以要要對文件進行追加寫入的話,必須提前增加文件的大小即調用ftruncate()和sync(),增加了4位了,最終才能使CCCC順利寫入

    ios查看靜态庫中的文件(iOS文件内存映射詳解)2

    ,
    Comments
    Welcome to tft每日頭條 comments! Please keep conversations courteous and on-topic. To fosterproductive and respectful conversations, you may see comments from our Community Managers.
    Sign up to post
    Sort by
    Show More Comments
    推荐阅读
    怎麼樣把電腦設置成密碼
    怎麼樣把電腦設置成密碼
    對于我們不想給别人看到的東西,我們一般都是加上密碼或者是用密碼箱将它們鎖起來。那麼電腦也是一樣的,我們自己使用的電腦一般都會有一些自己保存的文件,照片等一些私密的東西,不想讓人随便看到,為了防止别人可以輕易的打開自己的電腦,就要給電腦設置密...
    2026-10-23
    手機的飛行模式是什麼意思
    手機的飛行模式是什麼意思
    手機的飛行模式是什麼意思?飛行模式又叫航空模式,是在乘坐飛機時必須關掉手機,以免手機信号的發射和接受對飛機飛行造成影響,有某些手機裡就自帶了這個功能,可以關閉掉SIM卡的信号收發裝置飛行模式是關閉電話通信功能,即不能接打電話發短信,與基站沒...
    2026-10-23
    手機存儲卡損壞如何挽救
    手機存儲卡損壞如何挽救
    手機存儲卡是我們存放應用、媒體文件、個人文件的重要工具,但是它也因為頻繁的讀取很容易出現問題。往往存儲卡受損時,隻能通過格式化等方法來修複,導緻數據丢失,那有沒有其他辦法解決呢?手機提示存儲卡受損、需要格式化手機上容易碰到這樣的問題:就是提...
    2026-10-23
    走私手機是真是假
    走私手機是真是假
    走私手機是真是假?廣東珠海海關厲行檢查的時候發現一個旅客的身上藏了五十三部蘋果就手機這可是赤裸裸的走私這都什麼年代了,還有人走私蘋果舊手機我也不知道走私一部蘋果舊手機能掙多少錢,大家有人知道走私一部蘋果舊手機能掙多少錢嗎?如果有人知道走私一...
    2026-10-23
    一家奇怪的火鍋店
    一家奇怪的火鍋店
    前不久,北京朝陽派出所接到報案,揭開了一個戲劇性的騙局。男子郭某在一家火鍋店就餐,吃到快結束時,發現菜品中有蟲子,便叫來店員要求免單賠償。店員覺得事出突然,調出監控一看,發現似乎是郭某自己掏出蟲子放在菜品上的。雙方争執不下,火鍋店選擇了報警...
    2026-10-23
    Copyright 2023-2026 - www.tftnews.com All Rights Reserved