Entran expertos sobre el problema de establecer subprocesos múltiples en Windows usando lenguaje C (implementado en VC6.0)
Los ejemplos suelen ser lo más interesante de las cosas. Si siempre aprendes teorías básicas y no lo haces, no sentirás ninguna sensación de logro, jaja.
Pongamos primero un ejemplo. Creamos dos hilos para incrementar un número.
Quizás este ejemplo no tenga valor práctico, pero con un ligero cambio, podemos usarlo en otros lugares.
Aquí está nuestro código:
/*thread_example.c:c programación de subprocesos múltiples en Linux
*autor: falcon
* Correo electrónico: tunzhj03@st.lzu.edu.cn
*/
#include lt;pthread.hgt;
#include lt;stdio. hgt;
#include lt;sys/time.hgt;
#include lt;string.hgt;
#define MAX 10
pthread_t hilo[2];
pthread_mutex_t mut;
int number="0", i;
void *thread1()
{
printf ("hilo1: soy el hilo 1\n");
for (i = 0; i lt; MAX; i)
{
printf("thread1: número = d\n", número);
pthread_mutex_lock(amp; mut);
número; /p>
pthread_mutex_unlock(amp; mut);
sleep(2);
}
printf("thread1: La función principal está esperando ¿Completé la tarea?\n");
pthread_exit(NULL);
}
void *thread2()
{
printf("thread2: Soy el hilo 2\n");
for (i = 0; i lt; MAX; i)
{
printf("thread2: número = d\n", número);
pthread_mutex_lock(amp; mut);
número;
pthread_mutex_unlock(amp;mut);
sleep(3);
}
printf("thread2: ¿Está la función principal esperando a que completar la tarea? \n");
pthread_exit(NULL);
}
void thread_create(void)
{
< pinta>int temp;p>
memset(amp; thread, 0, sizeof(thread)); //comentario1
/*Crear hilo*/
if((temp = pthread_create(amp ;thread[0], NULL, thread1, NULL)) != 0) //comment2
printf("¡Error en la creación del hilo 1!\n");
else p>
printf("Se creó el subproceso 1\n");
if((temp = pthread_create(amp; subproceso[1], NULL, subproceso2, NULL)) != 0) / /comment3
printf("Error en la creación del hilo 2");
else
printf("Se creó el hilo 2\n");
}
void thread_wait(void)
{
/*Espera a que termine el hilo*/
if( thread[0 ] !=0) { //comment4
pthread_join(thread[0], NULL
printf("El hilo 1 ha finalizado\n"); p>
}
if(thread[1] !=0) { //comment5
pthread_join(thread[1], NULL);
printf( "El hilo 2 ha finalizado\n");
}
}
int main()
{ p>
/*Inicializa el bloqueo mutex con atributos predeterminados*/
pthread_mutex_init(amp; mut, NULL);
printf("Soy la función principal, soy creando un hilo, Jaja\n");
thread_create();
printf("Soy la función principal, estoy esperando que el hilo complete la tarea, jaja\ n");
thread_wait();
devuelve 0;
}
Compilemos y ejecutemos primero
Cita:
falcon@falcon:~/program/c/code/ftp$ gcc -lpthread -o thread_example thread_example.c
falcon@falcon:~/program/ c/code/ftp $ ./thread_example
Yo soy el maestro
Función, estoy creando un hilo, jaja
Se crea el hilo 1
Se crea el hilo 2
Soy la función principal, estoy esperando el hilo para completar la tarea Ah, jaja
hilo1: soy el hilo 1
hilo1: número = 0
hilo2: soy el hilo 2
hilo2: número = 1
hilo1: número = 2
hilo2: número = 3
hilo1: número = 4
hilo2: número = 5
hilo1: número = 6
hilo1: número = 7
hilo2: número = 8
hilo1: número = 9
hilo2: número = 10
hilo1: ¿Está la función principal esperando a que complete la tarea?
El hilo 1 ha finalizado
hilo 2: ¿Está la función principal esperando a que complete la tarea?
El hilo 2 ha finalizado
Los comentarios en el código de ejemplo deberían ser más claros. Ahora citaré varias funciones y variables mencionadas anteriormente en Internet.
Cita:
Operaciones relacionadas con subprocesos
Un pthread_t
pthread_t está en el archivo de encabezado /usr/include/bits/pthreadtypes .h Definición:
typedef unsigned long int pthread_t
Es el identificador de un hilo.
Dos pthread_create
La función pthread_create se utiliza para crear un hilo. Su prototipo es:
extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *). __attr ,
void *(*__start_routine) (void *), void *__arg));
El primer parámetro es un puntero al identificador del hilo y se utiliza el segundo parámetro. Establecer las propiedades del hilo. El tercer parámetro es la dirección inicial de la función en ejecución del hilo y el último parámetro es el parámetro de la función en ejecución. Aquí, nuestro hilo de función no requiere parámetros, por lo que el último parámetro se establece en un puntero nulo. También configuramos el segundo parámetro en un puntero nulo, que generará un hilo con atributos predeterminados. Explicaremos la configuración y modificación de los atributos del hilo en la siguiente sección. Cuando el subproceso se crea correctamente, la función devuelve 0. Si no es 0, la creación del subproceso falla. Los códigos de retorno de error comunes son EAGAIN y EINVAL. Lo primero significa que el sistema restringe la creación de nuevos subprocesos, por ejemplo, el número de subprocesos es demasiado grande; lo segundo significa que el valor del atributo del subproceso representado por el segundo parámetro es ilegal. Una vez que el subproceso se crea correctamente, el subproceso recién creado ejecuta la función determinada por el parámetro tres y el parámetro cuatro, y el subproceso original continúa ejecutando la siguiente línea de código.
Tres pthread_join pthread_exit
La función pthread_join se utiliza para esperar el final de un hilo.
El prototipo de la función es:
extern int pthread_join __P ((pthread_t __th, void **__thread_return));
El primer parámetro es el identificador del hilo que se esperará y el segundo. parámetro Es un puntero definido por el usuario que se puede utilizar para almacenar el valor de retorno del hilo en espera. Esta función es una función de bloqueo de subprocesos. La función que la llama esperará hasta que finalice el subproceso en espera. Cuando la función regresa, se recuperan los recursos del subproceso en espera. Hay dos formas de finalizar un hilo. Una es como nuestro ejemplo anterior, cuando la función finaliza, el hilo que la llamó también finaliza; la otra forma es a través de la función pthread_exit. Su prototipo de función es:
extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));
El único parámetro es el código de retorno de la función, siempre y cuando como pthread_join El segundo parámetro de thread_return no es NULL, este valor se pasará a thread_return. Lo último que hay que tener en cuenta es que varios subprocesos no pueden esperar a un subproceso; de lo contrario, el primer subproceso que recibe la señal regresa con éxito y los subprocesos restantes que llaman a pthread_join devuelven el código de error ESRCH.
En esta sección, escribimos el hilo más simple y dominamos las tres funciones más utilizadas: pthread_create, pthread_join y pthread_exit. A continuación, echemos un vistazo a algunas propiedades comunes de los subprocesos y cómo configurarlas.
Relacionado con el bloqueo Mutex
El bloqueo Mutex se utiliza para garantizar que solo un hilo esté ejecutando un fragmento de código dentro de un período de tiempo.
Un pthread_mutex_init
La función pthread_mutex_init se utiliza para generar un bloqueo mutex. El parámetro NULL indica que se utilizan los atributos predeterminados. Si necesita declarar un mutex para un atributo específico, debe llamar a la función pthread_mutexattr_init. La función pthread_mutexattr_setpshared y la función pthread_mutexattr_settype se utilizan para configurar los atributos de bloqueo mutex. La función anterior establece el atributo pshared, que tiene dos valores, PTHREAD_PROCESS_PRIVATE y PTHREAD_PROCESS_SHARED. El primero se utiliza para sincronizar subprocesos en diferentes procesos y el segundo se utiliza para sincronizar diferentes subprocesos en este proceso. En el ejemplo anterior, utilizamos la propiedad predeterminada PTHREAD_PROCESS_ PRIVATE. Este último se utiliza para configurar el tipo de bloqueo mutex. Los tipos opcionales son PTHREAD_MUTEX_NORMAL, PTHREAD_MUTEX_ERRORCHECK, PTHREAD_MUTEX_RECURSIVE y PTHREAD _MUTEX_DEFAULT. Definen respectivamente diferentes mecanismos de listado y desbloqueo. En circunstancias normales, se selecciona el último atributo predeterminado.
Dos pthread_mutex_lock pthread_mutex_unlock pthread_delay_np
La declaración pthread_mutex_lock comienza a bloquearse con un bloqueo mutex. El código posterior se bloquea hasta que se llama a pthread_mutex_unlock, es decir, solo puede ser llamado por un hilo. al mismo tiempo. Cuando un hilo se ejecuta en pthread_mutex_lock, si otro hilo usa el bloqueo en este momento, el hilo se bloquea, es decir, el programa esperará hasta que otro hilo libere el bloqueo mutex.
Nota:
1 Cabe señalar que las dos suspensiones anteriores no son solo para fines de demostración, sino también para permitir que el hilo duerma durante un período de tiempo, permitiendo que el hilo para liberar el bloqueo mutex y esperar. Otro hilo usa este bloqueo. Este problema se explica en la Referencia 1 a continuación. Sin embargo, parece que no hay una función pthread_delay_np en Linux (lo probé y me preguntaron que no había ninguna referencia a la función definida), así que usé la suspensión. Sin embargo, en la Referencia 2 se proporciona otro método, que parece. ser reemplazado por pthread_cond_timedwait, lo que proporciona una manera de lograrlo.
2 Por favor, preste atención a los comentarios 1-5 del interior, ahí es donde el problema me llevó varias horas descubrirlo.
Si no hay comentario1, comentario4 y comentario5, se producirá un error de segmentación durante pthread_join. Además, los comentarios2 y 3 anteriores son la causa principal, así que asegúrese de escribir el código completo. Debido a que es posible que el subproceso anterior no se haya creado correctamente, es imposible esperar a que finalice y se produce un error de segmentación (se accede a un área de memoria desconocida) cuando se utiliza pthread_join. Además, cuando utilices memset, debes incluir el archivo de encabezado string.h