2015-10-29 2 views
2

Я записывал на диск с использованием кода C.Запись диска не работает с malloc в C

Сначала я попытался с таНос и обнаружил, что записи не работает (запись возвращается -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

Когда я говорю 'write' не работает, это означает, что retval = -1. И я проверил, что malloc не возвращает null. @ameyCU – Algorithman

+0

имена, начинающиеся с '/ dev' в linux, являются специальными блочными устройствами. Что произойдет, если вы укажете фактический файл? – Mike

ответ

5

От человека странице Linux для открытых (2):

O_DIRECT флаг может наложить ограничения выравнивания по длине и адрес пользовательского пространства буферов и смещения файла ввода/вывода.

И:

Под Linux 2.4, размеры переноса и выравнивание буфера пользователя , а смещение файла должно быть кратным логическому блоку размер файловой системы. В Linux 2.6 достаточно выравнивания до 512-байтных границ .

Значение O_DIRECT является «попытаться минимизировать кэш эффектов ввода/вывода и из этого файла», и, если я правильно понимаю это означает, что ядро ​​должно копировать непосредственно из пользовательского пространства буфера , что, возможно, требует более строгого выравнивания данных.

+0

Ах, отлично, он отвечает на большинство проблем. Кстати, я еще не понял, почему 'posix_memalign' работает вместо' malloc'? – Algorithman

+1

Ухх, потому что он дает вам эту выровненную память? : o –

+0

'posix_memalign' похоже на' malloc', за исключением того, что выделенная память выравнивается. То есть, он начинается с адреса памяти, который кратен второму аргументу. –

2

Возможно, документация не указана, но вполне возможно, что запись и чтение в/из блочного устройства должны быть выровнены и для успешных целых блоков (это объясняет, почему вы получаете сбой в своем первом и последнем случаев, но не во втором). Если вы используете Linux документацию открытого (2) в основном говорит, что это:

Флаг O_DIRECT может наложить ограничение выравнивания по длине и адреса пользовательского пространства буферов и смещению файла ввод/вывод. В Linux ограничения выравнивания зависят от файловой системы и версии ядра, а могут отсутствовать полностью. Тем не менее, есть cur- , не имеющий никакого файлового системного интерфейса для приложения, чтобы обнаружить эти ограничения для данного файла или файловой системы. Некоторые файловые системы предоставляют свои собственные интерфейсы для этого, например операцию XFS_IOC_DIOINFO в xfsctl (3).

Ваш код показывает отсутствие обработки ошибок. Каждая строка в коде содержит функции, которые могут сбой, и open, lseek и write также сообщают о причине ошибки в 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; 
} 

в том случае, если, по крайней мере, получить более подробные объяснения о том, что идет не так. В этом случае я подозреваю, что вы получаете EIO (Ошибка ввода/вывода) из вызова write.

Обратите внимание, что вышеуказанное возможно не является полным обработкой ошибок, так как сами perror и printf могут потерпеть неудачу (и вы можете что-то сделать с этой возможностью).

+0

Спасибо за вашу мысль. На самом деле у меня есть аналогичная обработка ошибок внутри кода, я просто показал ситч, чтобы показать важную часть и избежать длинного сообщения. – Algorithman

+0

@ Vincentius Если у вас есть обработка ошибок, возможно, вам больше рассказывается о том, что произошло. Что говорит 'perror()'? – glglgl

Смежные вопросы