Pregunta

Estoy desarrollando un sistema operativo y, en lugar de programar el núcleo, estoy diseñando el núcleo. Este sistema operativo está dirigido a la arquitectura x86 y mi objetivo es para las computadoras modernas. La cantidad estimada de RAM requerida es 256Mb o más.

¿Cuál es un buen tamaño para hacer que la pila de cada hilo se ejecute en el sistema? ¿Debería intentar diseñar el sistema de tal manera que la pila se pueda extender automáticamente si se alcanza la longitud máxima?

Creo que si recuerdo correctamente que una página en RAM tiene 4k o 4096 bytes y eso simplemente no me parece mucho. Definitivamente puedo ver los tiempos, especialmente cuando uso mucha recursividad, que me gustaría tener más de 1000 integars en RAM a la vez. Ahora, la solución real sería tener el programa haciendo esto usando malloc y administrar sus propios recursos de memoria, pero realmente me gustaría saber la opinión del usuario sobre esto.

¿Es 4k lo suficientemente grande para una pila con programas de computadora modernos? ¿Debería la pila ser más grande que eso? ¿Debe la pila expandirse automáticamente para acomodar cualquier tipo de tamaño? Estoy interesado en esto tanto desde el punto de vista práctico del desarrollador como desde el punto de vista de la seguridad.

¿4k es demasiado grande para una pila? Considerando la ejecución normal del programa, especialmente desde el punto de vista de las clases en C ++, noto que un buen código fuente tiende a malloc / new los datos que necesita cuando se crean las clases, para minimizar los datos que se arrojan. en una llamada de función.

En lo que ni siquiera me he metido es en el tamaño de la memoria caché del procesador. Idealmente, creo que la pila residiría en el caché para acelerar las cosas y no estoy seguro si necesito lograr esto, o si el procesador puede manejarlo por mí. Estaba planeando usar RAM aburrida y vieja para propósitos de prueba. No puedo decidir ¿Cuáles son las opciones?

¿Fue útil?

Solución

El tamaño de la pila depende de lo que estén haciendo tus hilos. Mi consejo:

  • hacer que el tamaño de la pila sea un parámetro en el momento de la creación del hilo (diferentes hilos harán diferentes cosas, y por lo tanto necesitarán diferentes tamaños de pila)
  • proporciona un valor predeterminado razonable para aquellos que no quieren molestarse en especificar un tamaño de pila (4K atrae al monstruo del control en mí, ya que hará que el stack-profligate, er, reciba la señal bastante rápido)
  • considere cómo detectará y lidiará con el desbordamiento de la pila. La detección puede ser complicada. Puede colocar páginas de protección, vacías, en los extremos de su pila, y eso generalmente funcionará. Pero usted confía en el comportamiento de Bad Thread para no saltar sobre ese foso y comenzar a contaminar lo que está más allá. En general, eso no sucederá ... pero eso es lo que hace que los errores realmente difíciles sean difíciles. Un mecanismo hermético implica piratear su compilador para generar código de comprobación de pila. En cuanto a lidiar con un desbordamiento de la pila, necesitará una pila dedicada en otro lugar en el que se ejecutará el hilo ofensor (o su ángel guardián, quien sea que decida que es, usted es el diseñador del sistema operativo, después de todo).
  • Recomiendo encarecidamente marcar los extremos de su pila con un patrón distintivo, de modo que cuando sus hilos pasen por los extremos (y siempre lo hacen), al menos puede ir post-mortem y ver que algo realmente sucedió salir corriendo de su pila. Una página de 0xDEADBEEF o algo así es útil.

Por cierto, los tamaños de página x86 son generalmente 4k, pero no tienen que serlo. Puedes ir con un tamaño de 64k o incluso más grande. La razón habitual para páginas más grandes es evitar errores TLB. Nuevamente, lo convertiría en una configuración del kernel o parámetro de tiempo de ejecución.

Otros consejos

Busque KERNEL_STACK_SIZE en el código fuente del kernel de Linux y verá que depende mucho de la arquitectura: PAGE_SIZE o 2 * PAGE_SIZE, etc. (a continuación se muestran algunos resultados: se eliminan muchos resultados intermedios).

./arch/cris/include/asm/processor.h:
#define KERNEL_STACK_SIZE PAGE_SIZE

./arch/ia64/include/asm/ptrace.h:
# define KERNEL_STACK_SIZE_ORDER        3
# define KERNEL_STACK_SIZE_ORDER        2
# define KERNEL_STACK_SIZE_ORDER        1
# define KERNEL_STACK_SIZE_ORDER        0
#define IA64_STK_OFFSET         ((1 << KERNEL_STACK_SIZE_ORDER)*PAGE_SIZE)
#define KERNEL_STACK_SIZE       IA64_STK_OFFSET

./arch/ia64/include/asm/mca.h:
    u64 mca_stack[KERNEL_STACK_SIZE/8];
    u64 init_stack[KERNEL_STACK_SIZE/8];

./arch/ia64/include/asm/thread_info.h:
#define THREAD_SIZE         KERNEL_STACK_SIZE

./arch/ia64/include/asm/mca_asm.h:
#define MCA_PT_REGS_OFFSET      ALIGN16(KERNEL_STACK_SIZE-IA64_PT_REGS_SIZE)

./arch/parisc/include/asm/processor.h:
#define KERNEL_STACK_SIZE   (4*PAGE_SIZE)

./arch/xtensa/include/asm/ptrace.h:
#define KERNEL_STACK_SIZE (2 * PAGE_SIZE)

./arch/microblaze/include/asm/processor.h:
# define KERNEL_STACK_SIZE  0x2000

Voy a tirar mis dos centavos para que la pelota ruede:

  • No estoy seguro de qué es un "típico" tamaño de la pila sería. Supongo que tal vez 8 KB por subproceso, y si un subproceso supera esta cantidad, solo arroje una excepción. Sin embargo, de acuerdo con esto , Windows tiene un tamaño de pila reservado predeterminado de 1 MB por subproceso, pero no se confirma de una vez (las páginas se confirman según sea necesario). Además, puede solicitar un tamaño de pila diferente para un EXE determinado en tiempo de compilación con una directiva de compilación. No estoy seguro de lo que hace Linux, pero he visto referencias a pilas de 4 KB (aunque creo que esto se puede cambiar cuando compila el núcleo y no estoy seguro de cuál es el tamaño de pila predeterminado ...)

  • Esto se relaciona con el primer punto. Probablemente desee un límite fijo sobre la cantidad de pila que puede obtener cada subproceso. Por lo tanto, probablemente no desee asignar automáticamente más espacio de pila cada vez que un hilo excede su espacio de pila actual, porque un programa defectuoso que se atasca en una recursión infinita va a consumir toda la memoria disponible.

Si está utilizando memoria virtual, desea hacer que la pila crezca. Forzar la asignación estática del tamaño de la pila, como es común en subprocesos a nivel de usuario como Qthreads y Windows Fibers, es un desastre. Difícil de usar, fácil de bloquear. Todos los sistemas operativos modernos hacen crecer la pila dinámicamente, creo que generalmente tienen una o dos páginas protegidas contra escritura debajo del puntero de la pila actual. Escribe allí y luego le dice al sistema operativo que la pila ha subido por debajo de su espacio asignado, y asigna una nueva página de protección debajo de eso y hace que la página que se golpeó sea editable. Mientras ninguna función individual asigne más de una página de datos, esto funciona bien. O puede usar dos o cuatro páginas de protección para permitir marcos de pila más grandes.

Si desea una forma de controlar el tamaño de la pila y su objetivo es un entorno realmente controlado y eficiente, pero no le importa la programación en el mismo estilo que Linux, etc., busque un modelo de ejecución de un solo disparo donde una tarea es se inicia cada vez que se detecta un evento relevante, se ejecuta hasta su finalización y luego almacena los datos persistentes en su estructura de datos de tareas. De esta manera, todos los hilos pueden compartir una sola pila. Utilizado en muchos sistemas operativos delgados en tiempo real para control automotriz y similares.

¿Por qué no hacer que el tamaño de la pila sea un elemento configurable, ya sea almacenado con el programa o especificado cuando un proceso crea otro proceso?

Hay muchas maneras de hacer que esto sea configurable.

Hay una directriz que establece '' 0, 1 o n '', lo que significa que debe permitir cero, uno o cualquier número (limitado por otras restricciones como la memoria) de un objeto; esto también se aplica al tamaño de los objetos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top