Бесстыдный плагин: при сборке с musl libc, для этой программы статическая связь или динамическая связь равна:
execve("./a.out", ["./a.out"], [/* 42 vars */]) = 0
write(1, "Hello world!", 12) = 12
exit_group(0) = ?
Она должна быть аналогично минимальной с dietlibc, если вы статическая ссылкаили с uClibc и статическим связыванием, если вы создали uClibc с отключенными локалями и расширенными возможностями stdio.(По какой-то причине uClibc с этими функциями запускает много кода запуска, чтобы инициализировать их даже в программах, которые их не используют ...)Насколько я знаю, однако, musl - единственный, кто имеет динамический компоновщик, способный избежать чрезмерных издержек системного вызова при запуске в программах с динамической связью.
Что касается , почему статическая связь с glibcделает все эти brk
звонки, я действительно понятия не имею;Вы должны прочитать источник.Я подозреваю, что это выделяет пространство для внутренних структур данных для malloc
, stdio, locale и, возможно, структуры потока для основного потока.Как сказал nm, arch_prctl
предназначен для установки регистра потока, чтобы он указывал на структуру потока основного потока.Этот может быть отложен до первого доступа (что делает musl), но это немного болезненно и слегка ухудшает производительность.Если вы заботитесь о времени выполнения больших программ больше, чем время запуска многих и многих маленьких программ, возможно, имеет смысл всегда инициализировать регистр потока во время загрузки программы.Обратите внимание, что ядро не может установить его для вас, потому что оно не знает адрес, который должен быть установлен.
Возможно, что расширение формата ELF может быть сделано для того, чтобы структура основного потока находилась в.data
раздел с заголовком ELF, указывающим ядру, где оно находится, но акробатика, необходимая между libc, компоновщиком и ядром, вероятно, будет настолько уродливой, что сделает эту оптимизацию нежелательной ... Они также наложат дополнительные ограничения нареализация потоков в пользовательском пространстве.