16 votos

¿Por qué establecer el límite rígido para maxfiles en "ilimitado" usando `launchctl limit` da como resultado un límite rígido ligeramente superior al límite soft?

¿Por qué establecer el límite rígido para maxfiles en "ilimitado" usando launchctl limit resultado un límite rígido ligeramente superior al límite soft?

Al establecer el límite de maxfiles usando launchctl en launchctl limit maxfiles 10000 unlimited , obtengo el siguiente resultado:

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

Inicialmente, después de que el sistema se ha iniciado, el límite rígido se establece en "ilimitado", entonces, ¿por qué no puedo establecer el mismo límite rígido configurándolo manualmente?

34voto

Prado Puntos 261

Un nuevo sistema de instalación, con los parámetros por defecto está configurado con el siguiente sistema de ancho de los límites de archivo:

  • El Kernel De Archivos Max: 12288
  • Max Archivos por Proceso: 10240

Kernel actual sysctl parámetros se pueden ver con sysctl comando:

$ sysctl -a |grep kern.maxf

kern.maxfiles: 12288
kern.maxfilesperproc: 10240

Ahora vamos a ver los límites de los valores, el uso de ulimit comando:

Para los límites SUAVES: [podemos ver que: abrir archivos = 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

Para limites: [podemos ver que: abrir archivos = Ilimitado]

$ 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


El uso de launchctl

launchctl tiene la capacidad de configurar los valores límite, o mostrar los valores actuales.

El uso de lanchctl limit muestra todos los actuales límites rígidos y Suaves, y podemos ver que el límite elástico es de 256 y límite duro es 'ilimitado' para el elemento maxfiles. (la misma información que obtuvo usando comando ulimit arriba)

$ 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      

Para filtrar, simplemente tenemos que usar launchctl limit maxfiles

$ launchctl limit maxfiles
    maxfiles    256            unlimited

Ahora vamos a intentar cambiar esos valores #

Utilizando la línea de comandos, como por ejemplo:

sudo launchctl limit maxfiles 10000 unlimited

Pero después, cuando yo ejecute de nuevo el comando para mostrar los límites, podemos ver que:

  • el límite elástico se ajusta de 256 a 10000,
  • pero el límite se redujo de 'ilimitado' a '10240'
sudo launchctl limit          
    maxfiles    10000          10240          

Y a partir de ahora, es imposible volver a un número ilimitado!

Podemos ver que después de la ejecución, sino que también cambió el kernel sysctl parámetros

$ sysctl -A |grep max

kern.maxfiles: 10240
kern.maxfilesperproc: 10000

La razón es

La palabra"ilimitado"cuando se usa como un parámetro para la configuración de maxfiles, es igual que usar el valor de '10240'.

Porque launchctl no aceptan la cadena 'ilimitado' y convertirlo el valor de 10240!

[Voy a demostrar a continuación, con el código fuente de launchclt y fuente de MacOS Mojave kernel]

Pero primero, vamos a ver si podemos utilizar un valor más grande, como de 2 millones de:

sudo launchctl limit maxfiles 10000 2000000

$ launchctl limit maxfiles
    maxfiles    10000          2000000 

Sí, podemos, aceptó el valor más grande.


Por qué sucede esto

Es codificado en el código fuente para que no acepte 'ilimitado' como un valor, así que una vez cambiado, nunca se puede poner de nuevo.

Pero ¿cuál es el valor que corresponde a 'ilimitado' ?

  • R: El valor de 'ilimitado' es INT_MAX, que es '2147483647' (el valor máximo del Tipo Entero)

Vamos a entrar en el código fuente #

Análisis de código fuente de launchclt.c y las rutinas del Núcleo de MacOS 10.14 Mojave acerca de por qué no es posible establecer maxfiles a 'ilimitado' a través de launchctl de la línea de comandos.

Toda la información a continuación es mi análisis, utilizando el código fuente de Apple, que puede ser obtenida a través de: 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 */


Esto explica por qué es imposible establecer 'ilimitado' de nuevo, después de cambiarlo por algún otro valor.


Cómo hacerlo? #

RLIM_INFINITY se define en la línea 416 de <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 la práctica, para la plataforma actual, el ilimitado INFINITO valor máximo está limitado a INT_MAX (que es el valor máximo del Tipo Entero)

Teniendo en cuenta eso, significa que 'ilimitado' significa INT_MAX, que es el valor 2147483647.

Una posible solución podría ser establecer el valor límite de 2147483647:

sudo launchctl limit maxfiles 2147483647 2147483647

Debido a que este es el valor máximo posible.

Dado que esta es una posible solución. Yo tendría que ir más profundo en origen para comprobar si esto realmente significa 'lo mismo' como 'ilimitado'.


Advertencia:

PS: por Favor, no lo deje más grande que 2147483647, porque es SIGNED INT, y si pones 2147483648 (aviso al número ocho, acabo de añadir +1 a ese valor máximo), el SIGNED INT se interpretarán como negativa, y al instante casi chocar su macOS, porque no será capaz de abrir cualquier otro descriptor de archivo, incluyendo el que usted necesita para revertir este valor de nuevo, si intenta ajustar de nuevo por ejecutar launchctl con diferentes parámetros.

La única solución será el restablecimiento de su sistema si usted intenta esto. Y usted puede perder todas sus cosas que no son salvos. Intente en algunos MacOS máquina virtual para propósitos de prueba


Código fuente de Referencias:

<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

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X