Джерри прав, если вас беспокоит только Ctrl-C, вы можете игнорировать SIGINT в течение некоторого времени. Если вы хотите быть доказательством против процесса смерти в целом, вам нужно какое-то минимальное ведение журнала. Чтобы поменять местами два элемента:
1) Добавить запись в управляющую структуру в конце файла или в отдельный файл, указав, какие два элемента файла вы собираетесь поменять местами, A и B.
2) Скопируйте A в пустое пространство, запишите, что вы сделали, очистите.
3) Скопируйте B поверх A, затем запишите в пустом месте, что вы сделали, очистите
4) Копировать с нуля пространство над B.
5) Удалить запись.
Это O (1) дополнительное пространство для всех практических целей, поэтому оно по-прежнему считается на месте в большинстве определений. В теории при записи индекс равен O (log n), если n может быть сколь угодно большим: в действительности это очень маленький журнал n, и разумное аппаратное / рабочее время ограничивает его до 64.
Во всех случаях, когда я говорю «сбрасывать», я имею в виду совершать изменения «достаточно далеко». Иногда ваша базовая операция сброса только сбрасывает буферы внутри процесса, но на самом деле она не синхронизирует физическую среду, потому что она не сбрасывает буферы полностью через уровни ОС / драйвера устройства / аппаратного обеспечения. Этого достаточно, когда все, о чем вы беспокоитесь, - это смерть процесса, но если вы беспокоитесь о внезапном отключении носителя, вам придется пролететь мимо драйвера. Если вы беспокоитесь о сбое питания, вам придется синхронизировать оборудование, но это не так. С ИБП или, если вы думаете, что отключения питания настолько редки, что вы не возражаете против потери данных, это нормально.
При запуске проверьте пустое пространство на наличие записей «в процессе обмена». Если вы найдете его, выясните, как далеко вы продвинулись, и завершите обмен, чтобы вернуть данные в нормальное состояние. Затем снова начните сортировку.
Очевидно, что здесь есть проблема с производительностью, так как вы делаете в два раза больше записей, чем раньше, и сброс / синхронизация могут быть удивительно дорогими. На практике в вашей сортировке на месте могут быть составные операции с движущимся материалом, включающие много замен, но вы можете оптимизировать их, чтобы избежать попадания каждого элемента в пустое пространство. Вам просто нужно убедиться, что перед тем, как перезаписать какие-либо данные, у вас есть их надежная копия и запись о том, куда эта копия должна идти, чтобы вернуть ваш файл в состояние, в котором он содержит ровно одну копию каждого элемента.
Джерри также прав, что настоящая сортировка на месте слишком сложна и медленна для большинства практических целей. Если вы можете сэкономить некоторую линейную дробь исходного размера файла в качестве пустого места, вам будет намного удобнее с сортировкой слиянием.
Судя по вашим разъяснениям, вам не понадобятся операции очистки даже при сортировке на месте. Вам нужно пространство памяти в памяти, которое работает таким же образом, и к которому ваш обработчик SIGINT может получить доступ, чтобы обеспечить безопасность данных до выхода , а не восстановление при запуске после аварийного выхода и вам необходимо получить доступ к этой памяти безопасным для сигнала способом (что технически означает использование sig_atomic_t
для обозначения внесенных изменений). Тем не менее, вам, вероятно, лучше с сортировкой слиянием, чем с сортировкой по месту.