Есть ли смысл в handles вместо сырых указателей для аллокации памяти в embedded устройствах?
Начну с небольшой предыстории, я хочу сделать КПК-подобное устройство на базе esp32s3 с поддержкой загрузки внешних приложений и многозадачностью, Т.к. в моей esp32s3 всего 8мб озу и нет виртуальной памяти + многозадачность + внешние приложения остро встает проблема фрагментации кучи. В теории можно использовать статическую память в приложениях но тогда ОЗУ может забиться очень быстро, поэтому появилась идея использовать handles вместо сырых указателей для работы с кучей как это делали классическая macOS, palmOS и 16 битные версии windows, т.к таким образом система имеет возможность передвинуть память в куче даже без поддержки виртуальной памяти. Но имеет ли смысл такой подход на esp32s3 с 8мб озу? Я знаю про сложность программирования с хэндлами вместо традиционного malloc/calloc (лично для меня это не будет большой проблемой, и вряд-ли это будет устройство под которое найдутся другие разработчики). И я вижу еще 1 плюс в использование handles, в них можно хранить метаданные об объекте, например его размер и тому подобное
А где будете выделять память под handles? Судя по описанию это должен быть какой-то статический массив фиксированного размера не в общей куче.
Для борьбы с фрагментацией идея выглядит здравой. Но с другой стороны, возможно, лучше использовать какой-то аллокатор, в котором уже реализована логика дефрагментации.
res2001, Можно использовать под handles статический массив и если его не будет хватать то выделять новый но уже из кучи, и насчет аллокатора, я планировал заранее выделить условно 4 мегабайта памяти и уже из нее выделять память через хэндлы, т.к куча понадобится для загрузки приложений, потоков freeRTOS, сети и т.п.
res2001, Логика дефрагментации есть и в стандартном аллокаторе из esp-idf но от маленькой долго живущей аллокации в середине кучи он не защитит, потому что без полноценной виртуальной памяти такое сделать невозможно(или крайне сложно)
Catmengi, Если массив хэндлов выделять динамически в той же куче, то он сам будет попадать под операцию дефрагментации и может быть перемещен дефрагментатором и тогда все хэндлы станут не действительны.
В таком случае вам, видимо, надо будет делать 2 кучи. Одну по меньше для разных "системных" нужд, где память не будет принудительно дефрагментироваться и где аллокатор будет выдавать прямые указатели. И вторую на которой будет работать дефрагментатор и память будет выдаваться через хэндлы.
Ну или как-то по другому это обходить.
Думаю, что массив хэндлов, который нельзя перемещать, окажется не единственным подобным объектом в вашей системе.
res2001, поэтому я про хэндлы и вспомнил, такая дефрагментация у меня будет происходить когда в куче свободного места больше или равно размеру необходимой аллокации а свободного места "подряд" меньше размера необходимой аллокации. (надеюсь я смогу написать нормальную и удобную имплементацию этих хэндлов на Си с поддержкой метаданных). И сразу вопрос про метаданные, тут есть 2 варианта их адресации: через enum значения что крайне быстро и сразу видно что поддерживается а что нет, или через строки (можно сделать define на строку чтобы было удобнее писать) где можно добавлять какие-то свойства к хэндлу которые не известны для ОС в compile time, например приложение добавляет какие-то свои метаданные, но тогда для каждого свойства в метаданных необходимо будет делать free callback (что бы не городить костыли для очистки) и придется использовать структуру данных по типу хэштаблицы, которая может неплохо вызывать фрагментацию а она вероятно будет хранится в системной куче или массива но поиск в нем будет выполнятся медленнее
Catmengi, Какие например метаданные могут быть не известны в compile time?
Если пользователю понадобятся добавить к хэндлу свои данные, то он просто объявит свою структуру, хэндл и метаданные положит в эту структуру. В общем как обычно делаются обертки вокруг системных функций.
Вообще в хэндле в качестве метаданных будет некая информация, которая будет необходима вашему дефрагментатору для работы. С их набором вы определитесь, когда будете его писать.
Пока же можно просто положить в структуру хэндла указатель на реальные данные.
А вы планируете вытесняемую многозадачность реализовывать или кооперативную? Ядер сколько на вашей железке?
При вытесняемой надо будет блокировать хэндл на мьютексе при попытке доступа к памяти по нему и освобождать после доступа.
В кооперативном варианте на одном ядре этого, видимо, можно избежать. На нескольких ядрах уже начнется конкуренция.
res2001, 2 ядра по 240мгц, вытесняющая многозадачность, думаю использовать рекурсивный мьютекс и автоматическую разблокировку через __attribute__ cleanup. чтобы получить указатель надо будет сначала заблокировать хэндл
res2001, кстати, насчет многозадачности в GUI я не знаю, т.к планировал делать его на LVGL, есть вариант ограничить количество одновременно работающих GUI приложений до 1, а вот количество приложений без GUI (которые скорее всего будут общаться через RPC, который должен неплохо работать в условиях одного адресного пространства) ограниченно не будет (ограничения будут только по памяти и от самой rtos под капотом)