2012-04-15 91 views
4

我想在C中使用mmap來查看它是如何工作的。目前我嘗試使用mmap逐字節讀取二進制文件。我的代碼是這樣的:在C中使用mmap讀取二進制文件時出現Segfault錯誤

#include <unistd.h> 
#include <sys/types.h> 
#include <sys/mman.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <fcntl.h>  

int main(int argc, char *argv[]) { 
    int fd; 
    char *data; 

    for (int i = 1; i<argc; i++) 
    { 

     if(strcmp(argv[i],"-i")==0) 
      fd = open(argv[i+1],O_RDONLY); 
    } 

    data = mmap(NULL, 4000, PROT_READ, MAP_SHARED, fd, 8000); 
    int i = 0; 
    notation = data [i]; 
    // ...... 

} 

當我嘗試記數法=數據[0]和我得到一個段錯誤時,我的問題發生。我相信二進制文件中的第一個字節也是一個字符。我的for循環檢查編譯時是否有-i標誌,如果有下一個參數應該是文件名。

+0

確定該文件的大小至少爲8000字節?另外,手冊頁中提到「offset必須是由sysconf(_SC_PAGE_SIZE)返回的頁面大小的倍數」。作爲次要方面,您應該將fd初始化爲-1,以防用戶未指定-i參數,並且for循環應該循環到argc-1,否則您將訪問argv,超出了用戶指定的傳入參數 - 我作爲最後一個參數。 – EricS 2012-04-15 17:39:30

回答

4

看起來mmap失敗了,因爲偏移量不是頁面大小的倍數。你可以用perror來測試它,看看問題是一個無效的參數。如果你寫:

data = mmap(NULL, 4000, PROT_READ, MAP_SHARED, fd, 8000); 
perror("Error"); 

至少在我的OS X打印以下錯誤:

錯誤:無效的參數

改變從8000偏移到4096級或8192的作品。 6144沒有,所以它必須是這個平臺上4096的倍數。順便說一句,

printf("%d\n",getpagesize()); 

4096打印要圓向下偏移,爲MMAP的這個最接近的整數倍,其餘訪問該地區時,添加到我。當然,從該功能獲取特定平臺的頁面大小。它可能在你已經聲明的unistd.h中定義。

以下是如何正確處理偏移量並處理可能的錯誤。它打印位置8000處的字節:

int offset = 8000; 
int pageoffset = offset % getpagesize(); 

data = mmap(NULL, 4000 + pageoffset, PROT_READ, MAP_SHARED, fd, offset - pageoffset); 
if (data == MAP_FAILED) { 
    perror ("mmap"); 
    exit (EXIT_FAILURE); 
} 
i = 0; 
printf("%c\n",data [i + pageoffset]); 
+0

+1斑點:-) – cnicutar 2012-04-15 17:48:35

+0

因此,在完成所有這些之後,我仍然以數據爲空。但我的bin文件的大小是16MB。有什麼想法嗎 ? – AndroidDev93 2012-04-15 18:06:52

+0

你以後在做什麼數據?我注意到頁面偏移量也必須添加到長度4000.使用當前代碼,您應該能夠訪問字節8000到11999. – jjrv 2012-04-15 18:10:58