我们在下面有一个代码,它每秒都能保持滴答作响。问题开始时我们//选择和插入查询需要每秒处理一次我们注意到时间间隔在1到10秒之间。因此,我们实际上错过了一些要完成的处理。知道怎么克服这个吗?是不是我们需要在每一秒创建一个单独的线程呢?谢谢。
void * reader_thread (void * arg) {
while (1) {
if (flag) {
struct timeval tv;
char timeBuf[10],secondBuf1[100],queryBuf1[500],queryBuf2[500];
char buff[20] = {0};
gettimeofday (&tv, NULL);
//fprintf (stderr, "[%d.%06d] Flag set to 1 on ", tv.tv_sec, tv.tv_usec);
tv.tv_sec -= 5;
strftime(buff, 20, "%Y-%m-%d %H:%M:%S", localtime(&tv.tv_sec));
printf("\nTime is %s", buff);
//select and insert queries
fprintf (stderr, " %s\n", buff);
flag = 0;
}
usleep (100); // will skew the processing but not signal delivery
}
return NULL;
}
void callback (int sig) {
flag = 1; // this is the only thing the callback does
}
int main () {
timer_t tid = 0;
pthread_t thread;
struct itimerspec it;
char *localServer = "localhost", *remoteServer = "localhost";
char *localUser = "user1", *remoteUser = "user2";
char *localPassword = "****", *remotePassword = "*****";
char *localDatabase = "db1", *remoteDatabase = "db1";
localConn = mysql_init(NULL), remoteConn = mysql_init(NULL);
if (!mysql_real_connect(localConn, localServer,
localUser, localPassword, localDatabase, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(localConn));
exit(1);
}
pthread_create (&thread, NULL, reader_thread, NULL);
signal (SIGALRM, callback);
it.it_value.tv_sec = 1;
it.it_value.tv_nsec = 0;
it.it_interval.tv_sec = 1;
it.it_interval.tv_nsec = 0;
timer_create (CLOCK_REALTIME, NULL, &tid);
timer_settime (tid, 0, &it, NULL);
while (1) sleep (100);
return 0;
}
编辑代码。
sigset_t sigset;
sigfillset(&sigset);
if (pthread_sigmask(
SIG_BLOCK,
&sigset,
NULL))
{
perror("pthread_sigmask");
}
pthread_create (&thread, NULL, reader_thread, NULL);
//sigset_t sigset;
//sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
if (pthread_sigmask(
SIG_UNBLOCK,
&sigset,
NULL))
{
perror("pthread_sigmask");
}
答案 0 :(得分:1)
您可能希望以不同的方式设置它:
1 在产生任何线程之前使用pthread_sigmask()
使应用忽略所有信号。然后,此行为将由之后创建的任何线程继承,并且不会消除任何信号,因为只有主线程才能处理它们(请参阅下面的步骤2)。
2 创建所有主题后再次使用pthread_sigmask()
使主线程接收SIGALRM
并使用sigaction()
(而不是signal()
;另请参阅我对OP的评论,为SIGALRM
设置信号处理程序。
3为每个线程声明标志。目前,重置标志的线程可能会在另一个线程启动之前执行此操作。
如果主线程不需要执行anthing(或者你不介意产生另一个线程):或者使用sigaction()
安装信号处理程序(如上面的步骤2所述)你可以使用类似的东西do { int sig = sigwaitinfo(...); ... } while (1);
用于提取从队列接收的信号,并设置用于触发查询开始的标志。
<强>更新强>:
如何使用pthread_sigmask()
阻止调用线程的所有信号的示例:
sigset_t sigset;
sigfillset(&sigset);
if (pthread_sigmask(
SIG_BLOCK,
&sigset,
NULL))
{
perror("pthread_sigmask");
}
有关如何使用pthread_sigmask()
取消阻止SIGALRM
调用线程的示例:
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
if (pthread_sigmask(
SIG_UNBLOCK,
&sigset,
NULL))
{
perror("pthread_sigmask");
}
有关pthread_sigmask()
的详细信息,请参阅man pthread_sigmask()
。
答案 1 :(得分:0)
只是一个建议 - 可能/可能不是你正在寻找的那个 - 你可以做一些事情,比如继续向reader_thread中的队列添加select和insert查询,并为一个函数提供一个单独的线程,该函数从排队并实际执行它们。