Хобрук: Ваш путь к мастерству в программировании

Пользовательский буфер после «записи» в файл, открытый с помощью O_DIRECT

Я использую флаг O_DIRECT для записи на диск непосредственно из пользовательского буфера. Но насколько я понимаю, линукс не гарантирует, что после этого вызова данные запишутся. Он просто пишет напрямую из пользовательского буфера на физическое устройство, используя DMA или что-то еще... Поэтому я не понимаю, могу ли я писать в пользовательский буфер после вызова функции «запись».

Я уверен, что пример кода поможет понять мой вопрос:

char *user_buff = malloc(...); /* assume it is aligned as needed */
fd = open(..., O_DIRECT);
write(fd, ...)
memset(user_buff, 0, ...)

Законна ли последняя строка (memset)? Допустима ли запись в пользовательский буфер, который может использоваться DMA для передачи данных на устройство?

01.12.2012

Ответы:


1

Это законно. Здесь нет «петли» - подумайте, что вы должны делать, если вы использовали динамически распределенный массив. Не могли бы вы освободить его после write()? Не могли бы вы? - Что ж, ответ заключается в том, что функция write() (и системный вызов) не изменяет и не обращается к пользовательскому буферу после его возврата - если немедленная запись не может быть выполнена, будет сделана копия данных. Вам не нужно беспокоиться о деталях реализации (в конце концов, это цель стандартной библиотеки C...)

01.12.2012
  • write() не является частью стандартной библиотеки C, это системный вызов Unix более низкого уровня. 01.12.2012
  • Я в замешательстве, один ответ говорит, что это незаконно, другой ответ говорит, что это не так. @ H2CO3 - если DMA выполняется из пользовательского буфера, будет ли «записывать» ожидание завершения DMA, прежде чем он будет возвращен ?? 01.12.2012
  • @ user1868481 Я не думаю, что есть какое-то противоречие - в ответе Бармара также говорится, что гарантируется, что при «записи» ваши данные будут записаны. 01.12.2012
  • но Бармар предложил добавить флаг O_SYNC в дополнение к O_DIRECT. Это необходимо? Мне нужно, чтобы эта запись была как можно быстрее. После этой «записи» я заполняю тот же пользовательский буфер новыми данными, а затем снова использую «запись». Я просто хочу понять, что происходит, когда я использую только O_DIRECT и «запись» и активируется DMA. Как узнать, безопасно ли использовать пользовательский буфер или он используется DMA после возврата 'write'... 01.12.2012
  • @userXXX, вы знаете, что это безопасно, поскольку, если бы это было не так, вам пришлось бы наблюдать за деталями реализации, чего вам не нужно делать. 01.12.2012
  • Хорошо, но я не понимаю, как это возможно с DMA. С одной стороны, справочная страница open говорит: Файловый ввод-вывод выполняется непосредственно в/из буферов пользовательского пространства. С другой стороны, это говорит, но не дает гарантий O_SYNC, что данные и необходимые метаданные передаются. Итак, если я использую «запись» и DMA активируется непосредственно из пользовательского буфера, но «запись» возвращается до завершения DMA, возникает проблема... 01.12.2012
  • @ user1868481: Я не уверен, подразумевает ли O_DIRECT DMA, как это предусмотрено контроллерами жестких дисков. Я бы сказал, что он просто обходит использование внутренних буферов библиотеки. По-прежнему может происходить кэширование на аппаратном уровне или при использовании распределенных файловых систем. Чтобы убедиться, что последние также были сброшены, следует использовать O_SYNC, поэтому данные гарантировано, что они были сохранены физически. 02.12.2012
  • @user1868481 user1868481 Вы знаете, что это безопасно, потому что это гарантированно безопасно. Независимо от каких-либо флагов, которые вы передаете в open(), write() не оставляет ядро ​​с указателем обратно на ваш буфер в пользовательском пространстве, к которому оно пытается получить асинхронный доступ позже. Когда write() возвращается, ядро ​​ни при каких обстоятельствах не будет пытаться получить доступ к вашему буферу пользовательского пространства. Вы можете делать с ним все, что хотите. 14.02.2014

  • 2

    Используйте флаг O_SYNC в сочетании с O_DIRECT. Тогда вы можете быть уверены, что данные были записаны, когда write() вернется.

    01.12.2012
    Новые материалы

    Библиотеки PyTorch и Python для машинного обучения: приложения в здравоохранении с обнимающим лицом…
    В сфере машинного обучения Python выделяется благодаря своей универсальности и набору предлагаемых библиотек. Развитие машинного обучения в здравоохранении можно частично объяснить простотой и..

    «Что за…» очень хорошо представляет мое выражение лица после того, как я увидел это!
    «Что за…» очень хорошо представляет мое выражение лица после того, как я увидел это!

    5 вещей, которые я сделал, чтобы стать профессиональным разработчиком JavaScript
    Чтобы стать профессиональным JS-разработчиком: 1. Практикуйтесь в рутине, 2. Работайте над проектами, 3. Придерживайтесь одного языка, 4. Наблюдайте за чужим кодом, 5. Будьте последовательны..

    От теории к практике: пошаговое руководство по реализации наивного Байеса
    Вы когда-нибудь застревали в проекте классификации, не зная, как точно предсказать результаты для ваших данных? Вы искали более простой и интуитивно понятный алгоритм, который поможет вам достичь..

    #093 | Моделирование вспышки эпидемии с помощью JavaScript — Часть 3
    TLDR: Я сделал симуляцию вспышки эпидемии, в которую можно поиграть здесь . Мой холст, моя сцена Мой HTML — это всего лишь один div с классом stage, и вот как я настроил на нем свой объект..

    numberToString.js (8kyu 16)
    Алгоритм кодовых войн Проблема Нам нужна функция, которая может преобразовать число в строку. 숫자를 문자열로 변환하는 함수를 작성해라. Решение 01 function numberToString(n) { return n.toString(); }..

    Лучшие практики для быстрого изучения языка программирования
    Изучение языка программирования может быть сложной задачей, но при правильном подходе определенно возможно быстро выучить язык программирования. Хорошее понимание языка программирования может..