Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

229
Vistas
¿Cómo crear una demora precisa de nanosegundos en un pthread y cómo ejecutar una parte del pthread del programa sin interrupción?

Soy un principiante en la programación C. En el siguiente código, tenemos dos pthreads. Quiero que uno de ellos se retrase a elección del usuario después de sincronizar los dos pthreads. Quiero que este retraso sea lo más preciso posible. En el siguiente código he hecho esto pero no ocurre la cantidad exacta de retraso.

Pero también tengo otra pregunta, y es cómo puedo obligar a un pthread a ejecutar cierta parte del programa de principio a fin sin interrupción.

Gracias de antemano.

código:

 #include <stdio.h> #include <unistd.h> #include <pthread.h> #include <sys/random.h> #include <sys/time.h> #include <math.h> pthread_cond_t cond; pthread_mutex_t cond_mutex; unsigned int waiting; struct timeval timeZero, timeOne, timeZeroBase, timeOneBase; struct timespec tim, tim2; int flag = 0; void synchronize(void) { pthread_mutex_lock(&cond_mutex); if (++waiting == 2) { pthread_cond_broadcast(&cond); } else { while (waiting != 2) pthread_cond_wait(&cond, &cond_mutex); } pthread_mutex_unlock(&cond_mutex); } void *threadZero(void *_) { // ... synchronize(); gettimeofday(&timeZeroBase, 0); if(flag == 0) nanosleep(&tim, &tim2); gettimeofday(&timeZero, 0); timeZero.tv_usec = timeZero.tv_usec - timeZeroBase.tv_usec; // ... return NULL; } void *threadOne(void *_) { // ... synchronize(); gettimeofday(&timeOneBase, 0); if(flag == 1) nanosleep(&tim, &tim2); gettimeofday(&timeOne, 0); timeOne.tv_usec = timeOne.tv_usec - timeOneBase.tv_usec; // ... return NULL; } int main(void) { pthread_t zero, one; tim.tv_sec = 0; tim.tv_nsec = 50; printf("Declare the number of function (0 or 1): "); scanf("%d", &flag); pthread_create(&zero, NULL, threadZero, NULL); pthread_create(&one, NULL, threadOne, NULL); // ... pthread_join(zero, NULL); pthread_join(one, NULL); printf("\nReal delay (ns): %lu\n", (timeZero.tv_usec - timeOne.tv_usec)); return 0; }
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Una forma de aumentar la precisión es esperar ocupado en lugar de dormir.

Creé una función llamada mysleep que toma una struct timespec* que contiene el tiempo de sueño solicitado. Verifica la hora actual y agrega el tiempo de suspensión solicitado a eso, y luego simplemente gira hasta la hora actual >= el punto objetivo en el tiempo.

Sin embargo, tenga en cuenta: no se garantiza que permanezca dentro de cualquier precisión. A menudo estará bastante bien, pero a veces, cuando el sistema operativo pone el hilo en espera, verá picos en el tiempo medido. Si no tiene suerte, la calibración tendrá uno de estos picos y luego todos sus sueños se apagarán por completo. Puede ejecutar la rutina de calibración 100 veces y luego elegir el valor medio para que esa desafortunada circunstancia sea muy poco probable.

 #include <stdio.h> #include <time.h> static long calib; // used for calibrating mysleep() void mysleep(const struct timespec *req) { struct timespec tp, now; clock_gettime(CLOCK_MONOTONIC, &tp); // get current time point // add the requested sleep time and remove the calibrated value tp.tv_sec += req->tv_sec; tp.tv_nsec += req->tv_nsec - calib; if(tp.tv_nsec > 999999999) { tp.tv_nsec -= 1000000000; ++tp.tv_sec; } else if(tp.tv_nsec<0) { tp.tv_nsec += 1000000000; --tp.tv_sec; } // busy-wait until the target time point is reached: do { clock_gettime(CLOCK_MONOTONIC, &now); } while(now.tv_sec < tp.tv_sec || (now.tv_sec == tp.tv_sec && now.tv_nsec < tp.tv_nsec)); } struct timespec get_diff(const struct timespec *start, struct timespec *end) { struct timespec temp; if((end->tv_nsec - start->tv_nsec) < 0) { temp.tv_sec = end->tv_sec - start->tv_sec - 1; temp.tv_nsec = 1000000000 + end->tv_nsec - start->tv_nsec; } else { temp.tv_sec = end->tv_sec - start->tv_sec; temp.tv_nsec = end->tv_nsec - start->tv_nsec; } return temp; } // A non-scientific calibration routine void calibrate() { struct timespec start, end, sleep = {0}; calib = 0; clock_gettime(CLOCK_MONOTONIC, &start); mysleep(&sleep); clock_gettime(CLOCK_MONOTONIC, &end); struct timespec diff = get_diff(&start, &end); calib = (diff.tv_sec * 1000000000 + diff.tv_nsec) / 2; } int main() { calibrate(); // must be done before using mysleep() // use mysleep() }

Manifestación

Salida posible (con un pico):

 calib=157 should be close to 1000: 961 should be close to 1000: 931 should be close to 1000: 906 should be close to 1000: 926 should be close to 1000: 935 should be close to 1000: 930 should be close to 1000: 916 should be close to 1000: 932 should be close to 1000: 124441 should be close to 1000: 911
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda