[LINUX-05] Hilo y programación del proceso de Linux

Este artículo es el original del autor, indique la fuente al volver a imprimir: https://www.cnblogs.com/leisure_chn/p/10393707.html


Este artículo es una nota de estudio para el "Proceso, subproceso y programación de Linux" de Song Baohua.

1 concepto de proceso

1.1 Definición de procesos y subprocesos

La definición clásica en el sistema operativo:
proceso: unidad de asignación de recursos.
Hilo: unidad de programación.
En el sistema operativo, se utiliza PCB (Bloque de control de proceso) para describir el proceso. El PCB en Linux es una estructura task_struct.
task_struct

1.2 Ciclo de vida del proceso

1.2.1 Estado del proceso

R, TASK_RUNNING: estado listo o estado de ejecución, el proceso está listo para ejecutarse, pero no necesariamente ocupa la CPU
S, TASK_INTERRUPTIBLE: sueño ligero, esperando recursos, puede responder a las señales, generalmente el estado del proceso de sueño activo entra en
D, TASK_UNINTERRUPTIBLE: sueño profundo , Esperando recursos, sin responder a las señales, el escenario típico es que el proceso no puede adquirir semáforos
Z, TASK_ZOMBIE: estado zombie, el proceso ha salido o finalizado, pero el proceso padre aún no se conoce, no hay estado de recuperación
T, TASK_STOPED: detener, estado de depuración El proceso se bloquea después de recibir la señal SIGSTOP
task_status

1.2.2 Creación de procesos y API relacionada con la muerte

1) system ()
inicia un nuevo proceso llamando al shell

2) exec ()
inicia un nuevo proceso reemplazando la imagen del proceso actual

3) fork ()
inicia un nuevo proceso copiando la imagen del proceso actual. Fork () devuelve 0 en el proceso secundario y fork () devuelve la ID del proceso secundario en el proceso primario.

4) wait () El
proceso padre se cuelga, esperando que finalice el proceso hijo.

5) Proceso huérfano y proceso zombie Proceso
huérfano: Sale un proceso padre, y uno o más de sus procesos hijos todavía se están ejecutando, entonces esos procesos hijos se convertirán en procesos huérfanos. El proceso de inicio será adoptado por el proceso de inicio (proceso número 1), y el proceso de inicio completará el trabajo de recopilación de estado para ellos. Los procesos huérfanos no desperdician recursos.
Proceso Zombie: Un proceso usa fork para crear un proceso hijo. Si el proceso hijo se cierra y el proceso padre no llama a wait o waitpid para obtener la información de estado del proceso hijo, el descriptor del proceso hijo aún se guarda en el sistema. Este proceso se llama proceso zombie. El proceso zombie desperdicia recursos del sistema (el descriptor del proceso task_struct existe, los recursos ocupados por el proceso se recuperan y no hay pérdida de memoria. De hecho, los recursos del sistema básicamente no se desperdician, vea el curso de Song Baohua).
Evite el proceso zombie: El
motivo del proceso zombie:
1. El proceso hijo envía una señal SIGCHLD al proceso padre después del final del proceso hijo. El proceso padre lo ignora por defecto;
2. El proceso padre no llama a la función wait () o waitpid () para esperar el final del proceso hijo.
Métodos para evitar procesos zombie:
1. El proceso padre llama a wait () o waitpid () para esperar a que finalice el proceso hijo, de modo que el proceso padre generalmente se bloquea en espera y no puede manejar otras cosas.
2. Capture la señal SIGCHLD y llame a la función de espera en la función de procesamiento de señal, para que el procesamiento pueda evitar los problemas descritos en 1.
3. Bifurca dos veces, el proceso padre crea un proceso hijo, el proceso hijo crea un proceso nieto, luego el proceso hijo se suicida, el proceso nieto se convierte en un proceso huérfano y es adoptado por el proceso init.

1.3 Comunicación entre procesos

1) Señal
Señal aquí se refiere a un evento. Por ejemplo, presionar la combinación de teclas CTRL-C enviará una señal SIGINT, que puede capturarse en el proceso y procesarse en consecuencia.

2) Pipe PIPE
todo es un archivo, la operación de la tubería es similar a la operación del archivo.
La función popen () es similar a la función fopen () y devuelve un puntero de objeto.
La función pipe () es similar a la función open () y devuelve un descriptor de objeto.
Las tuberías transfieren datos entre procesos relativos (procesos creados por el mismo proceso padre).

3) Canalizaciones con
nombre Las canalizaciones con nombre FIFO se pueden utilizar para la comunicación entre procesos antes de que no haya parentesco.
mkfifo () / mknod () creará un archivo con ruta y nombre en el sistema de archivos. Simplemente use este archivo de canalización como un archivo normal y podrá implementar la comunicación entre procesos.

4) Semáforo El
semáforo, la cola de mensajes y la memoria compartida son mecanismos IPC del Sistema V.
Sección crítica: una sección de código a la que puede acceder exclusivamente un solo proceso a la vez.
Semáforos: la mayoría de las comunicaciones entre procesos solo requieren semáforos binarios, por lo que aquí solo se analizan los semáforos binarios. Antes de ingresar a la sección crítica, realice la operación P (si el semáforo es mayor que 1, luego disminuya en 1 e ingrese a la sección crítica, de lo contrario suspenda el proceso); al salir de la sección crítica, realice la operación V (despierte si hay un proceso esperando a ser suspendido, de lo contrario Agrega 1) al semáforo.
Mutex: Mutex es un subconjunto de semáforo binario.

5) La cola de mensajes es
similar a la canalización de comandos, pero no es necesario considerar las operaciones complicadas de abrir / cerrar la canalización. La cola de mensajes existe independientemente del proceso.

6) La memoria compartida
necesita compartir un trozo de memoria para el intercambio de datos entre procesos de comunicación.

2 La esencia del hilo del proceso

El planificador de Linux reconoce realmente task_struct para la programación.
Independientemente del hilo del proceso, la capa inferior corresponde a una estructura_tarea. La diferencia entre un proceso y un hilo es cuántos recursos se comparten. Los dos procesos no comparten recursos en absoluto, y los dos hilos comparten todos los recursos.

2.1 horquilla ()

Después de ejecutar la bifurcación, el task_struck del proceso padre se copia al proceso hijo. Los recursos originales de los procesos padre e hijo son exactamente iguales, pero dos copias diferentes, por lo que cualquier cambio hará que los dos se dividan.
tenedor

El proceso padre-hijo usa COW (Copy-On-Write) para administrar los recursos de memoria (mm):

  1. Antes de la bifurcación, un área de memoria corresponde a una dirección física y una dirección virtual, el RW de los permisos del área de memoria;
  2. Después de la bifurcación, la dirección virtual del área de memoria vista por los procesos padre e hijo es la misma, y ​​la dirección física también es la misma. Los procesos padre e hijo en realidad están utilizando la misma pieza de memoria física. No se produce ninguna copia de memoria, y el sistema operativo cambiará el permiso del área de memoria a RO;
  3. El proceso primario o secundario que se escribe en el área de memoria activará PageFault. El sistema operativo copiará el área de memoria en este momento. La dirección virtual vista por el proceso primario y secundario sigue siendo la misma, pero la dirección física no es la misma. La asignación de la dirección virtual a la dirección física de cada proceso es administrada por la MMU (Unidad de administración de memoria, unidad de administración de memoria).
    VACA

La bifurcación se ejecuta en la CPU con MMU.

2.2 vfork ()

vfork
Para CPU sin MMU, COW no se puede aplicar y fork no se puede admitir.
Las CPU sin MMU usan vfork para crear procesos, y el proceso padre se bloqueará hasta que el proceso hijo salga o se ejecute.
La diferencia esencial entre vfork y fork es que los procesos padre e hijo en vfork comparten la misma área de memoria.

2.3 pthread_create ()

pthread
Los hilos de Linux son esencialmente procesos, pero todos los recursos se comparten entre hilos. Como se muestra arriba.
Cada hilo tiene su propia task_struct, porque cada hilo puede ser programado por la CPU. Los mismos recursos de proceso se comparten entre múltiples subprocesos. Estos dos puntos solo cumplen con la definición de hilo.
Así es como Linux implementa hilos con procesos, por lo que los hilos también se denominan procesos ligeros.

2.4 PID y TGID

pid_tgid
POSIX requiere que varios subprocesos del mismo proceso obtengan una ID de proceso para obtener un valor de ID único.

Linux multihilo del mismo proceso, de hecho, cada subproceso tiene un PID desde la perspectiva del kernel, pero en el espacio del usuario, getpid devuelve un valor único. Linux utiliza un truco para introducir el concepto de TGID, el TGID devuelto por getpid Valor.

El comando top desde la perspectiva del proceso: el comando top
sin parámetros (el valor predeterminado) muestra la utilización de la CPU de un solo núcleo por el proceso. Por ejemplo, hay tres hilos en un proceso, el hilo principal crea el hilo 1 y el hilo 2, y el hilo 1 Y el subproceso 2 requiere un tiempo (1), para la CPU de doble núcleo, el subproceso 1 y el subproceso 2 usan un núcleo, la tasa de ocupación es del 100%, luego la utilización de la CPU del proceso visto por el comando superior es del 200%, el proceso ID es el PID del hilo principal (también TGID).

El comando superior
top –Hdesde la perspectiva del hilo : el comando muestra la ocupación de la CPU desde la perspectiva del hilo. En el ejemplo anterior, mostrará que la tasa de ocupación del hilo 1 es del 100% y la tasa de ocupación del hilo 2 es del 100%.
El PID del subproceso se refiere a la ID del proceso del espacio del usuario, y el valor es TGID; cuando se señala específicamente, el PID del subproceso en el espacio del kernel se refiere al PID único para el subproceso en la task_struct en el kernel.

3 Programación de procesos

horario_tarea

3.1 Programación de procesos en tiempo real

SCHED_FIFO: diferentes prioridades se ejecutan para dormir primero de acuerdo con la prioridad más alta, y luego se ejecutan antes de la prioridad más baja; la misma prioridad viene primero en entrar, primero en salir.
SCHED_RR: diferentes prioridades se ejecutan para dormir primero de acuerdo con la prioridad más alta y luego se ejecutan antes de la prioridad más baja; la misma prioridad gira.
Kernel RT parche:
/ proc / sys / kernel / sched_rt_period_us
/ proc / sys / kernel / sched_rt_runtime_us
En el período de tiempo, RT solo puede ejecutarse en la mayoría del tiempo de ejecución

3.2 Programación ordinaria de procesos

SCHED_OTHER :

3.2.1 Prioridad dinámica (principios de 2.6)

Los procesos tienen dos parámetros de medición: consumo de E / S y consumo de CPU.
Alta prioridad significa: 1) obtener más segmentos de tiempo, 2) puede evitar una prioridad baja al despertar. Tiempo de rotación de la porción.
El kernel almacena la prioridad estática, y los usuarios pueden modificar la prioridad estática a través de nice.
La prioridad dinámica del proceso se calcula en tiempo real en función de la prioridad estática. El algoritmo de programación recompensa el consumo de E / S (aumentando la prioridad para aumentar el tiempo real) y castiga el consumo de CPU (disminuyendo la prioridad para reducir el tiempo real)

3.2.2 CFS: programación completamente justa (nuevo núcleo)

Árbol rojo-negro, el nodo izquierdo es más pequeño que el nodo derecho para
ejecutar el proceso
con el tiempo de ejecución más pequeño hasta ahora, teniendo en cuenta que CPU / IO y agradable
siempre encuentran la programación de subprocesos con el tiempo de ejecución más pequeño.
vruntime = pruntime / weight × 1024;
vruntime es el tiempo de ejecución virtual, pruntime es el tiempo de ejecución físico, el peso está determinado por el valor agradable (cuanto menor es el agradable, mayor es el peso), el hilo con menos tiempo de ejecución y menor valor agradable tendrá un tiempo de ejecución más pequeño, Obtenga una programación prioritaria. Este es un proceso que cambia dinámicamente con la operación.
vruntime

Herramientas chrt y renice:

Establezca SCHED_FIFO y 50 RT prioridad 
# chrt -f -a -p 50  10576 
Establezca nice 
# renice -n- 5 -g 9394 
# nice -n 5 ./a. Out

4 Equilibrio de carga multinúcleo

Ligeramente

5 referencias

[1] Song Baohua, procesos, subprocesos y programación de Linux
[2]  https://blog.csdn.net/sdkdlwk/article/details/65938204
[3]  https://blog.csdn.net/kklvsports/article/details/ 52268085
[4]  https://blog.csdn.net/qq_20218109/article/details/52078076
[5]  https://www.cnblogs.com/yuxingfirst/p/3165407.html

Supongo que te gusta

Origin www.cnblogs.com/Ph-one/p/12736406.html
Recomendado
Clasificación