Память в GoOS, часть 1. От bump allocator к собственному heap и GC
В первой статье про GoOS я довольно подробно прошёлся по загрузке, SMP, IPC, capabilities, сети, Linux ABI и устройству сервисов. А в комментариях довольно быстро всплыл вопрос, который я тогда сознательно обошёл стороной: что в системе происходит с динамической памятью и сборщиком мусора. Вопрос был вполне по делу. Я пишу ОС преимущественно на Go, компилирую её TinyGo, но обычный Go runtime мне тут никто не выдаёт. Значит, фраза «Go сам разберётся с памятью» тут совершенно не работает. Кто-то должен дать new , make , слайсам, map, channel и остальным объектам кучу. Кто-то должен вернуть память после того, как объект перестал быть нужен. А если в системе появляется Garbage Collector - сборщик мусора " data-abbr="GC">GC , он должен понимать, где искать корни, как останавливаться относительно потоков и что делать с указателями, которые в момент остановки лежат не на стеке, а в регистрах процессора. На момент той дискуссии ответ был сильно проще. Ядро было и остаётся собрано TinyGo с gc: leaking : его Go-куча умеет только выделять. В повторяющихся путях ядра динамические аллокации запрещены архитектурно, а объекты для таких путей заранее выделяются, переиспользуются или живут в специальных таблицах и пулах. В userspace ситуация была хуже: там уже существовал собственный runtime, но runtime.alloc по сути был bump allocator, а runtime.free и runtime.GC были заглушками. В одном из ответов я тогда написал: «И таки да, следующим релизом я этот вопрос решу». 0.2.8 , который я сейчас готовлю — как раз этот самый релиз. Читать далее
