[LINUX-04] Proceso de Linux, programación, hilo, contexto de proceso y otra comprensión

1. La señal proviene del proceso o del núcleo
2. El espacio de código y el espacio de datos (variables globales o variables estáticas), descriptores de archivo, señales y memoria asignada por malloc compartida por el hilo, cada hilo tiene un espacio de pila independiente y un contador de programa, Al crear un hilo, el orden de ejecución del hilo que llama a la función pthread_create y el hilo recién creado es aleatorio

3. En Linux, los procesos ligeros se utilizan para simular hilos, y las funciones relacionadas de las operaciones de hilos se implementan a través de bibliotecas de hilos de terceros (Linuxthreads o Native POSIX Thread Library (NPTL))

4. down () / down_interruptible () se usa para sincronizar la unidad de ejecución del espacio del kernel, donde down (struct semaphore * sem) se usa para obtener el semáforo sem. Si la persona que llama no puede obtener el semáforo, provocará la suspensión y entrará en el estado de suspensión La señal no puede interrumpir el proceso, y la señal puede interrumpir el proceso que se fue a dormir debido a down_interruptible, haciendo que la función regrese.

5. Intervalo de tiempo: el número de tics de reloj restantes cuando el proceso está en el estado de ejecución. Este valor se reduce en 1 cada vez que llega la interrupción del reloj. Cuando el valor de este campo se vuelve cada vez más pequeño hasta que es 0, el campo need_resched se establece en 1 (cuando llegue el momento de la programación, verifique el valor de este campo, si es 1, luego llame al horario ())

6. El reloj del sistema operativo (reloj de marcación) se utiliza como reloj de referencia para la programación del sistema Linux.

7. En la programación multiproceso de Linux, puede usar la función de suspensión para liberar el control de la CPU del hilo.

#include <stdio.h> 
#include <unistd.h> 
#include < string .h> 
#include <pthread.h> void * SleepTest1 ( void * arg) 
{ while ( 1 ) 
        { 
                printf ( " el sleeptest1 está bien! \ n " ); 
                dormir ( 3 ); 
        } 
} void * SleepTest2 ( void * arg) 
{ while ( 1 ) 
        { 
                printf ( "



        



        ¡sleeptest2 está bien! \ n " ); 
                sleep ( 10 ); 
        } 
} 

int main ( int argc, char * argv []) 
{ 
        pthread_t tid [ 2 ];
         int ret; 
        ret = pthread_create (& tid [ 0 ], NULL, SleepTest1, NULL);
         if (ret < 0 ) 
        { 
                printf ( " pthread_create " );
                 return - 1 ; 
        } 
        ret= pthread_create (& tid [ 1 ], NULL, SleepTest2, NULL);
        if (ret < 0 ) 
        { 
                perror ( " pthread_create " );
                volver - 1 ; 
        } 
        printf ( " el thread1 y el thread2 crean ok! \ n " ); 

        pthread_join (tid [ 0 ], NULL); 
        pthread_join (tid [ 1 ], NULL); 
        printf ( " la salida del hilo! \ n " ); 

        devuelve  0 ; 
}

 

8. Proceso Zombie: cuando sale cada proceso, el núcleo libera todos los recursos del proceso (incluidos los archivos abiertos, la memoria ocupada, etc.), pero aún conserva cierta información (incluido el número de proceso, el estado de salida y el tiempo de ejecución) Etc.) hasta que el proceso padre se recupere mediante wait / waitpid externo. En este punto, el proceso está en un estado muerto.

 

9. Salida del proceso

Cuando finaliza el proceso, debe liberar los recursos que tiene y decirle al proceso padre de alguna manera (enviar señal SIGCHLD). La salida del proceso suele ser mostrar o llamar implícitamente a eixt (), o aceptar algún tipo de señal. Pero por cualquier motivo para salir, finalmente se llamó a do_exit.

 

Hay dos llamadas al sistema exit y exit_group para la salida del proceso, exit solo termina un determinado proceso y exit_group procesa en todo el hilo. Sus funciones de servicio en el núcleo son sys_exit y sys_exit_group, y llaman a do_exit y do_group_exit respectivamente. Y do_group finalmente llama a do_exit (do_exit se define en kernel / exit.c).

 

10. Ver el descriptor de archivo abierto por un proceso

[root @ localhost proc] # cd 1328 /
[root @ localhost 1328] # ls
attr clear_refs cpuset exe io loginuid mountinfo net pagemap sched smaps statm task
auxv cmdline cwd fd latencia mapas monturas oom_adj personalidad schedstat estado de pila wchan
cgroup coredump_filter medio ambiente fdinfo límites mem mountstats oom_score root sessionid stat syscall
[root @ localhost 1328] # cd fdinfo /
[root @ localhost fdinfo] # ls
0 1 10 11 12 13 14 15 16 17 18 19 2 20 21 22 23 3 4 5 6 7 8 9
[root @localhost fdinfo] # 

El número que figura en la carpeta fdinfo es el descriptor de archivo abierto por el proceso.

11. Función de horquilla

Cuando se copia la bifurcación, ¡el código ejecutado por la secuencia principal no debe ejecutarse en frío!

12. Explicación detallada del contexto del proceso y el contexto de interrupción.

Los programas de aplicación en el espacio del usuario ingresan al espacio del kernel a través de llamadas al sistema. En este momento, el proceso de espacio de usuario debe pasar muchas variables y valores de parámetros al kernel. Cuando se ejecuta el modo kernel, también debe guardar algunos valores de registro y variables del proceso de usuario. El llamado "contexto de proceso" puede considerarse como estos parámetros que el proceso del usuario pasa al núcleo y al conjunto de variables y valores de registro que el núcleo y el entorno deben guardar en ese momento .

A través de la señal de activación, el hardware hace que el núcleo llame al controlador de interrupciones e ingrese al espacio del núcleo. Durante este proceso, algunas variables y parámetros del hardware también se pasan al núcleo, y el núcleo utiliza estos parámetros para realizar el procesamiento de interrupción. El llamado "contexto de interrupción" en realidad puede considerarse como estos parámetros pasados ​​por el hardware y algunos otros entornos que el núcleo necesita guardar (principalmente el entorno del proceso que está actualmente interrumpido) .

[Comprensión simple: durante el funcionamiento del dispositivo, hay dos partes de software que pueden ejecutarse, a saber, el programa de usuario y el núcleo del sistema. Cuando se ejecuta una aplicación, se puede acceder al núcleo a través de funciones como ioctl. Después de que el núcleo reciba este acceso, la CPU Ejecute el segmento de código de función correspondiente del núcleo. En este momento, guarde la información del entorno actual para asegurarse de que el código del núcleo regrese al segmento de código de aplicación correspondiente después de la ejecución. Este es el contexto del proceso; para el contexto de interrupción, solo el núcleo tiene procesamiento de interrupción, que es lo mismo que la naturaleza de interrupción del chip único]

Un párrafo en el comentario completo de LINUX:

Cuando se ejecuta un proceso, los valores en todos los registros de la CPU, el estado del proceso y el contenido de la pila se denominan contexto del proceso. Cuando el kernel necesita cambiar a otro proceso, necesita guardar todo el estado del proceso actual, es decir, guardar el contexto del proceso actual, de modo que cuando el proceso se ejecute nuevamente, el estado en el momento del cambio debe ejecutarse. En LINUX, el contexto del proceso actual se almacena en la estructura de datos de la tarea del proceso. Cuando ocurre una interrupción, el núcleo ejecuta la rutina del servicio de interrupción en el estado del núcleo en el contexto del proceso interrumpido. Pero al mismo tiempo, todos los recursos necesarios estarán reservados para que la ejecución del proceso interrumpido pueda reanudarse cuando finalice el servicio de retransmisión.

El contexto del proceso es un modo operativo en el que se ubica el kernel. En este momento, el kernel se ejecuta en nombre del proceso, por ejemplo, ejecutando una llamada al sistema o ejecutando un hilo del kernel.
Contexto: el contexto es simplemente un entorno, relativo al proceso, es el entorno cuando se ejecuta el proceso. Específicamente, se trata de cada variable y datos, incluidas todas las variables de registro, los archivos abiertos por el proceso y la información de la memoria.
    El contexto de un proceso se puede dividir en tres partes: contexto a nivel de usuario, contexto de registro y contexto a nivel de sistema.
    Contexto a nivel de usuario: texto, datos, pila de usuario y área de almacenamiento compartida;
    contexto de registro: registro de propósito general, registro de programa (IP), registro de estado del procesador (EFLAGS), puntero de pila (ESP);
    contexto a nivel de sistema: bloque de control de proceso task_struct, Información de gestión de memoria (mm_struct, vm_area_struct, pgd, pte), kernel stack.

    Cuando se produce la programación del proceso , un cambio de proceso es un cambio de contexto. El sistema operativo debe cambiar toda la información mencionada anteriormente antes de que el proceso recién programado pueda ejecutarse. Y el cambio de modo por la llamada al sistema (cambio de modo). En comparación con el cambio de proceso, el cambio de modo es mucho más fácil y ahorra tiempo, porque la tarea principal del cambio de modo es cambiar el contexto del registro del proceso. 

13. Terminación del proceso

En Linux, la salida del proceso se divide en salida normal y salida anormal.

1> Salga normalmente

Ejecute return en la función main ().

b. Llamar a la función de salida ()

c. Llamar a la función _exit ()

2> salida anormal

a. Función de anulación de llamada

b) El proceso recibe una señal y la señal termina el programa.

Independientemente del método de salida, el sistema eventualmente ejecutará el mismo código en el núcleo. Este código se utiliza para cerrar el descriptor de archivo abierto utilizado por el proceso y liberar la memoria y otros recursos que ocupa.

3> La diferencia entre _exit () y exit ():

a._exit () regresa al kernel inmediatamente después de la ejecución, y exit () primero debe realizar algunas operaciones de limpieza y luego dar el control al kernel.

Una de las diferencias entre exit () y _exit (): la primera admite la llamada al programa de compensación definido por el usuario (registro de la función atexit)

c. Al llamar a la función _exit, cerrará todos los descriptores de archivos del proceso, limpiará la memoria y algunas otras funciones de limpieza del núcleo, pero no parpadeará

Nueva secuencia (stdin, stdout, stderr ...) . La función de salida es un contenedor sobre la función _exit, que llamará a _exit y

Actualice la secuencia antes de llamar.

 

14. Tecnología de copia en escritura

Fork copiará todo el contenido del proceso de llamada al proceso hijo recién creado intacto, estas acciones de copia requieren mucho tiempo y, si llamamos a un ejecutivo inmediatamente después de que finalice la bifurcación, estas copias duras de las cosas Se borrará de inmediato, lo que parece muy rentable, por lo que las personas han diseñado una tecnología de "copia en escritura", para que la bifurcación no copie de inmediato el contenido del proceso principal, sino a la realidad Se copia solo cuando se usa, de modo que si la siguiente declaración es ejecutiva, no será inútil y aumentará la eficiencia.

15. Hay varios puntos a tener en cuenta al ejecutar programas en segundo plano:

Tenga cuidado al ejecutar trabajos en segundo plano: los comandos que requieren la interacción del usuario no deben ejecutarse en segundo plano, porque su máquina será estúpida esperando allí. Sin embargo, ejecutar el trabajo en segundo plano también mostrará los resultados en la pantalla, lo que interferirá con su trabajo. Si un trabajo que se ejecuta en segundo plano produce una gran cantidad de resultados, lo mejor es redirigir su salida a un archivo utilizando el siguiente método:
comando> out.file 2> & 1 &

16, función de descarga

La función fflush () de C estándar admite el almacenamiento intermedio de salida de lavado, sin definición para el almacenamiento intermedio de entrada

Supongo que te gusta

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