Les paramètres liés à malloc peuvent être modifiés avec mallopt (3)
.
Par exemple, vous pouvez modifier le seuil d'utilisation de mMap dans malloc à 1 Mo en procédant comme suit:
mallopt(M_MMAP_THRESHOLD, 1024*1024);
Certains des paramètres qui peuvent être définis avec mallopt peuvent également être modifiés avec des variables d'environnement. Par exemple, le «M_MMAP_THRESHOLD» mentionné ci-dessus peut également être défini avec la variable d'environnement «MALLOC_MMAP_THRESHOLD_».
$ export MALLOC_MMAP_THRESHOLD_=1048576
$ ./a.out
Les variables d'environnement peuvent être appliquées sans changer le programme, ce qui est utile lors de la modification des valeurs par défaut du système. Le changement de mallopt par cette variable d'environnement utilise le mécanisme appelé Tunables de la glibc.
Dans cet article, le déroulement de la configuration des paramètres réglables de la glibc
Prenons la variable d'environnement MALLOC_MMAP_THRESHOLD_
comme exemple et laissons-la comme mémorandum.
Si vous avez des erreurs, je vous serais reconnaissant de bien vouloir les signaler.
L'environnement est le suivant.
$ 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_
Flux qui reflète les variables d'environnementLe vecteur auxiliaire peut être obtenu avec getauxval (3)
,
Informations auxiliaires pour le fichier exécutable transmises depuis le chargeur ELF du noyau.
Dans le chargeur, récupérez les informations ʻAT_SECURE du vecteur auxiliaire et ʻSi AT_SECURE
est vrai, la variable globale __libc_enable_secure
est définie.
Ici, ʻAT_SECURE est un nom un peu trompeur, Cela signifie que le processus actuel doit s'exécuter en toute sécurité. Plus spécifiquement, ʻAT_SECURE
est défini dans l'un des cas suivants.
--Programmes avec set-user-ID ou set-group-ID valide --Programmes avec capacités
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;
}
tunable_list []
à partir de la valeur de la variable d'environnementDans __tunables_init
, si l'élément danstunnelable_list [] ʻest inclus dans la variable d'environnement, La valeur de la variable d'environnement est reflétée par
tunable_initialize ()`.
Cependant, si __libc_enable_secure
est défini (= ʻAT_SECUREest défini), Le traitement est effectué selon les trois types suivants de
security_level`.
--SXID_ERASE
: ʻAT_SECURE, supprimez-le de la variable d'environnement afin qu'il ne soit pas lu par les processus enfants. --Ignorer si
SXID_IGNORE: ʻAT_SECURE
(reste dans la variable d'environnement)
--NONE
: toujours refléter
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;
}
}
}
}
Le security_level
de chaque élément dans le paramétrable est défini dans le fichier .list
avec le nom et le type de la variable d'environnement.
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
génère automatiquement dl-tunable-list.h
à partir de dl-tunables.list
tunable_list []
y est défini.
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 []
à mp_
au premier mallocÀ partir de maintenant, il ne s'agit pas de paramètres réglables, mais de paramètres malloc. En outre, la synchronisation d'exécution n'est pas le chargeur, mais la première fois que malloc est appelé après avoir entré la fonction principale normale.
La première fois que le programme appelle la fonction d'allocation de mémoire, malloc_hook_ini
est appelé et
Appelez ptmalloc_init
à partir de là.
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);
}
Dans ptmalloc_init
, récupérezmmap_threshold
à partir de la liste tunable_list définie en 2.
Réglez sur la structure mp_
qui contient les paramètres malloc ensemble.
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);
}
Le paramètre actuel est la fonction do_set_mmap_threshold
.
Si vous regardez ici, il y a en fait une limite supérieure pour la valeur définie,
Vous pouvez voir que le contrôle de seuil dynamique est désactivé lors de la définition de mmap_threshold
.
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;
}
Maintenant, il fait beau et la valeur de la variable d'environnement MALLOC_MMAP_THRESHOLD_
sera utilisée pour déterminer si mmap
Je suis heureux.
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));
}
}
Lors de la définition du paramètre malloc avec une variable d'environnement, il est préférable de vérifier si le paramètre est correctement reflété par le débogueur.
Suite au fonctionnement de malloc (variables environnementales) --Qiita mallopt(3) - Linux manual page The GNU C Library getauxval(3) - Linux manual page
Recommended Posts