Resumen de los puntos de conocimiento común del multiproceso de Linux

Notas de funciones de uso común de subprocesos múltiples de Linux

Uso de la función de hilo

[Tipo de TID: pthread_t]

  • pthread_t es un tipo de datos estructurados, por lo que las implementaciones de sistemas operativos portátiles no pueden tratarlo como un número entero
  • Linux 3.2.0 usa un entero largo sin signo para representar el tipo de datos pthread_t

[Comparación del hilo TID: pthread_equal]

#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);
// 若相等,返回非0数值;否则,返回0

[Obtenga su propio ID de hilo: pthread_self]

  • Al imprimir con printf, use "% lu" para imprimir el valor del tipo pthread_t
#include <pthread.h>
pthread_t pthread_self(void); 
// 返回调用线程的线程ID

[Gettid () para obtener el tid del hilo]

  • La función gettid () puede obtener el tid del hilo, pero glibc no implementa esta función, solo se puede obtener a través de la llamada al sistema Linux syscall (<sys / syscall.h>)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h> 

void *hello()
{
	printf("child,the tid=%lu,pid=%ld\n",pthread_self(),syscall(SYS_gettid));
}

int main(int argc,char *agrv[])
{
	pthread_t thread_id;
	pthread_create(&thread_id,NULL,(void *)*hello,NULL);
	
	printf("parent,the tid=%lu,pid=%ld\n",pthread_self(),syscall(SYS_gettid));
	pthread_join(thread_id,NULL);
}
  • Nota:
    • Utilice el método anterior para verificar: el PID del hilo principal es el mismo que el PID del proceso
    • Cuando no se crea ningún hilo en el proceso, el proceso principal es equivalente a un hilo principal, porque el ID del proceso y el hilo son el mismo

[Función de creación de hilo: pthread_create]

#include <pthread.h>
int pthread_create(
	pthread_t              *restrict tidp,        //当pthread_create成功返回时,新创建的线程ID会被设置到tidp所指向的内存单元中
	const pthread_attr_t   *restrict attr,        //atrr参数用于指定线程创建时的初始化属性。值为NULL时,创建一个具有默认属性的线程。
	void                   *(*start_rtn)(void *), //新创建的线程从start_rtn函数的地址开始运行。该函数只有一个无类型指针参数arg,返回值为void*类型
	void                   *restrict  arg         //如果需要向start_rtn函数传递的参数有一个以上,需要把这些参数放到一个结构中,传递该结构的地址
	);
  • valor de retorno:
    • Éxito: devuelve 0
    • Error: devuelve el número de error sin configurar errno
  • Caso 1
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
pthread_t ntid;
 
void printids(const char *s){
    pid_t pid;
    pthread_t tid;
    pid = getpid();
    tid = pthread_self();
    printf("%s pid %lu tid %lu (0x%lx)\n", s, (unsigned long)pid,(unsigned long)tid, 
    (unsigned long)tid);
}
 
void *thr_fn(void *arg){
    printids("new thread: ");
    return((void *)0);
}
 
int main(void)
{
    int err;
    //create thread
    err = pthread_create(&ntid, NULL, thr_fn, NULL);
    if (err != 0)
        printf("can’t create thread\n");
    printids("main thread:");
    sleep(1);
    exit(0);
}
  • Caso 2
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h> 

struct message
{
	int i;
	int j;
};

void *hello(struct message *str)
{
	printf("child,the tid=%lu,pid=%ld\n",pthread_self(),syscall(SYS_gettid));
	printf("the arg.i is %d,arg.j is %d\n",str->i,str->j);
}
 
int main(int argc,char *agrv[])
{
	struct message test;
	pthread_t thread_id;
	test.i=10;
	test.j=20;
	pthread_create(&thread_id, NULL,(void *)*hello,&test);
	printf("parent,the tid=%lu,pid=%ld\n",pthread_self(),syscall(SYS_gettid));
	pthread_join(thread_id,NULL);
}

[Estructura de atributo del hilo: pthread_attr_t]

  • El contenido de esta estructura contiene el valor del atributo del hilo, y el parámetro 2 de pthread_create usa esta estructura para establecer el valor del atributo inicial para el hilo.

[Creación y destrucción de la estructura de atributos del hilo]

int pthread_attr_init(pthread_attr_t *attr);
  • Función: se utiliza para inicializar el valor del atributo del hilo.
  • Nota: Después de llamar a esta función, los atributos de la estructura de atributos son valores predeterminados del sistema. Si desea establecer otros atributos, debe llamar a diferentes funciones para establecerlos.
int pthread_attr_destroy(pthread_attr_t *attr);
  • Función: se utiliza para desinicializar (destruir) atributos. Si los atributos del hilo inicializados por la función pthread_attr_init se asignan dinámicamente, esta función liberará el espacio de memoria de los atributos del hilo
  • La función pthread_attr_destory inicializa el objeto de atributo con un valor no válido, por lo que después de desinicializar el atributo con esta función, el atributo no puede ser utilizado por la función pthread_create.

[Método de terminación del hilo]

  • Los siguientes tres métodos son terminar el hilo y detener su flujo de control sin terminar todo el proceso normalmente:
    • ① El hilo simplemente puede regresar de la rutina de inicio, y el valor de retorno es el código de salida del hilo
    • ② El hilo puede ser cancelado por otros hilos en el mismo proceso ( pthread_cancel )
    • ③ Thread llama pthread_exit

[Función de salida del hilo: pthread_exit]

#include <pthread.h>
void pthread_exit(void *rval_ptr);
  • Función: el hilo llama a esta función para terminar.
  • Parámetro: rval_ptr es un puntero sin tipo, y el contenido se puede configurar en este puntero para salir del proceso (generalmente para configurar el código de terminación).
    • Otros subprocesos en el proceso también pueden acceder a este puntero llamando a la función pthread_join
#include<pthread.h>
#include<stdlib.h>
#include<stdio.h>
void * thr_fn1(void *arg){
    printf("thread 1 returning\n");
    return((void *)1);
}
void *thr_fn2(void *arg){
    printf("thread 2 exiting\n");
    pthread_exit((void *)2);
}
int main(void)
{
    int err;
    pthread_t tid1, tid2;
    void *tret;
 
    err = pthread_create(&tid1, NULL, thr_fn1, NULL);//创建线程1
    if (err != 0)
        printf("can’t create thread 1\n");
    err = pthread_create(&tid2, NULL, thr_fn2, NULL);//创建线程2
    if (err != 0)
        printf("can’t create thread 2\n");
 
    err = pthread_join(tid1, &tret);//等待线程1
    if (err != 0)
        printf("can’t join with thread 1\n");
    printf("thread 1 exit code %ld\n", (long)tret);
    
    err = pthread_join(tid2, &tret);//等待线程2
    if (err != 0)
        printf("can’t join with thread 2\n");
    printf("thread 2 exit code %ld\n", (long)tret);
   
     exit(0);
}

[Función de espera de hilo pthread_join]

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
  • Valor de retorno: devuelve 0 en caso de éxito; devuelve el número de error en caso de error
  • Función: se usa para esperar el final del hilo especificado por el parámetro 1
  • Esta función se bloqueará hasta que el hilo especificado llame a pthread_exit, regrese del hilo inicial o se cancele, luego esta función regresa
  • parámetro:
    • Parámetro 1: especifique el ID del hilo en espera
    • Parámetro 2:
      • Complete NULL: obtenga la información de terminación del hilo en espera. Si no está interesado en la información de terminación del hilo, puede establecerlo en NULL.
      • No vacío: si el hilo simplemente regresa de su rutina de retorno, rval_ptr contiene el código de retorno.
      • Si se cancela el hilo, la unidad de memoria especificada por rval_ptr se establece en PTHREAD_CANCELED
  • La relación entre el uso de la función thread_join y la separación de hilos:
    • Llame a pthread_join para esperar un hilo. Una vez que finaliza el hilo en espera, se colocará en un estado separado, de modo que los recursos utilizados por el hilo se puedan restaurar
    • Si se llama a pthread_join para esperar un hilo, si el hilo ya está en un estado separado (por ejemplo, se llama a la función pthread_detach), la llamada pthread_join fallará y devolverá EINVAL, aunque este comportamiento está relacionado con la implementación específica

[Función de cancelación de hilo: pthread_cancel]

#include <pthread.h>
int pthread_cancel(pthread_t tid);
  • Valor de retorno: devuelve 0 si tiene éxito; de lo contrario, devuelve el número de error
  • Función: el hilo puede solicitar la cancelación de otros hilos en el mismo proceso a través de pthread_cancel
  • pthread_cancel no espera a que termine el hilo, solo realiza una solicitud
  • parámetro:
    • ID del hilo que debe cancelarse
  • Precauciones:
    • Por defecto, la función pthread_cancel hará que el hilo identificado por tid se comporte como si llamara a la función pthread_exit con el parámetro PTHREAD_CANCELED, pero el hilo cancelado puede optar por ignorar la cancelación o controlar cómo se cancela.

[Punto de cancelación del hilo]

  • Concepto: El sistema personaliza algunos puntos de cancelación de hilo. Cuando un hilo recibe una solicitud de cancelación de otro hilo, si no se ha ejecutado hasta el punto de cancelación, el hilo continuará ejecutándose hasta que llegue a un cierto punto de cancelación, el hilo se cancela realmente. La tecnología del punto de cancelación del hilo también se llama "aplazamiento". cancelar "
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
 
void *thread_func(void* arg);
 
int main()
{
    pthread_t tid;
    int *thread_exit_code=malloc(sizeof(int));
    if(pthread_create(&tid,NULL,thread_func,NULL)!=0){
        fprintf(stdout,"pthread_create error\n");
        exit(EXIT_FAILURE);
    }
 
    //进程休眠1秒,然后取消子线程
    sleep(1);
    if(pthread_cancel(tid)!=0){
        fprintf(stdout,"pthread_cancel error\n");
        exit(EXIT_FAILURE);
    }
 
    printf("pthread_cancel filaed\n");
    
    //睡眠8秒之后取消线程失败了,因为线程已经退出了
    sleep(8);
    if(pthread_cancel(tid)!=0){
        fprintf(stdout,"pthread_cancel error\n");
        exit(EXIT_FAILURE);
    }
    
    printf("kill thread success\n");
 
    if(pthread_join(tid,(void*)&thread_exit_code)==0){
        printf("pthread_join success,exit_code is %d\n",(int)*thread_exit_code);
    }else{
        fprintf(stdout,"pthread_join error\n");
        exit(EXIT_FAILURE);
    }
 
    exit(0);
}
 
void *thread_func(void* arg)
{
    int exit_code,i;
    
    //进入之后,先设置自己为不可取消状态
    printf("I am thread,now my cancle type is disable\n");
    if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL)!=0){
        fprintf(stdout,"pthread_setcancelstate error\n");
        exit_code=-1;
        pthread_exit(&exit_code);
    }
   
 
    for(i=1;i<=3;i++){
        sleep(1);
        printf("thread running (%d)\n",i);
    }
 
    //休眠3秒之后之后设置线程可以被取消
    printf("I am thread,now my cancle type is enable\n");
    if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL)!=0){
        fprintf(stdout,"pthread_setcancelstate error\n");
        exit_code=-1;
        pthread_exit(&exit_code);
    }
    
    printf("thread sleep....\n");
    sleep(20);
 
    pthread_exit(NULL);
}

[Separación de hilos: pthread_detach]

  • Si el hilo no está separado: el estado de terminación del hilo se mantendrá hasta que otro hilo llame a pthread_join en el hilo para obtener su estado de terminación, el estado de terminación no se liberará
  • Si el subproceso se ha separado: los recursos de almacenamiento subyacentes del subproceso se pueden reclamar inmediatamente cuando el subproceso termina
  • Una vez que se separa el hilo, no podemos usar la función pthread_join para esperar su estado de terminación, porque llamar a pthread_join en el hilo en el estado desconectado producirá un comportamiento indefinido
#include <pthread.h>
int pthread_detach(pthread_t tid);
  • Valor de retorno: devuelve 0 si tiene éxito; de lo contrario, devuelve el número de error 
  • Función: se utiliza para separar hilos
  • Parámetros: el tid del hilo a separar

[Exclusión mutua: pthread_mutex_t]

  • El mutex es esencialmente un bloqueo. El mutex se establece (bloquea) antes de acceder a los recursos compartidos, y el mutex se libera (desbloquea) después de que se completa el acceso
  • Inicialización y liberación de variables mutuamente excluyentes
  • ①Inicialización estática
    • Establezca la variable mutex pthread_mutex_t directamente en la constante PTHREAD_MUTEX_INITIALIZER
    • Las variables mutex inicializadas estáticamente solo pueden tener los atributos mutex predeterminados y no pueden establecer otros atributos mutex
pthread_mutex_t  mutex;
mutex=PTHREAD_MUTEX_INITIALIZER;
//或者
pthread_mutex_t *mutex=(pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
*mutex=PTHREAD_MUTEX_INITIALIZER;
  • ②Inicialización dinámica
    • Las variables mutex inicializadas estáticamente solo pueden tener los atributos mutex predeterminados, podemos inicializar dinámicamente el mutex a través de la función pthread_mutex_init, y puede elegir establecer los atributos mutex durante la inicialización
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
  • Valor de retorno: devuelve 0 si tiene éxito, de lo contrario devuelve un número de error
  • p th read_mutex_init :
    • Función: inicializar el mutex
    • parámetro:
      • Parámetro 1: el mutex debe inicializarse
      • Parámetro 2: las propiedades del mutex durante la inicialización. Si usa los atributos predeterminados, complete NULL aquí
  • pthread_mutex_destroy:
    • Función: Desinicialización del mutex
    • Parámetros: Mutex
    • Observaciones (énfasis): esta función solo desinicializa el mutex y no libera el espacio de memoria. Si el mutex se solicita a través de una función como malloc, entonces debe llamar a la función pthread_mutex_destroy antes de liberar el mutex
pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL); 
/*do something*/
pthread_mutex_destroy(&mutex);

pthread_mutex_t* mutex=(pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutex, NULL);
/*do something*/
pthread_mutex_destroy(mutex);
free(mutex);

[Bloqueo y desbloqueo de mutex]

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);  //对互斥量进行加锁。如果互斥量已经上锁,调用线程将阻塞到互斥量被解锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);  //对互斥量进行解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex); 
  • Intente bloquear el mutex (sin bloqueo). Si el mutex está en un estado desbloqueado, entonces pthead_mutex_trylock bloqueará el mutex; si el bloqueo está en un estado bloqueado, entonces pthead_mutex_trylock devolverá EBUSY por error y no bloqueará

[Caso de recuento de referencias]

struct foo {
    int f_count;
    pthread_mutex_t f_lock;
    int f_id;
};
 
struct foo *foo_alloc(int id)
{
    struct foo *fp;
 
    if ((fp == malloc(sizeof(struct foo))) != NULL) {
        fp->f_count = 1;
        fp->f_id = id;
        if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
            free(fp);
            fp = NULL;
        }
    }
 
    return fp;
}
 
void foo_hold(struct foo *fp)
{
    pthread_mutex_lock(&fp->f_lock);
    fp->f_count++;
    pthread_mutex_unlock(&fp->f_lock);
}
 
void foo_rele(struct foo *fp)
{
    pthread_mutex_lock(&fp->f_lock);
    if (--fp->f_count == 0) {
        pthread_mutex_unlock(&fp->f_lock);
        pthread_mutex_destory(&fp->f_lock);
        free(fp);
    } else {
        pthread_mutex_unlock(&fp->f_lock);
    }
}

[Tiempo de espera mutex: pthread_mutex_timedlock]

#include <pthread.h>
#include <time.h>
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,const struct timespec *restrict tsptr);
  • Valor de retorno: devuelve 0 si tiene éxito; de lo contrario, devuelve un número de error.
  • Función: cuando un hilo intenta adquirir un mutex bloqueado, pthread_mutex_timedlock permite enlazar el tiempo de bloqueo del hilo
  • parámetro:
    • mutex: el mutex para intentar bloquear
    • tsptr: establece el tiempo de espera
  • Características: cuando se alcanza el valor de tiempo de espera, si el mutex no se puede bloquear correctamente, se devolverá el código de error ETIMEDOUT
  • Nota sobre las horas extraordinarias: las horas extraordinarias especifica el tiempo absoluto que está dispuesto a esperar. Este valor de tiempo es un número absoluto en lugar de un número relativo.
  • Por ejemplo, si está dispuesto a esperar 3 minutos, en lugar de convertir 3 minutos en una estructura de especificación de tiempo y pasarlo al parámetro 2, debe agregar 3 minutos a la hora actual y luego convertirlo en una estructura de especificación de tiempo y luego pasarlo al parámetro 2.

[Pthread_mutex_timedlock evita casos de bloqueo permanente]

#include <pthread.h>
 
int main(void)
{
    int err;
    struct timespec tout;
    struct tm *tmp;
    char buf[64];
 
    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_lock(&lock);
    printf("mutex is locked\n");
	
    clock_gettime(CLOCK_REALTIME, &tout);
	
    tmp = localtime(&tout.tv_sec);
    strftime(buf, sizeof(buf), "%r", tmp);
    printf("current time is %s\n", buf);
	
    tout.tv_sec += 10; /* 10 seconds from now */
    
    /* caution: this could lead to deadlock */
    err = pthread_mutex_timedlock(&lock, &tout);
	
    clock_gettime(CLOCK_REALTIME, &tout);
    tmp = localtime(&tout.tv_sec);
    strftime(buf, sizeof(buf), "%r", tmp);
    printf("the time is now %s\n", buf);
	
    if (err == 0)
        printf("mutex locked again!\n");
    else
        printf("can’t lock mutex again: %s\n", strerror(err));
    exit(0);
}
  • Este programa bloquea deliberadamente su mutex existente para demostrar cómo funciona pthread_mutex_timedlock. No se recomienda utilizar este método en la práctica, ya que conducirá a un punto muerto.
  • Nota: El tiempo de bloqueo puede ser diferente. Hay muchas razones por diferentes razones: la hora de inicio puede estar en la mitad de un segundo determinado, la precisión del reloj del sistema puede no ser lo suficientemente precisa para admitir el valor de tiempo de espera especificado por nosotros, o el programa continúa Antes de ejecutarse, la demora en la programación puede aumentar el valor de tiempo

[Variable de condición: pthread_cond_t]

  • Las variables de condición son otro mecanismo de sincronización disponible para los subprocesos.
  • Las variables de condición proporcionan un lugar de encuentro para múltiples hilos
  • Cuando las variables de condición y el mutex se usan juntas, los subprocesos pueden esperar a que ocurran condiciones específicas de una manera no competitiva
  • Las variables de condición son cosas en el hilo, es decir, esperando que ocurra una determinada condición, como una señal.
  • La variable de condición debe usarse con el mutex, y la condición en sí misma está protegida por el mutex. El hilo debe bloquear primero el mutex antes de cambiar el estado de la condición
  • Otros subprocesos no se darán cuenta de este cambio antes de obtener el mutex, porque el mutex debe estar bloqueado antes de que se pueda calcular la condición.
  • ①Inicialización estática
    • Establezca directamente la variable de condición definida por pthread_cond_t en la constante PTHREAD_COND_INITIALIZER
    • Las variables de condición inicializadas estáticamente solo pueden tener atributos de variable de condición predeterminados y no pueden establecer otros atributos de variable de condición
pthread_cond_t cond;
cond=PTHREAD_COND_INITIALIZER;
//或者
pthread_cond_t *cond=(pthread_cond_t *)malloc(sizeof(pthread_cond_t));
*cond=PTHREAD_COND_INITIALIZER;
  • ②Inicialización dinámica
    • Las variables de condición inicializadas estáticamente solo pueden tener atributos de variable de condición predeterminados, podemos inicializar dinámicamente las variables de condición a través de la función pthread_mutex_init y podemos elegir establecer los atributos de la variable de condición durante la inicialización
#include <pthread.h>
int pthread_cond_init(pthread_cond_t* restrict cond,const pthread_condattr_t* restrict attr);
int pthread_cond_destroy(pthread_cond_t* cond);
  • Valor de retorno: devuelve 0 en caso de éxito; devuelve el número de error en caso de error
  • pthread_cond_init:
    • Función: inicializar la variable de condición
    • parámetro:
      • Parámetro 1: la variable de condición que debe inicializarse
      • Parámetro 2: El atributo de la variable de condición durante la inicialización. Si usa los atributos predeterminados, complete NULL aquí
  • pthread_cond_destroy:
    • Función: Desinicializar la variable de condición (antes de que la variable de condición libere la memoria)
    • Parámetros: variables de condición
    • Observaciones (énfasis): esta función solo desinicializa el mutex y no libera el espacio de memoria. Si el mutex se solicita a través de una función como malloc, entonces debe llamar a la función pthread_mutex_destroy antes de liberar el mutex
pthread_cond_t cond;
pthread_cond_init(&cond,NULL);
/*do something*/
pthread_cond_destroy(&cond);

pthread_cond_t * cond=(pthread_cond_t *)malloc(sizeof(pthread_cond_t));
pthread_cond_init(cond,NULL);
/*do something*/
pthread_cond_destroy(cond);
free(cond);

[Espere la función de variable de condición]

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t* restrict cond,pthread_mutex_t* restrict mutex);
int pthread_cond_timedwait(pthread_cond_t* cond,pthread_mutex_t* restrict mutex,const struct timespec* restrict tsptr);
  • Valor de retorno: devuelve 0 en caso de éxito; devuelve el número de error en caso de error
  • Cuando estas dos llamadas de función regresan con éxito, el subproceso debe volver a calcular la condición, porque es posible que otro subproceso ya se esté ejecutando y cambie la condición
  • pthread_cond_wait
    • Nota: Espere a que la variable de condición se convierta en verdadera
    • Cómo se usa: El parámetro mutex mutex se bloquea de antemano, y luego el mutex protege la condición, esperando que la variable de condición de 1 segundo del parámetro se convierta en verdadera. En el proceso de esperar a que la variable de condición se convierta en verdadera, esta función se ha bloqueado. Pero cuando está en un estado de bloqueo, el mutex mutex está desbloqueado (porque otros subprocesos necesitan usar este bloqueo para hacer que la variable de condición sea verdadera)
    • Cuando la función pthread_cond_wait regresa, el mutex se bloquea nuevamente
  • pthread_cond_timedwait
    • La función pthread_cond_timedwait tiene la misma función que la función pthread_cond_wait. Pero hay un parámetro de tiempo de espera más. El valor de tiempo de espera especifica cuánto tiempo estamos dispuestos a esperar, que está representado por la estructura de tiempo de espera
    • Si la condición no aparece después de que expira el tiempo de espera, esta función recuperará el mutex y devolverá el error ETIMEOUT
    • Nota: Este valor de tiempo es un número absoluto y no relativo. Por ejemplo, si está dispuesto a esperar 3 minutos, en lugar de convertir 3 minutos en una estructura de especificación de tiempo, debe agregar 3 minutos a la hora actual y luego convertirla en una estructura de especificación de tiempo.

[Obtener la función de adquisición de tiempo absoluto del valor de tiempo de espera]

  • Puede utilizar la función clock_gettime para obtener la hora actual representada por la estructura timespec. Pero no todas las plataformas admiten actualmente esta función. Por lo tanto, puede usar gettimeofday para obtener la hora actual representada por la estructura timeval y luego convertir esta hora en una estructura de especificación de tiempo
#include <sys/time.h>
#include <stdlib.h>
 
void maketimeout(struct timespec *tsp, long minutes)
{
	struct timeval now;
 
	/* get the current time */
	gettimeofday(&now, NULL);
	
	tsp->tv_sec = now.tv_sec;
	tsp->tv_nsec = now.tv_usec * 1000; /* usec to nsec */
	/* add the offset to get timeout value */
	tsp->tv_sec += minutes * 60;
}

【Función de envío de señal de variable de condición】

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t* cond);    //至少能唤醒一个等待该条件的线程
int pthread_cond_broadcast(pthread_cond_t* cond); //唤醒等待该条件的所有线程
  • Valor de retorno: devuelve 0 en caso de éxito; devuelve el número de error en caso de error
  • Estas dos funciones se utilizan para notificar al hilo que la variable de condición ha cumplido la condición (se vuelve verdadera). Cuando se llaman estas dos funciones, están señalando el hilo o condición
  • Se debe prestar atención: el hilo debe ser señalado después de cambiar el estado de la condición

[Combine el uso de variables de condición y mutex para sincronizar subprocesos]

#include <pthread.h>
 
struct msg {
	struct msg *m_next;
	/* ... more stuff here ... */
};
 
struct msg  *workq;
pthread_cond_t  qready = PTHREAD_COND_INITIALIZER;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;
 
void  process_msg(void)
{
	struct msg *mp;
 
	for (;;) {
		pthread_mutex_lock(&qlock);
		while (workq == NULL)
			pthread_cond_wait(&qready, &qlock);
		mp = workq;
		workq = mp->m_next;
		pthread_mutex_unlock(&qlock);
		/* now process the message mp */
	}
}

void  enqueue_msg(struct msg *mp)
{
	pthread_mutex_lock(&qlock);
	mp->m_next = workq;
	workq = mp;
	pthread_mutex_unlock(&qlock);
	pthread_cond_signal(&qready);
}

 

Supongo que te gusta

Origin blog.csdn.net/baidu_41388533/article/details/114851779
Recomendado
Clasificación