2015-10-29 45 views
2

我用C代碼寫入磁盤。磁盤寫入不能在malloc中使用C

首先,我試着用malloc和發現寫不工作(寫返回-1):

fd = open('/dev/sdb', O_DIRECT | O_SYNC | O_RDWR); 
void *buff = malloc(512); 
lseek(fd, 0, SEEK_SET); 
write(fd, buff, 512); 

然後,我這改變了第二行和它的工作:

void *buff; 
posix_memalign(&buff,512,512); 

然而,當我將lseek偏移量更改爲1:lseek(fd, 1, SEEK_SET);時,寫入不再工作。

首先,爲什麼沒有malloc工作?

然後,我知道在我的情況下,posix_memalign保證內存對齊的開始地址必須是512的倍數。但是,內存對齊和寫入不應該是一個單獨的過程嗎?那麼爲什麼我不能寫任何我想要的偏移?

+1

您是否檢查過'malloc','write'的返回? – ameyCU

+0

當我說'寫'不起作用時,這意味着retval = -1。我已經檢查過malloc沒有返回null。 @ameyCU – Algorithman

+0

在linux中以'/ dev'開頭的名字是特殊的塊設備。如果你指定一個實際的文件,會發生什麼? – Mike

回答

5

從Linux手冊頁開放(2):

的O_DIRECT標誌可以在長度 和用戶空間的緩衝區的地址和文件I/O的偏移強加對齊限制。

和:

在Linux下2。4,傳輸大小以及用戶對齊的緩衝區和文件偏移必須都是文件系統邏輯塊大小 的倍數。在Linux 2.6下,對齊至512字節的 邊界就足夠了。

O_DIRECT的意思是「儘量減少I/O,並從該文件的緩存效應」,如果我理解正確的話就意味着內核應該從用戶空間緩衝區直接複製,因此可能需要更嚴格的數據對齊。

+0

好啊,它回答了大部分問題。順便說一句,我還不清楚的是,爲什麼'posix_memalign'工作而不是'malloc'? – Algorithman

+1

呃,因爲它給你這個對齊的內存? :o –

+0

'posix_memalign'就像'malloc',只是它分配的內存是對齊的。也就是說,它從一個內存地址開始,它是第二個參數的倍數。 –

2

也許文檔沒有說,但是很有可能寫入和讀取/從塊設備讀取需要對齊並且整個塊成功(這可以解釋爲什麼您在第一個和最後一個失敗但不在第二個)。如果你使用Linux的開放文檔(2)基本上是這樣說:

的O_DIRECT標誌可以在長度和用戶空間的緩衝區 地址和文件I/O的偏移強加對齊限制。在Linux 中,對齊限制因文件系統和內核版本而異,並且 可能完全不存在。但是,存在一個應用程序發現給定文件或文件系統的這些限制的文件系統無關接口。一些 文件系統提供它們自己的接口來執行此操作,例如 xfsctl(3)中的XFS_IOC_DIOINFO操作。

您的代碼顯示缺少錯誤處理。代碼中的每行都包含可能會失敗的函數,並且open,lseekwrite也會報告errno中的錯誤原因。因此,與某種錯誤處理,這將是:

fd = open('/dev/sdb', O_DIRECT | O_SYNC | O_RDWR); 

if(fd == -1) { 
    perror("open failed"); 
    return; 
} 

void *buff = malloc(512); 

if(!buff) { 
    printf("malloc failed"); 
    return; 
} 

if(lseek(fd, 0, SEEK_SET) == (off_t)-1) { 
    perror("lseek failed"); 
    free(buff); 
    return; 
} 

if(write(fd, buff, 512) == -1) { 
    perror("write failed"); 
    free(buff); 
    return; 
} 

在這種情況下,你就至少得拿到什麼不順心的更詳細的解釋。在這種情況下,我懷疑你從write調用中獲得了EIO(輸入/輸出錯誤)。

請注意,上述可能不是完整的錯誤處理,因爲perrorprintf本身可能會失敗(並且您可能想要對此做一些處理)。

+0

謝謝你的想法。其實我在代碼裏面有類似的錯誤處理,我只是展示了髓子來顯示重要的部分,並避免了長時間的後處理。 – Algorithman

+0

@Vincentius如果你有這樣的錯誤處理,它可能會告訴你更多關於發生了什麼。 「perror()」告訴你什麼? – glglgl