2015-10-29 47 views
5

時,我有一個簡單的程序去這樣的:總線錯誤(核心轉儲)使用的strcpy到mmap'ed文件

int main(void) { 
    int fd; 
    const char *text = "This is a test"; 

    fd = open("/tmp/msyncTest", (O_CREAT | O_TRUNC | O_RDWR), (S_IRWXU | S_IRWXG | S_IRWXO)); 
    if (fd < 0) { 
      perror("open() error"); 
      return fd; 
    } 

    /* mmap the file. */ 
    void *address; 
    off_t my_offset = 0; 
    address = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED, fd, my_offset); 

    if (address == MAP_FAILED) { 
      perror("mmap error. "); 
      return -1; 
    } 

    /* Move some data into the file using memory map. */ 
    strcpy((char *)address, text); 

    /* use msync to write changes to disk. */ 
    if (msync(address, 4096 , MS_SYNC) < 0) { 
    perror("msync failed with error:"); 
     return -1; 
    } 
    else { 
    printf("%s","msync completed successfully."); 
} 

    close(fd); 
    unlink("/tmp/msyncTest"); 
} 

什麼錯我的代碼?我做了一些簡單的測試,看起來問題來自strcpy。但根據定義,我認爲沒有問題。

+1

你沒有顯示如何檢查'fd';如何設置'len'和'my_offset';你如何檢查'mmap()'調用。我們可以猜測與那些相關的東西導致代碼失敗。 –

+0

@JonathanLeffler好吧,我會發布所有的代碼。 – HuangJie

+1

我們只需要看到一個MCVE([如何創建一個最小,完整和可驗證的例子?](http://stackoverflow.com/help/mcve)) - 這可能是另外10行左右。 –

回答

4

如果

fd = open("/tmp/msyncTest", (O_CREAT | O_TRUNC | O_RDWR), (S_IRWXU | S_IRWXG | S_IRWXO)); 

是成功的,fd將指零長度文件(O_TRUNC)。到mmap()

address = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED, fd, my_offset); 

呼叫建立內存映射,但網頁不符合的對象。

http://pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html有以下要說一下這種情況:

系統總是在對象的末尾零填充任何部分頁面。此外,系統不會寫出超出其結尾的對象的最後一頁的任何修改部分。在從pa開始的地址範圍內的引用以及在對象結束後的整個頁面中繼續len字節導致傳送SIGBUS信號。

同樣,man mmap在Linux注意到

使用映射的區域可導致這些信號:
[...]
SIGBUS嘗試訪問不適用的緩衝器的一部分對應於文件(例如,超出文件末尾,包括另一個進程已截斷文件的情況)。

因此,必須前mmap()ftruncate()文件到一個非零長度荷蘭國際集團(除非你是mmap()荷蘭國際集團匿名內存)。

+0

一個細節:'ftruncate'不需要在'mmap'之前發生;只要它在發生錯誤的訪問之前發生,就可以在'mmap'之後完成。 –

+0

@R ..我會*強烈*建議反對:http://pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html'如果映射文件的大小在調用mmap()後由於其他原因而改變對映射文件進行操作時,未指定對映射區域的部分對應於文件的添加或刪除部分的引用的效果。'Linux'man mmap:更改映射的底層文件的大小沒有指定對應於文件的添加或刪除區域的頁面。' – EOF

+0

好的,很高興知道;不知怎的,我總是錯過了。 –