运行 线程每 20 毫秒定期失败
Running thread periodically every 20 ms fails
目前我正在为一个嵌入式应用程序编程,该应用程序会定期从传感器读取值。我希望每 20 毫秒读取一次。
我正在使用这个 tutorial
struct periodic_info {
int sig;
sigset_t alarm_sig;
};
static int make_periodic(int unsigned period, struct periodic_info *info)
{
static int next_sig;
int ret;
unsigned int ns;
unsigned int sec;
struct sigevent sigev;
timer_t timer_id;
struct itimerspec itval;
/* Initialise next_sig first time through. We can't use static
initialisation because SIGRTMIN is a function call, not a constant */
if (next_sig == 0)
next_sig = SIGRTMIN;
/* Check that we have not run out of signals */
if (next_sig > SIGRTMAX)
return -1;
info->sig = next_sig;
next_sig++;
/* Create the signal mask that will be used in wait_period */
sigemptyset(&(info->alarm_sig));
sigaddset(&(info->alarm_sig), info->sig);
/* Create a timer that will generate the signal we have chosen */
sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = info->sig;
sigev.sigev_value.sival_ptr = (void *)&timer_id;
ret = timer_create(CLOCK_MONOTONIC, &sigev, &timer_id);
if (ret == -1)
return ret;
/* Make the timer periodic */
sec = period / 1000000;
ns = (period - (sec * 1000000)) * 1000;
itval.it_interval.tv_sec = sec;
itval.it_interval.tv_nsec = ns;
itval.it_value.tv_sec = sec;
itval.it_value.tv_nsec = ns;
ret = timer_settime(timer_id, 0, &itval, NULL);
return ret;
}
static void wait_period(struct periodic_info *info)
{
int sig;
sigwait(&(info->alarm_sig), &sig);
}
static int thread_1_count;
主线:
int main(){
pthread_t t_1;
pthread_t t_2;
sigset_t alarm_sig;
int i;
printf("Periodic threads using POSIX timers\n");
/* Block all real time signals so they can be used for the timers.
Note: this has to be done in main() before any threads are created
so they all inherit the same mask. Doing it later is subject to
race conditions */
sigemptyset(&alarm_sig);
for (i = SIGRTMIN; i <= SIGRTMAX; i++)
sigaddset(&alarm_sig, i);
sigprocmask(SIG_BLOCK, &alarm_sig, NULL);
pthread_create(&t_1, NULL, thread_1, NULL);
sleep(10);
printf("Thread 1 %d iterations\n", thread_1_count);
return 0;
我现在的问题,我用高分辨率时钟测量时间,周期为 20ms。
static void *thread_1(void *arg)
{
struct periodic_info info;
printf("Thread 1 period 10ms\n");
make_periodic(20000, &info);
while (1) {
auto start = std::chrono::high_resolution_clock::now();
printf("Hello\n");
thread_1_count++;
wait_period(&info);
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> ms_double = finish - start;
std::cout << ms_double.count() << "ms\n";
}
return NULL;
}
我得到的输出是:
...
19.8556ms
19.8587ms
19.8556ms
19.8543ms
19.8562ms
19.8809ms
19.7592ms
19.8381ms
19.8302ms
19.8437ms
...
所以我的问题是,为什么时间比我的经期时间短,我做错了什么?
为了更准确,每次迭代不要花费两次时间,保留最后一个值,如下所示:
static void *thread_1(void *arg)
{
struct periodic_info info;
printf("Thread 1 period 10ms\n");
make_periodic(20000, &info);
auto start = std::chrono::high_resolution_clock::now();
while (1) {
wait_period(&info);
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> ms_double = finish - start;
std::cout << ms_double.count() << "ms\n";
start = finish;
}
return NULL;
}
这样的话,时间的测量会更加准确。
目前我正在为一个嵌入式应用程序编程,该应用程序会定期从传感器读取值。我希望每 20 毫秒读取一次。
我正在使用这个 tutorial
struct periodic_info {
int sig;
sigset_t alarm_sig;
};
static int make_periodic(int unsigned period, struct periodic_info *info)
{
static int next_sig;
int ret;
unsigned int ns;
unsigned int sec;
struct sigevent sigev;
timer_t timer_id;
struct itimerspec itval;
/* Initialise next_sig first time through. We can't use static
initialisation because SIGRTMIN is a function call, not a constant */
if (next_sig == 0)
next_sig = SIGRTMIN;
/* Check that we have not run out of signals */
if (next_sig > SIGRTMAX)
return -1;
info->sig = next_sig;
next_sig++;
/* Create the signal mask that will be used in wait_period */
sigemptyset(&(info->alarm_sig));
sigaddset(&(info->alarm_sig), info->sig);
/* Create a timer that will generate the signal we have chosen */
sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = info->sig;
sigev.sigev_value.sival_ptr = (void *)&timer_id;
ret = timer_create(CLOCK_MONOTONIC, &sigev, &timer_id);
if (ret == -1)
return ret;
/* Make the timer periodic */
sec = period / 1000000;
ns = (period - (sec * 1000000)) * 1000;
itval.it_interval.tv_sec = sec;
itval.it_interval.tv_nsec = ns;
itval.it_value.tv_sec = sec;
itval.it_value.tv_nsec = ns;
ret = timer_settime(timer_id, 0, &itval, NULL);
return ret;
}
static void wait_period(struct periodic_info *info)
{
int sig;
sigwait(&(info->alarm_sig), &sig);
}
static int thread_1_count;
主线:
int main(){
pthread_t t_1;
pthread_t t_2;
sigset_t alarm_sig;
int i;
printf("Periodic threads using POSIX timers\n");
/* Block all real time signals so they can be used for the timers.
Note: this has to be done in main() before any threads are created
so they all inherit the same mask. Doing it later is subject to
race conditions */
sigemptyset(&alarm_sig);
for (i = SIGRTMIN; i <= SIGRTMAX; i++)
sigaddset(&alarm_sig, i);
sigprocmask(SIG_BLOCK, &alarm_sig, NULL);
pthread_create(&t_1, NULL, thread_1, NULL);
sleep(10);
printf("Thread 1 %d iterations\n", thread_1_count);
return 0;
我现在的问题,我用高分辨率时钟测量时间,周期为 20ms。
static void *thread_1(void *arg)
{
struct periodic_info info;
printf("Thread 1 period 10ms\n");
make_periodic(20000, &info);
while (1) {
auto start = std::chrono::high_resolution_clock::now();
printf("Hello\n");
thread_1_count++;
wait_period(&info);
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> ms_double = finish - start;
std::cout << ms_double.count() << "ms\n";
}
return NULL;
}
我得到的输出是:
...
19.8556ms
19.8587ms
19.8556ms
19.8543ms
19.8562ms
19.8809ms
19.7592ms
19.8381ms
19.8302ms
19.8437ms
...
所以我的问题是,为什么时间比我的经期时间短,我做错了什么?
为了更准确,每次迭代不要花费两次时间,保留最后一个值,如下所示:
static void *thread_1(void *arg)
{
struct periodic_info info;
printf("Thread 1 period 10ms\n");
make_periodic(20000, &info);
auto start = std::chrono::high_resolution_clock::now();
while (1) {
wait_period(&info);
auto finish = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> ms_double = finish - start;
std::cout << ms_double.count() << "ms\n";
start = finish;
}
return NULL;
}
这样的话,时间的测量会更加准确。