Linux/C: копирование файла с обрезанным последним заполненным нулями отверстием

У меня есть программное обеспечение (C/C++/Linux), состоящее из трех сервисов, использующее файл tmpfs в качестве общей памяти. Мы ftruncate увеличиваем размер файла до 1 ГБ для удобства, но на практике файл будет содержать не более 500 МБ данных, и, следовательно, более 50% файла представляет собой большую заполненную нулями дыру в конце.

Программное обеспечение предлагает инструмент под названием download, позволяющий пользователю получить собственную автономную копию файла. При выполнении этой копии я не хочу, чтобы пользователь видел, что она занимает 1 ГБ, а вместо этого удалите «конечную дыру». Нам не нужно постоянно отслеживать «фактический размер», и я предпочитаю узнавать или «выводить» размер только тогда, когда пользователь просит его загрузить, что является довольно необычной операцией. Я хочу, чтобы система помогла мне это выяснить.

Мне достаточно любого из следующих подходов:

  • Просматриваем список отверстий, извлеченный из файла метаданных, и находим отверстия(я), которые являются концом и его размером. Таким образом, я могу вычислить фактический размер как 1 ГБ — совокупный размер конечных отверстий.
  • Системный вызов, который сообщает мне смещение старшего записанного байта и/или блока?
  • (Наименее предпочтительно) Команда терминала, которая уже делает это за меня (обрезанная копия). Это наименее предпочтительно, потому что мне не нравится использование вызовов system("blabla") и я предпочитаю вызывать функции C.

Как мне это сделать? Я предпочитаю использовать системные вызовы или libc, а если нет удобного способа сделать это, то в качестве альтернативы использую инструменты командной строки. Использование сторонних библиотек C/C++ недопустимо.

Можете ли вы ftruncate() уменьшить размер файла до объема данных, которые были записаны в него, когда вы закончите его создание?

Andrew Henle 10.05.2024 11:38

@AndrewHenle Если я сделаю это по наивности, не будет ли чтение файла в «незаписанных зонах» провоцировать выделение страниц? Исходный файл находится в оперативной памяти, поэтому я не хочу, чтобы «чтение всего файла» приводило к тому, что ядро ​​случайно выделяло для него страницы.

ABu 10.05.2024 11:41

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

Andrew Henle 10.05.2024 11:44

Когда вы говорите «пишите», что вы имеете в виду? О каком письме вы думаете? Вызов write из моих данных в пользовательский файл, а затем проверка, сколько байт было записано, вернулось? Или что?

ABu 10.05.2024 11:50
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
4
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете исследовать дыры в файле с помощью последовательности lseek с флагами SEEK_HOLE и SEEK_DATA, которые приводят вас к следующей дыре/не-дыре.

Эти флаги доступны в Linux 3.1+, а также в некоторых BSD.

Другие вопросы по теме