16 votes

Pourquoi le fait de fixer la limite dure de maxfiles à "illimité" en utilisant `launchctl limit` résulte en une limite dure légèrement supérieure à la limite douce ?

Pourquoi le fait de fixer la limite stricte de maxfiles à "illimité" en utilisant la fonction launchctl limit entraîne une limite dure légèrement supérieure à la limite douce ?

En fixant la limite maxfiles en utilisant launchctl à launchctl limit maxfiles 10000 unlimited J'obtiens le résultat suivant :

nlykkei-mbp:~ nlykkei$ launchctl limit maxfiles
    maxfiles    10000          10240

Initialement, après le démarrage du système, le hard-limit est défini sur "illimité", alors pourquoi ne puis-je pas définir le même hard-limit en le paramétrant manuellement ?

34voto

Prado Points 1415

Une nouvelle installation du système, avec des paramètres par défaut, est configurée avec les limites de fichiers suivantes pour l'ensemble du système :

  • Kernel Max Files : 12288
  • Fichiers maximum par processus : 10240

Les paramètres sysctl actuels du noyau peuvent être visualisés avec sysctl commandement :

$ sysctl -a |grep kern.maxf

kern.maxfiles: 12288
kern.maxfilesperproc: 10240

Vérifions maintenant les valeurs limites, en utilisant ulimit commandement :

Pour les limites souples : [on peut le voir : les fichiers ouverts \= 256]

$ ulimit -aS

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 256
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 266
virtual memory          (kbytes, -v) unlimited

Pour les limites HARD : [on peut le voir : les fichiers ouverts \= Illimité]

$ ulimit -aH

core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) unlimited
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 65532
cpu time               (seconds, -t) unlimited
max user processes              (-u) 532
virtual memory          (kbytes, -v) unlimited

Utiliser launchctl

launchctl a la capacité de configurer les valeurs limites, ou de montrer les valeurs actuelles.

Utilisation de launchctl limit il affiche toutes les limites souples et dures actuelles, et nous pouvons voir que la limite souple est de 256 et la limite dure est "illimitée" pour l'article. maxfiles . (la même information que nous avons obtenue en utilisant la commande ulimit ci-dessus)

$ uname -a 
18.6.0 Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 x86_64

$ launchctl limit
    cpu         unlimited      unlimited      
    filesize    unlimited      unlimited      
    data        unlimited      unlimited      
    stack       8388608        67104768       
    core        0              unlimited      
    rss         unlimited      unlimited      
    memlock     unlimited      unlimited      
    maxproc     266            532            
    maxfiles    256            unlimited      

Pour filtrer, nous pouvons simplement utiliser launchctl limit maxfiles

$ launchctl limit maxfiles
    maxfiles    256            unlimited

Maintenant, essayons de changer ces valeurs

En utilisant votre ligne de commande comme exemple :

sudo launchctl limit maxfiles 10000 unlimited

Mais après cela, lorsque j'exécute à nouveau la commande pour afficher les limites, nous pouvons voir que :

  • la limite Soft a été ajustée de 256 à 10000,
  • mais la limite Hard a été réduite de "illimité" à "10240".

    sudo launchctl limit
    maxfiles 10000 10240

Et à partir de maintenant, il est impossible de le ramener à un niveau illimité !

Nous pouvons voir qu'après l'avoir exécuté, il a également changé les paramètres sysctl du noyau.

$ sysctl -A |grep max

kern.maxfiles: 10240
kern.maxfilesperproc: 10000

La raison en est que

Le mot ' illimité ' lorsqu'il est utilisé comme paramètre pour définir maxfiles, est identique à l'utilisation de la valeur ' 10240 '.

Parce que launchctl n'accepte pas la chaîne de caractères 'unlimited' et la convertit en valeur 10240 !

[Je le prouverai ci-dessous, avec le code source de launchclt et la source du noyau de MacOS Mojave].

Mais d'abord, voyons si nous pouvons utiliser une valeur plus grande comme 2 millions :

sudo launchctl limit maxfiles 10000 2000000

$ launchctl limit maxfiles
    maxfiles    10000          2000000 

Oui, nous pouvons il a accepté la plus grande valeur.


Pourquoi cela se produit-il ?

Il est codé en dur dans le code source pour ne pas accepter ' illimité comme une valeur, donc une fois que nous l'avons changé, nous ne pouvons jamais le remettre.

Mais quelle est la valeur qui correspond à "illimité" ?

  • R : La valeur de ' illimité ' est INT_MAX, qui est ' 2147483647 ' (la valeur maximale du type Integer)

Allons à l'intérieur du code source #

Analyse du code source de launchclt.c et des routines du noyau de MacOS 10.14 Mojave sur la raison pour laquelle il n'est pas possible de définir maxfiles à 'unlimited' via la ligne de commande launchctl.

Toutes les informations ci-dessous sont mon analyse, en utilisant le code source de Apple, qui peut être obtenu via : https://opensource.apple.com

Rafael Prado - 2019/08/09

/* START OF CODE ANALYSIS */

// --------------- Analisys Comment ----------------------------------
// Looking at MacOS system core header file syslimits.h there is 
// a definition of OPEN_MAX with value 10240. 
// 
// This is the base value that will be used by default for 
// maxfiles value during system startup. 
//
// This comment you are reading here is mine.
//

/* FILE: sys/syslimits.h */
// *****************************************************************

#define OPEN_MAX                10240   /* max open files per process - todo, make a config option? */

// *****************************************************************

//
// --------------- Analisys Comment ---------------------------------
// Now we can see inside kernel config, that maxfiles parameter
// is a subprodut of OPEN_MAX, by adding 2048 to its value, 
// which give us the number 12288. 
// 
// This will became the default value for sysctl kern.maxfiles: 12288
//

/* FILE: conf/param.c */
// *****************************************************************

#define MAXFILES (OPEN_MAX + 2048)
int     maxfiles = MAXFILES;

// *****************************************************************

//
// --------------- Analisys Comment ---------------------------------
// Now here is why it is impossible to set 'unlimited' value using 
// the command line of launchctl:
//

/* FILE: launchd/support/launchctl.c */
// *****************************************************************
//

// (:..) Function lim2str() on line 2810
const char *
lim2str(rlim_t val, char *buf)
{
    if (val == RLIM_INFINITY)
        strcpy(buf, "unlimited");  
    else
        sprintf(buf, "%lld", val);
    return buf;
}

// (:..) Function srt2lim() on line 2821
bool
str2lim(const char *buf, rlim_t *res)
{
        char *endptr;
        *res = strtoll(buf, &endptr, 10);
        if (!strcmp(buf, "unlimited")) {
                *res = RLIM_INFINITY;
                return false;
        } else if (*endptr == '\0') {
                 return false;
        }
        return true;
}

// (:..) Function limit_cmd() found on line 2835
int
limit_cmd(int argc, char *const argv[])
{

    // ------------------------------------------------------------
    // This comment is not part of the source file, it is 
    // my analisys comment about what this function does.
    //
    // Here it is reading the parameters of 'launchctl limit argv2 argv3'  
    // and will call function srt2lim() to convert the args to limit values
    // 
    // Function srt2lim() is printed above.
    // ------------------------------------------------------------
    //
    // (:....) skipping to line 2850 inside this function

    if (argc >= 3 && str2lim(argv[2], &slim))
            badargs = true;
    else
            hlim = slim;

    if (argc == 4 && str2lim(argv[3], &hlim))
            badargs = true;

    // ------------------------------------------------------------
    // But before settin the values, there is a verification that 
    // prohibits using the word 'unlimited' as a parameter (only 
    // if used for 'maxfiles') and this check returns error, exiting
    // the limit_cmd() function [the function we are now inside] and
    // the system kernel paramter is never adjusted if we use 
    // the word 'unlimited' as a value.
    //
    // This comment was written by me 
    // and is not part of the source file.
    // ------------------------------------------------------------
    //
    // (:....) skiping to line 2906 inside this function

    bool maxfiles_exceeded = false;

    if (strncmp(argv[1], "maxfiles", sizeof("maxfiles")) == 0) {
        if (argc > 2) {
            maxfiles_exceeded = (strncmp(argv[2], "unlimited", sizeof("unlimited")) == 0);
        }

        if (argc > 3) {
            maxfiles_exceeded = (maxfiles_exceeded || strncmp(argv[3], "unlimited", sizeof("unlimited")) == 0);
        }

        if (maxfiles_exceeded) {
            launchctl_log(LOG_ERR, "Neither the hard nor soft limit for \"maxfiles\" can be unlimited. Please use a numeric parameter for both.");
            return 1;
        }
    }

    // -------------------------------------------------------------
    // We can see above, that it is prohibited to use the 'unlimited' value
    // And when we use it, the system assumes the 
    // default value of OPEN_MAX which is 10240 !
    // 
    // This explains and prove why setting 'unlimited' gives us 10240
    // --------------------------------------------------------------

// *****************************************************************

//
// --------------- Analisys Comment ---------------------------------
// Looking at another file from Kernel source, we can find another 
// place where it checks for 'unlimited' value, and also there is
// an explanation by Apple on it.
// 
// The comment BELOW IS Original comment from Apple Developers and 
// it is inside the file kern_resource.c from MacOS Kernel Source.
//

/* FILE: kern/kern_resource.c  */ 
// *****************************************************************

case RLIMIT_NOFILE:
        /*
         * Only root can set the maxfiles limits, as it is
         * systemwide resource.  If we are expecting POSIX behavior,
         * instead of clamping the value, return EINVAL.  We do this
         * because historically, people have been able to attempt to
         * set RLIM_INFINITY to get "whatever the maximum is".
        */
        if ( kauth_cred_issuser(kauth_cred_get()) ) {
                if (limp->rlim_cur != alimp->rlim_cur &&
                    limp->rlim_cur > (rlim_t)maxfiles) {
                        if (posix) {
                                error =  EINVAL;
                                goto out;
                        }
                        limp->rlim_cur = maxfiles;
                }
                if (limp->rlim_max != alimp->rlim_max &&
                    limp->rlim_max > (rlim_t)maxfiles)
                        limp->rlim_max = maxfiles;
        }
        else {
                if (limp->rlim_cur != alimp->rlim_cur &&
                    limp->rlim_cur > (rlim_t)maxfilesperproc) {
                        if (posix) {
                                error =  EINVAL;
                                goto out;
                        }
                        limp->rlim_cur = maxfilesperproc;
                }
                if (limp->rlim_max != alimp->rlim_max &&
                    limp->rlim_max > (rlim_t)maxfilesperproc)
                        limp->rlim_max = maxfilesperproc;
        }
        break;

// *****************************************************************

/* END OF CODE ANALYSIS */

Cela explique pourquoi il est impossible de remettre la valeur "illimitée" après l'avoir remplacée par une autre valeur.


Comment faire ? #

RLIM_INFINITY est défini à la ligne 416 du document <sys/resources.h>

/*
 * Symbolic constants for resource limits; since all limits are representable
 * as a type rlim_t, we are permitted to define RLIM_SAVED_* in terms of
 * RLIM_INFINITY.
 */
#define RLIM_INFINITY   (((__uint64_t)1 << 63) - 1)     /* no limit */
#define RLIM_SAVED_MAX  RLIM_INFINITY   /* Unrepresentable hard limit */
#define RLIM_SAVED_CUR  RLIM_INFINITY   /* Unrepresentable soft limit */

En pratique, pour la plate-forme actuelle, la valeur maximale illimitée d'INFINITY est limitée à INT_MAX (qui est la valeur maximale du type Integer).

En considérant cela, cela signifie que ' illimité moyens INT_MAX qui est la valeur 2147483647 .

Un possible solution de contournement peut être fixé à la valeur limite de 2147483647 :

sudo launchctl limit maxfiles 2147483647 2147483647

Parce que c'est la valeur maximale possible.

Comme il s'agit d'une solution de contournement possible. Il faudrait que j'aille plus loin dans les sources pour vérifier si cela signifie vraiment "la même chose" que "illimité".


Attention :

PS : S'il vous plaît, ne le mettez pas plus grand que 2147483647, parce que c'est SIGNED INT, et si vous mettez 214748364 8 (remarquez le chiffre huit, j'ajoute juste +1 à cette valeur maximale), l'INT SIGNÉ sera interprété comme suit négatif et vous allez instantanément faire planter votre MacOS, parce qu'il ne sera pas capable d'ouvrir un autre descripteur de fichier, y compris celui dont vous aurez besoin pour rétablir cette valeur, si vous essayez de la régler à nouveau en exécutant launchctl avec différents paramètres.

La seule solution sera de réinitialiser votre système si vous essayez ceci. Et vous risquez de perdre toutes vos données non sauvegardées. Essayez-le sur une machine virtuelle MacOS à des fins de test.


Code source Références :

<sys/resource.h> https://opensource.apple.com/source/xnu/xnu-4903.221.2/bsd/sys/resource.h.auto.html

<dev/unix_startup.c> https://opensource.apple.com/source/xnu/xnu-4903.221.2/bsd/dev/unix_startup.c.auto.html

<kern/kern_resource.c> https://opensource.apple.com/source/xnu/xnu-4903.221.2/bsd/kern/kern_resource.c.auto.html

<conf/param.c> https://opensource.apple.com/source/xnu/xnu-4903.221.2/bsd/conf/param.c.auto.html

<sys/syslimits.h> https://opensource.apple.com/source/xnu/xnu-4903.221.2/bsd/sys/syslimits.h.auto.html

launchctl.c https://opensource.apple.com/source/launchd/launchd-442.21/support/launchctl.c.auto.html

0voto

Johnny Bonelli Points 1

Mais vous ne pouvez pas ajuster la limite douce même si vous changez les fichiers maximum. Vous vous heurterez toujours à une brique avec 10xxx données ouvertes.

Ecrivez le code et essayez d'ouvrir un plus.

La 10.14 ne permet pas d'ouvrir plus que ça.

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X