multithreading - toman - recursos y servicios que se comparten
¿Qué recursos se comparten entre los hilos? (12)
Algo que realmente hay que señalar es que realmente hay dos aspectos de esta pregunta: el aspecto teórico y el aspecto de las implementaciones.
Primero, veamos el aspecto teórico. Debe comprender qué es conceptualmente un proceso para comprender la diferencia entre un proceso y un subproceso y lo que se comparte entre ellos.
Tenemos lo siguiente de la sección 2.2.2 El modelo de rosca clásica en los sistemas operativos modernos 3e de Tanenbaum:
El modelo de proceso se basa en dos conceptos independientes: agrupación y ejecución de recursos. A veces es útil separarlos; aquí es donde entran los hilos ....
Él continúa:
Una forma de ver un proceso es que es una forma de agrupar recursos relacionados. Un proceso tiene un espacio de direcciones que contiene el texto y los datos del programa, así como otros recursos. Estos recursos pueden incluir archivos abiertos, procesos secundarios, alarmas pendientes, manejadores de señales, información contable y más. Al juntarlos en la forma de un proceso, se pueden gestionar más fácilmente. El otro concepto que tiene un proceso es un hilo de ejecución, generalmente acortado a solo un hilo. El hilo tiene un contador de programa que realiza un seguimiento de qué instrucción ejecutar a continuación. Cuenta con registros, que mantienen sus actuales variables de trabajo. Tiene una pila, que contiene el historial de ejecución, con un marco para cada procedimiento llamado pero aún no devuelto. Aunque un subproceso debe ejecutarse en algún proceso, el subproceso y su proceso son conceptos diferentes y se pueden tratar por separado. Los procesos se utilizan para agrupar los recursos; Los hilos son las entidades programadas para su ejecución en la CPU.
Más abajo proporciona la siguiente tabla:
Per process items | Per thread items
------------------------------|-----------------
Address space | Program counter
Global variables | Registers
Open files | Stack
Child processes | State
Pending alarms |
Signals and signal handlers |
Accounting information |
Lo anterior es lo que necesitas para que funcionen los hilos. Como han señalado otros, cosas como los segmentos son detalles de implementación dependientes del sistema operativo.
Recientemente, me hicieron una pregunta en una entrevista, ¿cuál es la diferencia entre un proceso y un hilo? Realmente, no sabía la respuesta. Pensé por un minuto y di una respuesta muy rara.
Los hilos comparten la misma memoria, los procesos no. Después de responder esto, el entrevistador me dio una sonrisa malvada y me lanzó las siguientes preguntas:
P. ¿Conoces los segmentos en que se divide un programa?
Mi respuesta: sí (pensé que era fácil) Stack, Data, Code, Heap
P. Entonces, dime: ¿qué segmentos comparten los hilos?
No pude contestar esto y terminé diciendo todos ellos.
Por favor, ¿alguien puede presentar las respuestas correctas e impresionantes de la diferencia entre un proceso y un hilo?
Dígale al entrevistador que depende completamente de la implementación del sistema operativo.
Tome Windows x86, por ejemplo. Solo hay 2 segmentos [1], Código y Datos. Y ambos están asignados a todo el espacio de direcciones de 2 GB (lineal, usuario). Base = 0, límite = 2GB. Habrían hecho uno, pero x86 no permite que un segmento sea Lectura / Escritura y Ejecutar. Así que hicieron dos y configuraron CS para que apunte al descriptor de código, y el resto (DS, ES, SS, etc.) para que apunten al otro [2]. ¡Pero ambos apuntan a lo mismo!
La persona que te entrevistó había hecho una suposición oculta de que él / ella no había dicho, y ese es un truco estúpido para tirar.
Así que con respecto
P. Entonces, dime qué segmento del hilo comparte?
Los segmentos son irrelevantes para la pregunta, al menos en Windows. Los hilos comparten todo el espacio de direcciones. Solo hay 1 segmento de pila, SS, y apunta a lo mismo que hacen DS, ES y CS [2]. Es decir, todo el sangriento espacio de usuario . 0-2GB. Por supuesto, eso no significa que los hilos solo tengan 1 pila. Naturalmente, cada uno tiene su propia pila, pero los segmentos x86 no se utilizan para este propósito.
Tal vez * nix hace algo diferente. Quién sabe. La premisa en la que se basaba la pregunta estaba rota.
- Al menos para el espacio de usuario.
- Desde el
ntsd notepad
:cs=001b ss=0023 ds=0023 es=0023
De Wikipedia (creo que sería una buena respuesta para el entrevistador: P)
Los hilos difieren de los procesos tradicionales del sistema operativo multitarea en que:
- los procesos suelen ser independientes, mientras que los subprocesos existen como subconjuntos de un proceso
- los procesos llevan información de estado considerable, mientras que varios subprocesos dentro de un proceso comparten el estado, así como la memoria y otros recursos
- los procesos tienen espacios de direcciones separados, mientras que los hilos comparten su espacio de direcciones
- Los procesos interactúan solo a través de mecanismos de comunicación entre procesos provistos por el sistema.
- El cambio de contexto entre hilos en el mismo proceso suele ser más rápido que el cambio de contexto entre procesos.
En proceso, todos los subprocesos comparten recursos del sistema como memoria de pila, etc. mientras Thread tiene su propia pila
Por lo tanto, su ans debe ser un montón de memoria que todos los subprocesos comparten para un proceso.
En un marco x86, uno puede dividir tantos segmentos (hasta 2 ^ 16-1). Las directivas ASM SEGMENT / ENDS lo permiten, y los operadores SEG y OFFSET permiten la inicialización de registros de segmento. CS: IP generalmente es inicializada por el cargador, pero para DS, ES, SS la aplicación es responsable con la inicialización. Muchos entornos permiten las denominadas "definiciones de segmento simplificadas" como .code, .data, .bss, .stack, etc. y, dependiendo también del "modelo de memoria" (pequeño, grande, compacto, etc.) el cargador inicializa los registros de segmento en consecuencia. Generalmente .data, .bss, .stack y otros segmentos usuales (no he hecho esto desde hace 20 años, por lo que no recuerdo todos) se agrupan en un solo grupo, es por eso que DS, ES y SS apuntan a misma área, pero esto es solo para simplificar las cosas.
En general, todos los registros de segmento pueden tener valores diferentes en tiempo de ejecución. Por lo tanto, la pregunta de la entrevista fue correcta: cuál de los CÓDIGOS, DATOS y STACK se comparten entre los hilos. La administración del montón es otra cosa, es simplemente una secuencia de llamadas al sistema operativo. Pero, ¿qué sucede si no tiene un sistema operativo en absoluto, como en un sistema integrado? ¿Aún puede tener un nuevo / eliminar en su código?
Mi consejo para los jóvenes es leer un buen libro de programación de ensamblaje. Parece que los currículos universitarios son bastante pobres a este respecto.
Eres bastante correcto, pero los hilos comparten todos los segmentos excepto la pila. Los subprocesos tienen pilas de llamadas independientes, sin embargo, la memoria en otras pilas de subprocesos sigue siendo accesible y, en teoría, podría tener un puntero a la memoria en el marco de la pila local de algún otro subproceso (aunque probablemente debería encontrar un lugar mejor para colocar esa memoria).
Generalmente, los hilos se denominan proceso de peso ligero. Si dividimos la memoria en tres secciones, será: Código, datos y Pila. Cada proceso tiene su propio código, datos y secciones de pila y, debido a este cambio de contexto, el tiempo es un poco alto. Para reducir el tiempo de cambio de contexto, las personas han creado el concepto de subproceso, que comparte datos y segmentos de código con otros subprocesos / procesos y tiene su propio segmento STACK.
Los hilos comparten todo [1]. Hay un espacio de direcciones para todo el proceso.
Cada hilo tiene su propia pila y registros, pero las pilas de todos los hilos están visibles en el espacio de direcciones compartido.
Si un hilo asigna algún objeto en su pila y envía la dirección a otro hilo, ambos tendrán igual acceso a ese objeto.
En realidad, acabo de notar un problema más amplio: creo que estás confundiendo dos usos del segmento de palabras.
El formato de archivo para un ejecutable (p. Ej., ELF) tiene distintas secciones, que pueden denominarse segmentos, que contienen código compilado (texto), datos inicializados, símbolos de enlace, información de depuración, etc. No hay segmentos de pila o pila Aquí, ya que esas son construcciones de tiempo de ejecución solamente.
Estos segmentos de archivos binarios se pueden asignar en el espacio de direcciones del proceso por separado, con diferentes permisos (por ejemplo, ejecutable de solo lectura para código / texto, y copia ejecutable no ejecutable para datos inicializados).
Las áreas de este espacio de direcciones se utilizan para diferentes propósitos, como la asignación de almacenamiento dinámico y las pilas de hilos, por convención (impuesta por las bibliotecas de tiempo de ejecución de su idioma). Sin embargo, todo es solo memoria, y probablemente no esté segmentado a menos que esté ejecutando en el modo 8086 virtual. La pila de cada hilo es una porción de memoria asignada en el momento de la creación del hilo, con la dirección superior de la pila actual almacenada en un registro de puntero de pila, y cada hilo mantiene su propio puntero de pila junto con sus otros registros.
[1] OK, lo sé: máscaras de señal, TSS / TSD, etc. Sin embargo, el espacio de direcciones, incluidos todos los segmentos de programa mapeados, todavía se comparte.
Los hilos comparten datos y códigos mientras que los procesos no lo hacen. La pila no se comparte para ambos.
Los procesos también pueden compartir memoria, código más preciso, por ejemplo, después de un Fork()
, pero esto es un detalle de implementación y optimización (sistema operativo). El código compartido por múltiples procesos (con suerte) se duplicará en la primera escritura del código, lo que se conoce como copy-on-write . No estoy seguro de la semántica exacta para el código de subprocesos, pero asumo un código compartido.
Process Thread Stack private private Data private shared Code private1 shared2
1 El código es lógicamente privado pero se puede compartir por razones de rendimiento. 2 No estoy 100% seguro.
Los subprocesos comparten el código y los segmentos de datos y el montón, pero no comparten la pila.
Thread comparte el montón (hay una investigación sobre el montón específico del hilo) pero la implementación actual comparte el montón. (y por supuesto el código)
Un proceso tiene código, datos, montón y segmentos de pila. Ahora, el puntero de instrucción (IP) de un subproceso O subprocesos apunta al segmento de código del proceso. Los segmentos de datos y montón son compartidos por todos los hilos. Ahora, ¿qué pasa con el área de la pila? ¿Qué es en realidad el área de pila? Es un área creada por el proceso solo para su uso por el hilo ... porque las pilas se pueden usar de manera mucho más rápida que los montones, etc. El área de la pila del proceso se divide entre los hilos, es decir, si hay 3 hilos, entonces el El área de apilamiento del proceso se divide en 3 partes y cada una se asigna a los 3 hilos. En otras palabras, cuando decimos que cada subproceso tiene su propia pila, esa pila es en realidad una parte del área de la pila de proceso asignada a cada subproceso. Cuando un hilo termina su ejecución, la pila del hilo es reclamada por el proceso. De hecho, no solo la pila de un proceso se divide entre subprocesos, sino que todo el conjunto de registros que utiliza un subproceso como SP, PC y registros de estado son los registros del proceso. Por lo tanto, cuando se trata de compartir, el código, los datos y las áreas de almacenamiento dinámico se comparten, mientras que el área de la pila se divide entre subprocesos.