malloc-bezogene Parameter können mit mallopt (3)
geändert werden.
Sie können beispielsweise den Schwellenwert für die Verwendung von mMap in Malloc auf 1 MB ändern, indem Sie folgende Schritte ausführen:
mallopt(M_MMAP_THRESHOLD, 1024*1024);
Einige der Parameter, die mit mallopt festgelegt werden können, können auch mit Umgebungsvariablen geändert werden.
Beispielsweise kann der oben erwähnte M_MMAP_THRESHOLD
auch mit der Umgebungsvariablen MALLOC_MMAP_THRESHOLD_
festgelegt werden.
$ export MALLOC_MMAP_THRESHOLD_=1048576
$ ./a.out
Umgebungsvariablen können angewendet werden, ohne das Programm zu ändern. Dies ist hilfreich, wenn Sie die Systemstandards ändern. Die Änderung von mallopt durch diese Umgebungsvariable verwendet den Mechanismus Tunables von glibc.
In diesem Artikel wird der Ablauf der Einstellung von Glibc-Tunables beschrieben
Nehmen wir als Beispiel die Umgebungsvariable MALLOC_MMAP_THRESHOLD_
und belassen Sie sie als Memorandum.
Wenn Sie Fehler haben, würde ich mich freuen, wenn Sie darauf hinweisen könnten.
Die Umgebung ist wie folgt.
$ arch
x86_64
$ uname -r
5.4.0-42-generic
$ lsb_release -d
Description: Ubuntu 18.04.4 LTS
$ dpkg -l | grep libc-bin
ii libc-bin 2.27-3ubuntu1.2 amd64 GNU C Library: Binaries
MALLOC_MMAP_THRESHOLD_
Fluss, der Umgebungsvariablen widerspiegeltDer Hilfsvektor kann mit getauxval (3) erhalten werden. Zusatzinformationen der ausführbaren Datei, die vom ELF-Loader des Kernels übergeben wurden.
Holen Sie sich im Loader die Informationen zu AT_SECURE aus dem Hilfsvektor und Wenn "AT_SECURE" wahr ist, wird die globale Variable "__libc_enable_secure" gesetzt.
Hier ist "AT_SECURE" ein Name, der etwas irreführend ist. Dies bedeutet, dass der aktuelle Prozess sicher ausgeführt werden muss. Insbesondere wird "AT_SECURE" in einem der folgenden Fälle festgelegt.
--Programme mit Set-User-ID oder Set-Group-ID gültig
glibc-2.27/elf/dl-sysdep.c
ElfW(Addr)
_dl_sysdep_start (void **start_argptr,
void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
{
...
for (av = GLRO(dl_auxv); av->a_type != AT_NULL; set_seen (av++))
switch (av->a_type)
{
...
case AT_SECURE:
__libc_enable_secure = av->a_un.a_val;
break;
...
}
__tunables_init (_environ);
...
(*dl_main) (phdr, phnum, &user_entry, GLRO(dl_auxv));
return user_entry;
}
Wenn in __tunables_init
das Element in tunnelable_list []
in der Umgebungsvariablen enthalten ist,
Der Wert der Umgebungsvariablen wird durch "tunable_initialize ()" wiedergegeben.
Wenn jedoch "__libc_enable_secure" gesetzt ist (= "AT_SECURE" gesetzt ist), Die Verarbeitung wird gemäß den folgenden drei Arten von "Sicherheitsstufe" durchgeführt.
--SXID_ERASE
: Bei AT_SECURE
löschen Sie es aus der Umgebungsvariablen, damit der untergeordnete Prozess es nicht lesen kann.
--SXID_IGNORE
: Ignorieren, wenn AT_SECURE
(bleibt in der Umgebungsvariablen)
--NONE
: Immer nachdenken
glibc-2.27/elf/dl-tunables.c
void
__tunables_init (char **envp)
{
...
while ((envp = get_next_env (envp, &envname, &len, &envval,
&prev_envp)) != NULL)
{
...
for (int i = 0; i < sizeof (tunable_list) / sizeof (tunable_t); i++)
{
tunable_t *cur = &tunable_list[i];
...
if (__libc_enable_secure)
{
if (cur->security_level == TUNABLE_SECLEVEL_SXID_ERASE)
{
/* Erase the environment variable. */
...
}
if (cur->security_level != TUNABLE_SECLEVEL_NONE)
continue;
}
tunable_initialize (cur, envval);
break;
}
}
}
}
Die Sicherheitsstufe jedes Elements in der einstellbaren Datei wird in der Datei ".list" zusammen mit dem Namen und dem Typ der Umgebungsvariablen definiert.
glibc-2.27/elf/dl-tunables.list
glibc {
malloc {
...
mmap_threshold {
type: SIZE_T
env_alias: MALLOC_MMAP_THRESHOLD_
security_level: SXID_IGNORE
}
...
}
}
scripts / gen-tunables.awk
generiert automatisch dl-tunable-list.h
aus dl-tunables.list
Dort wird tunable_list []
definiert.
dl-tunable-list.h
static tunable_t tunable_list[] attribute_relro = {
...
{TUNABLE_NAME_S(glibc, malloc, mmap_threshold), {TUNABLE_TYPE_SIZE_T, 0, SIZE_MAX}, {}, NULL, TUNABLE_SECLEVEL_SXID_IGNORE, "MALLOC_MMAP_THRESHOLD_"},
...
};
tunable_list []
zu mp_
beim ersten MallocAb hier geht es nicht mehr um Tunables, sondern um Malloc-Parameter. Außerdem ist der Ausführungszeitpunkt nicht der Loader, sondern das erste Mal, dass malloc nach Eingabe der normalen Hauptfunktion aufgerufen wird.
Wenn das Programm zum ersten Mal die Speicherzuweisungsfunktion aufruft, wird "malloc_hook_ini" aufgerufen und
Rufen Sie von dort aus ptmalloc_init
auf.
glibc-2.27/malloc/hooks.c
static void *
malloc_hook_ini (size_t sz, const void *caller)
{
__malloc_hook = NULL;
ptmalloc_init ();
return __libc_malloc (sz);
}
Holen Sie sich in ptmalloc_init``mmap_threshold
aus der in 2 festgelegten tunable_list.
Stellen Sie die Struktur mp_
ein, die die Malloc-Parameter zusammenhält.
glibc-2.27/malloc/arena.c
static void
ptmalloc_init (void)
{
...
TUNABLE_GET (mmap_threshold, size_t, TUNABLE_CALLBACK (set_mmap_threshold));
...
}
glibc-2.27/elf/dl-tunables.c
void
__tunable_get_val (tunable_id_t id, void *valp, tunable_callback_t callback)
{
tunable_t *cur = &tunable_list[id];
switch (cur->type.type_code)
{
...
case TUNABLE_TYPE_SIZE_T:
{
*((size_t *) valp) = (size_t) cur->val.numval;
break;
}
...
if (cur->initialized && callback != NULL)
callback (&cur->val);
}
Die eigentliche Einstellung ist die Funktion "do_set_mmap_threshold". Wenn Sie hier schauen, gibt es tatsächlich eine Obergrenze für den eingestellten Wert. Sie können sehen, dass die dynamische Schwellenwertsteuerung deaktiviert ist, wenn Sie "mmap_threshold" einstellen.
glibc-2.27/malloc/malloc.c
static inline int
__always_inline
do_set_mmap_threshold (size_t value)
{
/* Forbid setting the threshold too high. */
if (value <= HEAP_MAX_SIZE / 2)
{
LIBC_PROBE (memory_mallopt_mmap_threshold, 3, value, mp_.mmap_threshold,
mp_.no_dyn_threshold);
mp_.mmap_threshold = value;
mp_.no_dyn_threshold = 1;
return 1;
}
return 0;
}
Jetzt ist es sonnig und der Wert der Umgebungsvariablen "MALLOC_MMAP_THRESHOLD_" wird verwendet, um zu bestimmen, ob "mmap" verwendet werden soll. Ich bin glücklich.
glibc-2.27/malloc/malloc.c
static void *
sysmalloc (INTERNAL_SIZE_T nb, mstate av)
{
...
if (av == NULL
|| ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold)
&& (mp_.n_mmaps < mp_.n_mmaps_max)))
{
...
mm = (char *) (MMAP (0, size, PROT_READ | PROT_WRITE, 0));
}
}
Wenn Sie den malloc-Parameter mit einer Umgebungsvariablen festlegen, sollten Sie überprüfen, ob die Einstellung vom Debugger ordnungsgemäß wiedergegeben wird.
Nach dem Betrieb von malloc (Umgebungsvariablen) - Qiita mallopt(3) - Linux manual page The GNU C Library getauxval(3) - Linux manual page
Recommended Posts