У меня есть огромный буфер, выделенный с помощью malloc в куче, я хочу написать собственный распределитель для выделения пространства из этого буфера.
Теперь у меня вопрос, есть ли способ «пометить» некоторые регионы как «доступные для размещения», «доступные для записи» и «зарезервированные» в этом буфере, как в Kernel Development.
Например, у нас есть буфер с 6 элементами, как я могу пометить элементы 2-5 как «зарезервированные»?
[0][1][2][3][4][5]
Возможно ли это с помощью флагов, битовой манипуляции или чего-то еще? Или я могу отметить указатель?
Отложите какую-то структуру данных для хранения записей. Забудьте пока о битовых манипуляциях.
Массив 'struct' (или связанный список), который включает флаг в каждом экземпляре, который вы можете установить, чтобы указать, разрешено ли выделение, или нет.
Вероятно, было бы проще реализовать пул блоков, чем пул байтов.
Разве связанные списки не сильно повлияли бы на производительность?
Когда вы говорите о производительности, вы должны сравнивать с что-то. Итак, «огромное влияние» по сравнению с чем?
@Lazcano В своем вопросе вы не упомянули никаких ограничений или требований. Не сообщая нам, вы не получите правильных ответов.
Большое спасибо за вашу помощь! :) @EugeneSh. - по сравнению с malloc. Я буду следить за AndersK. совет!
Если вы хотите конкурировать со стандартным malloc, вы можете сначала взглянуть на его реализацию. Что, кстати, может сильно различаться.
Вызов malloc по сравнению, скажем, со статически определенной памятью в стеке, снижает производительность. Истинно, содержится ли указатель в массиве структур или в связанном списке.
Реализации AFAIK FreeBSD являются одними из лучших, если не лучшими.
@Lazcano - просто к сведению, когда вы хотите отправить текст кому-то конкретно, в поле для комментариев начинайте с символа @, за которым сразу следует псевдоним пользователя. Например, @ryyker вызовет появление связанного уведомления в верхней части страницы SO, уведомляющего меня о том, что кто-то оставил комментарий, позволяя мне щелкнуть это уведомление и просмотреть комментарий. :)
@ryyker Спасибо :)





Вы можете использовать что-то столь же простое, как массив struct (или linked list), который включает флаг в каждом экземпляре, который вы можете установить, чтобы указать, разрешено ли выделение, или нет.
Например, используя флаг и неоднозначную типизацию (void *):
typedef struct {
BOOL alloc; //set TRUE to allow or FALSE to disallow further allocation
void *space;
//other members
}BUF;
Создайте массив BUF и установите для члена alloc значение TRUE или FALSE, чтобы сделать экземпляр более недоступным для изменения его памяти. Конечно, это произойдет после того, как начальная память была выделена во время инициализации.
Или другая возможность использования типов enum в сочетании с union:
typedef enum {
_INT,
_UINT,
_CHAR,
_UCHAR,
... //other types
}TYPE;
typedef struct {
BOOL alloc; //set to allow or disallow further allocation
TYPE type; //flag to track type being used in instance
union {
char *cMem;
unsigned char *ucMem;
int *iMem;
unsigned int *uiMem;
... // other members
char *space;
}BUF;
Почему char *? Может void *?
Лучше подойдет void *, так как он подходит для большинства случаев. У меня слишком мало представителей для голосования, извините, но я ценю ваш ответ!
@Lazcano - без проблем. Кстати, объединение типов также может быть включено в структуру, представляющую необходимый type. (Но редактирование показывает предложение Fiddling Bits)
Вот так. Лично я предпочитаю void* с явным приведением.
Преобразуйте количество буферов в битовый массив беззнакового int и используйте индекс памяти, чтобы пометить его. Например: unsigned int allocatable [((x) +31) >> 5]; аналогично для записываемых и зарезервированных.
Почему ((x) +31)>>5? Вы можете объяснить?
Буфер - это единственный буфер, который действует как «куча». Таким образом, я почти полностью контролирую использование памяти и могу правильно выровнять память.
Предположим, что X - максимальное количество буферов, например: 120, тогда выделяемый [(120 + 31) >> 5) будет доступен для размещения [30]. Если вы выделяете память для индекса 4, а затем устанавливаете allocatable [index >> 5] | = (1 << (index & 0x31), этот способ можно использовать для установки и сброса при необходимости. (1 или 0)
Вероятно, вам нужно добавить метаданные, такие как указатели связанных списков, размер и т. д.