GNU/Linux >> Tutoriales Linux >  >> Linux

Cómo terminar un subproceso en un programa C (ejemplo de pthread_exit)

En la parte II (Creación e identificación de subprocesos) de la serie Linux Thread, discutimos sobre las ID de subprocesos, cómo comparar dos ID de subprocesos y cómo crear un subproceso.

En este artículo nos centraremos principalmente en cómo se termina un subproceso.

Serie de subprocesos de Linux:parte 1, parte 2, parte 3 (este artículo).

Programa de ejemplo de hilo C

Si tomamos el mismo ejemplo que se discutió en la parte II de esta serie:

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>

pthread_t tid[2];

void* doSomeThing(void *arg)
{
    unsigned long i = 0;
    pthread_t id = pthread_self();

    if(pthread_equal(id,tid[0]))
    {
        printf("\n First thread processing\n");
    }
    else
    {
        printf("\n Second thread processing\n");
    }

    for(i=0; i<(0xFFFFFFFF);i++);

    return NULL;
}

int main(void)
{
    int i = 0;
    int err;

    while(i < 2)
    {
        err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
        if (err != 0)
            printf("\ncan't create thread :[%s]", strerror(err));
        else
            printf("\n Thread created successfully\n");

        i++;
    }

    sleep(5);
    return 0;
}

¿Observó que se usaba la función 'dormir ()'? ¿Recibió una pregunta acerca de por qué se está utilizando sleep()? Bueno, si lo hizo, entonces está en el lugar correcto para obtener la respuesta y si no lo hizo, entonces también será una buena lectura.

Si elimino la función sleep() del código anterior y luego intento compilarla y ejecutarla, veo el siguiente resultado:

$ ./threads
Thread created successfully
First thread processing
Thread created successfully

Pero si lo ejecuto con sleep() habilitado, veo el resultado como  :

$ ./threads
Thread created successfully
First thread processing
Thread created successfully
Second thread processing

Entonces vemos que falta el registro 'Procesamiento del segundo subproceso' en caso de que eliminemos la función dormir().

¿Entonces, por qué pasa ésto? Bueno, esto sucedió porque justo antes de programar el segundo subproceso, el subproceso principal (a partir del cual se crearon los dos subprocesos) completó su ejecución. Esto significa que el subproceso predeterminado en el que se ejecutaba la función main() se completó y, por lo tanto, el proceso finalizó cuando se devolvió main().

Terminación de subprocesos

Como ya se discutió anteriormente, cada programa comienza con al menos un hilo, que es el hilo en el que se ejecuta la función main(). Entonces, la vida útil máxima de cada subproceso que se ejecuta en el programa es la del subproceso principal. Entonces, si queremos que el subproceso principal espere hasta que todos los demás subprocesos terminen, entonces hay una función pthread_join().

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);

La función anterior se asegura de que su subproceso principal no finalice hasta que finalice. Esta función se llama desde el subproceso principal y el primer argumento es el ID del subproceso en el que esperar y el segundo argumento es el valor de retorno del subproceso en el que queremos que espere el subproceso principal. Si no estamos interesados ​​en el valor devuelto, podemos configurar este puntero como NULL.

Si clasificamos en un nivel más amplio, vemos que un hilo puede terminar de tres maneras:

  1. Si el subproceso regresa de su rutina de inicio.
  2. Si es cancelado por algún otro subproceso. La función utilizada aquí es pthread_cancel().
  3. Si llama a la función pthread_exit() desde dentro de sí mismo.

El foco aquí estaría en pthread_exit(). Su prototipo es el siguiente:

#include <pthread.h>
void pthread_exit(void *rval_ptr);

Entonces vemos que esta función acepta solo un argumento, que es el retorno del hilo que llama a esta función. El subproceso principal accede a este valor de retorno que está esperando que finalice este subproceso. Se puede acceder al valor de retorno del subproceso terminado por la función pthread_exit() en el segundo argumento de pthread_join que se acaba de explicar anteriormente.

Ejemplo de terminación de hilo C

Tomemos un ejemplo en el que usamos las funciones discutidas anteriormente:

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>

pthread_t tid[2];
int ret1,ret2;

void* doSomeThing(void *arg)
{
    unsigned long i = 0;
    pthread_t id = pthread_self();

    for(i=0; i<(0xFFFFFFFF);i++);

    if(pthread_equal(id,tid[0]))
    {
        printf("\n First thread processing done\n");
        ret1  = 100;
        pthread_exit(&ret1);
    }
    else
    {
        printf("\n Second thread processing done\n");
        ret2  = 200;
        pthread_exit(&ret2);
    }

    return NULL;
}

int main(void)
{
    int i = 0;  
    int err;
    int *ptr[2];

    while(i < 2)
    {
        err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
        if (err != 0)
            printf("\ncan't create thread :[%s]", strerror(err));
        else
            printf("\n Thread created successfully\n");

        i++;
    }

    pthread_join(tid[0], (void**)&(ptr[0]));
    pthread_join(tid[1], (void**)&(ptr[1]));

    printf("\n return value from first thread is [%d]\n", *ptr[0]);
    printf("\n return value from second thread is [%d]\n", *ptr[1]);

    return 0;
}

En el código de arriba:

  • Creamos dos hilos usando pthread_create()
  • La función de inicio para ambos subprocesos es la misma, es decir, doSomeThing()
  • Los subprocesos salen de la función de inicio utilizando la función pthread_exit() con un valor de retorno.
  • En la función principal después de que se crean los subprocesos, se llama a las funciones pthread_join() para esperar a que se completen los dos subprocesos.
  • Una vez que ambos subprocesos están completos, se accede a su valor de retorno mediante el segundo argumento en la llamada pthread_join().

La salida del código anterior aparece como  :

$ ./threads
Thread created successfully
Thread created successfully
First thread processing done
Second thread processing done
return value from first thread is [100]
return value from second thread is [200]

Entonces vemos que ambos subprocesos se ejecutan completamente y se accede a su valor de retorno en la función principal.


Linux
  1. ¿Cómo redirigir la salida de un programa a un archivo zip?

  2. Ejemplo de Pascal Hello World:cómo escribir, compilar y ejecutar el programa Pascal en el sistema operativo Unix

  3. Ejemplo de Smalltalk Hello World:cómo escribir y ejecutar el programa Smalltalk en el sistema operativo Linux

  4. Ejemplo de Fortran Hello World:cómo escribir y ejecutar el programa Fortran en el sistema operativo Linux

  5. Ejemplo de XQuery Hello World:cómo escribir y ejecutar el programa XQuery en el sistema operativo Linux

Cómo:Introducción a la programación - Control de flujo

Maneras brillantes de cómo ejecutar un programa en Linux

Cómo escribir y ejecutar un programa C en Linux

Cómo usar execl (ejemplo incluido)

¿Cómo nombrar un hilo en Linux?

¿Cómo obtener la identificación del subproceso de un pthread en el programa linux c?