Función pthread_create en lenguaje C

Función pthread_create en lenguaje C

Conceptualmente, un programa es un solo hilo que ejecuta varias tareas en serie, una tras otra.
El lenguaje C nos permite escribir programas multiproceso utilizando la biblioteca PTHread del estándar POSIX.
Un programa multiproceso es un hilo o tarea que se ejecuta en paralelo y simultáneamente con el programa principal y otros hilos abiertos por el mismo programa en alguna parte.

En esto Pista de Linux Artículo, aprenderá cómo crear un hilo de un programa principal utilizando el pthread_create () función de la biblioteca pthread.

Esto explica el funcionamiento teórico de esta función, su sintaxis, argumentos de entrada y salida, y el tipo de datos aceptado en cada caso.
Luego aplicaremos lo que hemos aprendido en ejemplos prácticos, incluidos fragmentos e imágenes de código, en los que creamos y sincronizamos los hilos de la función principal.

Sintaxis de la función pthread_create () en lenguaje C

int pthread_create (pthread_t *restringir el hilo,
const pthread_attr_t *restringir attr,
void *( *start_routine) (void *),
vacío *restringir arg);

Descripción de la función pthread_create () en lenguaje C

El pthread_create () la función crea un hilo y lo ejecuta, en paralelo y simultáneamente con el programa que lo creó. Esta función ejecuta la rutina especificada por su puntero en la entrada start_routine pasándolo el argumento de entrada argumento.

A continuación, veamos los argumentos de entrada y salida de pthread_create () en detalle, así como una descripción del trabajo, cada uno de estos argumentos se realiza dentro de la función.

hilo: Este es un argumento de salida que devuelve el identificador del hilo creado. Este identificador se utiliza para hacer referencia a Ciertas funciones de gestión de hilos como pthread_join () o pthread_cancel ().

atencia: Esta entrada es el puntero a una estructura de tipo pthread_attr_t cuyos miembros especifican los atributos del nuevo hilo. Cuando este argumento se envía a NULL, los atributos del nuevo hilo se toman con sus parámetros predeterminados.

start_routine: Este es el puntero a la función que será ejecutada por el nuevo hilo.

argumento: Este es el puntero al argumento de que la función principal pasa al nuevo hilo.

Si el hilo se crea con éxito, pthread_create () Devuelve 0 como resultado. Si se produce un error, devuelve -1 y almacena en la variable global errar el valor numérico específico que representa ese error.

El pthread_create () la función se define en el PTHREAD.h encabezado. Para usarlo, los siguientes encabezados deben incluirse en el ".Archivo C ”, como se muestra a continuación:

#incluir
#incluir

Errores de compilación en programas con hilos

Al compilar programas GCC que usan subprocesos, la compilación puede fallar si no se hace correctamente desde la línea de comando.
El mensaje de error más común emitido por el compilador establece que una de las funciones de hilo a las que nos referimos en el código no está definida.

Estos errores a menudo dan como resultado un tiempo valioso para verificar los encabezados que hemos insertado en el código, su integridad y los directorios asociados con el compilador, ya que todo indica que el problema está ahí está ahí.
Aunque las funciones que causan el error se definen en el "PTHREAD.H "encabezado e incluido en el código, el compilador no reconoce estas funciones a menos que la biblioteca PTHREAD se llame desde la línea de comando durante la compilación.

A continuación, puede ver en Green la forma correcta de llamar a la biblioteca PTHread desde la consola de comando durante la compilación de programas con hilos:

~ $ gcc -pthread ruta/nombre de archivo.c -o out_name

Como se muestra en la figura a continuación, el error desaparece cuando se llama a la biblioteca PTHREAD durante la compilación.

Cómo crear y ejecutar un hilo con la función pthread_create () en el idioma C

En este ejemplo, explicaremos cómo pthread_create () obras. Para hacer esto, crearemos una función principal y a partir de ahí abriremos un hilo que ejecuta el Thread_function () función en paralelo con el función principal.

El código para este ejemplo consta de dos secciones, el principal() función y el Thread_function () función, que es el hilo.
A continuación, explicaremos cada una de las dos funciones por separado y luego las juntaremos para compilar y ejecutar el código.

Thread_function (): Esta función consiste en un para bucle con 5 ciclos, en cada uno de los cuales el mensaje "desde el hilo" se muestra en la consola de comando y después de un retraso de 3 segundos, el ciclo se repite nuevamente. El mensaje de esta función está entrelazado con el de principal() función para que pueda ver en tiempo real lo que cada uno de los procesos está haciendo simultáneamente.

A continuación, NCL vemos el nclusi el Thread_function () función y la definición de su prototipo:

void* thread_function (void* n);
void* thread_function (void* n)

para (int a = 0; a!= 5; a ++)

printf ("Desde el hilo \ n");
dormir (3);

printf ("Nclus Thread \ n");
pthread_exit (n);

función principal: En este ejemplo, el principal() la función es nclusióne para definir las variables y crear el hilo.

El primer paso para crear un hilo es definir una variable de tipo pthread_t que NCL sirve como identificador del hilo. En este ejemplo, NCL llamamos a esta variable Thread_1.

A nclus el hilo, llamamos al pthread_create () función y pasar el identificador de hilo Thread_1 como el primer argumento.
Los atributos del hilo a crear están preestablecidos en este caso, por lo que el segundo argumento de entrada es nulo.
Como el tercer argumento, pasamos el puntero a la función que se ejecutará en el nuevo hilo, en este caso Thread_function ().
Como no necesitamos pasar ningún argumento al nuevo hilo en este ejemplo, el puntero de arg ncl también será nulo.

Después de llamar pthread_create (), El nuevo hilo comienza la ejecución y la función principal() entra en un para bucle de 5 ciclos, cada uno de los cuales imprime el mensaje "desde la función principal" anidada con el mensaje "del hilo" de la función Thread_function (). Después de cada mensaje, se inserta un retraso de 3 segundos en los bucles para ambas funciones antes de comenzar un nuevo ciclo.

A continuación puede ver el Nclusi la función principal(), la nclusión de los encabezados necesarios y la declaración del prototipo de la función thread_function ()::

#incluir
#incluir
#incluir
#incluir
void* thread_function (void* data);
int main ()

pthread_t thread_1;
printf ("Creando el hilo ... \ n");
pthread_create (& thread_1, null, thread_function, null);
para (int a = 0; a!= 5; a ++)

printf ("de la función principal \ n");
dormir (3);

dormir (3);
regresar 0;

A continuación, vemos el código completo para este ejemplo. Copie y pegue este fragmento en un archivo con un ".extensión C ”. Compilar el código y ejecutarlo para ver cómo principal() función y el nuevo hilo realiza sus tareas simultáneamente.

#incluir
#incluir
#incluir
#incluir
void* thread_function (void* data);
int main ()

pthread_t thread_1;
printf ("Creando el hilo ... \ n");
pthread_create (& thread_1, null, thread_function, null);
para (int a = 0; a!= 5; a ++)

printf ("de la función principal \ n");
dormir (3);

regresar 0;

/****************************************************** ****************/
void* thread_function (void* n)

para (int a = 0; a!= 5; a ++)

printf ("desde el hilo \ n");
dormir (3);

printf ("End del hilo \ n");
pthread_exit (n);

La imagen que vemos a continuación muestra la tarea ejecutada por el hilo que creamos con el pthread_create () función en paralelo con la tarea del principal() función, y los mensajes cada uno de ellos envía a la consola de comando:

Sincronización de hilos en el lenguaje C

En el código del ejemplo anterior, el tiempo de ejecución del hilo es más corto que el del principal() función y, por lo tanto, ambos hacen su trabajo correctamente. Esto se debe al retraso de 3 segundos que ocurre cuando el principal() la función sale del bucle.
Sin embargo, si los tiempos de ejecución de un hilo son más largos que los de la principal() función y está completamente ejecutado, el programa termina y todos los hilos que se crearon y todavía están realizando una tarea se cierran automáticamente.

Veamos qué sucede en el código del ejemplo anterior si establecemos un retraso de 1 segundo por ciclo en el bucle for the principal() función y uno de 3 segundos en el bucle de hilo.

Como se muestra en la imagen, el principal() la función completó los 5 ciclos de su para bucle, mientras que el hilo solo pudo ejecutar 3 ciclos antes de que se cerrara el programa.

Cerrar un hilo sin ejecutarlo puede conducir a problemas críticos en ciertos casos, ya que podría almacenar datos generados por el usuario, escribir en un sistema de archivos o dispositivo de almacenamiento, o realizar alguna otra tarea en el momento de la terminación.
Para evitar estos problemas, es importante desarrollar un mecanismo para "esperar" a que el hilo complete la ejecución antes de cerrar el programa o ejecutar una tarea. El pthread_join () La función detiene la función que creó el hilo hasta que ese hilo finaliza su ejecución.

El pthread_join () la función toma dos argumentos de entrada. El primero es el identificador de hilo devuelto por el pthread_create () función cuando se crea el hilo y el segundo argumento es el puntero a una variable que devuelve el estado de salida del hilo.

A continuación, usamos el código del ejemplo anterior, pero reemplazamos el para bucle del principal() función con el pthread_join () función, como se muestra a continuación:

#incluir
#incluir
#incluir
#incluir
void* thread_function (void* data);
int main ()

pthread_t thread_1;
printf ("Creando el hilo ... \ n");
pthread_create (& thread_1, null, thread_function, null);
pthread_join (Thread_1, nulo);
regresar 0;

/****************************************************** ****************/
void* thread_function (void* n)

para (int a = 0; a!= 5; a ++)

printf ("desde el hilo \ n");
dormir (3);

printf ("End del hilo \ n");
pthread_exit (n);

En este caso, el principal() la función simplemente creará el hilo y esperará a que finalice su tarea, luego cierre el programa.

Posibles errores que puede generar la función pthread_create () y cómo reconocerlos

El pthread_create () La función puede generar varios errores, desde la configuración de atributos no válidos hasta los recursos del sistema insuficientes para el nuevo hilo.
Cuando una función genera un error, se almacena un código de identificación de error numérico en la variable global errar. Esta variable y las definiciones numéricas para cada error se definen en el "Errno.encabezado.
A continuación se muestra una descripción de cada error que puede ocurrir al llamar a la pthread_create () función y su representación numérica definida en "Errno.H ".

Águila: No hay recursos disponibles para crear otro hilo. La representación numérica de este error es 35.

Einval: La configuración de atributos en ATTT no es válida. La representación numérica de este error es 22.

Entera: Operacion no permitida. Este error ocurre cuando no tiene permisos suficientes para establecer los parámetros de atributo en ATTR. La representación numérica de este error es 1.

Conclusión

En esto Pista de Linux Artículo, le mostramos cómo usar el pthread_create () función para crear programas multitarea con hilos que se ejecutan en paralelo con la función principal.

También le dijimos cómo compilar programas que usan hilos correctamente desde la línea de comando.
También hemos incluido una sección especial que explica la importancia de tener en cuenta los tiempos de ejecución de los hilos creados y le hemos enseñado cómo sincronizar los hilos con la función principal para lograr su ejecución correcta.