C 在linux中使用计时器记录度量
我需要捕获一些指标,比如发送tcp消息的时间和linux上c语言中每秒发送的消息数。 我想知道这是否可以通过定时器来完成,这样每当定时器过期时,我只需打印度量。主要问题是,在度量递增时可能会出现计时器,在这种情况下,我的信号处理程序将打印损坏的数据。有办法解决这个问题吗 所以我心目中的伪代码是声明一个全局结构,它包含每个发送和计数的发送时间C 在linux中使用计时器记录度量,c,linux,C,Linux,我需要捕获一些指标,比如发送tcp消息的时间和linux上c语言中每秒发送的消息数。 我想知道这是否可以通过定时器来完成,这样每当定时器过期时,我只需打印度量。主要问题是,在度量递增时可能会出现计时器,在这种情况下,我的信号处理程序将打印损坏的数据。有办法解决这个问题吗 所以我心目中的伪代码是声明一个全局结构,它包含每个发送和计数的发送时间 struct db { struct sendTimes sendTimesPerSecond[10000]; // some large number
struct db
{
struct sendTimes sendTimesPerSecond[10000]; // some large number which i cannot send in a second
int count;
}
在哪里
然后提供一些可以在structdb上工作的函数,例如
void record_send_time(pointer_to_db, sendTimes); // simply store the times
void incrementMessagesSent(pointer_to_db); //basically count++
然后我可以做一些事情,比如:
signal(SIGALRM, alarm_handler);
alarm(1)
struct db database;
for(;;) {
struct sendTimes sTime;
sTime.start_time = now(); // current time
send()
sTime.end_time = now();
record_send_time(&database, sTime);
incrementMessagesSent(&database);
}
void alarm_handler(int signo)
{
printf database;
alarm(1);
}
更新:
Wildplasser关于管道的评论似乎是处理上述问题的最安全方式。您可以使用报警处理程序设置标志,而不是从信号处理程序打印
int print_database_flag = 0; // global flag
// ...
record_send_time(&database, sTime);
if (print_database_flag) {
printf database;
print_database_flag = 0;
}
void alarm_handler(int signo)
{
print_database_flag = 1;
alarm(1);
}
使用getrusage(2)
,它有两个struct timeval
捕获程序在用户(您的代码)和内核模式(发送等)下使用的时间
我不知道你打算用printf数据库做什么代码>,但我必须警告您,printf()在信号处理程序中不安全。顺便说一句:避免信号处理程序中出现printf或其他争用的最简单方法是使用管道:让信号处理程序写入管道,让main位于select()或poll()循环上。无需锁定/关闭。记住:write()是原子的。@wildplasser在信号处理程序中翻转布尔变量的值是否足够好,如更新:部分中所述?不,您仍然会遇到竞争(谁将重置变量?),和/或main()需要轮询,变量需要是volatile/sig_atomic__t等。太混乱。双重锁定,即,在主处理器和信号处理器中,将导致死锁。您可以使用Reentrant lock,但这样做不会保护全局数据结构被破坏。在该示例中没有锁定,只检查一个标志。我看不到潜在的僵局。最糟糕的情况是,多个alarm()调用将导致高负载下的一次打印,这对于显示getrusage和timersub来说是正确的。我是手工计算的。
int print_database_flag = 0; // global flag
// ...
record_send_time(&database, sTime);
if (print_database_flag) {
printf database;
print_database_flag = 0;
}
void alarm_handler(int signo)
{
print_database_flag = 1;
alarm(1);
}
#include <sys/time.h>
#include <sys/resource.h>
struct rusage start, end;
getrusage(RUSAGE_SELF, &start);
// do what you have to do
getrusage(RUSAGE_SELF, &end);
struct timeval utime, stime;
timersub(&end.ru_utime, &start.ru_utime, &utime);
timersub(&end.ru_stime, &start.ru_stime, &stime);
printf("Work took %lu microseconds of user time and %lu microseconds of system time\n",
(utime.tv_sec * 1000 * 1000) + utime.tv_usec,
(stime.tv_sec * 1000 * 1000) + stime.tv_usec
);