我是 C 編程的初學者。在下面的代碼中,我們有兩個 pthread。我希望在兩個 pthread 同步后根據用戶的選擇延遲其中一個。我希望這個延遲盡可能準確。在下面的代碼中,我已經這樣做了,但沒有發生確切的延遲量。
但是我還有一個問題,那就是如何強制一個pthread從頭到尾運行程式的某個部分而不會中斷。
先感謝您。
代碼:
#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;
}
uj5u.com熱心網友回復:
可以提高準確性的一種方法是忙等待而不是睡眠。
我創建了一個名為的函式mysleep,它struct timespec*包含請求的睡眠時間。它檢查當前時間并將請求的睡眠時間添加到其中 - 然后旋轉直到>=目標時間點的當前時間。
但請注意:不能保證保持在任何精度范圍內。這通常是可以的,但有時當作業系統暫停執行緒時,您會看到測量時間出現峰值。如果你不走運,校準會出現這些尖峰之一,然后你所有的睡眠都將完全關閉。您可以運行校準程式 100 次,然后選擇中間值,使這種不幸的情況不太可能發生。
#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()
}
演示
可能的輸出(帶尖峰):
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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/391063.html
