1

我们在下面有一个代码,它每秒都在滴答作响,它工作得很好。当我们有 //select 和 insert 查询需要处理每一秒时,问题就开始了,我们注意到时间间隔在 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");
        } 
4

2 回答 2

1

您可能希望以不同的方式进行设置:

1在产生任何线程之前,使用pthread_sigmask()使应用程序忽略所有信号。然后,此行为将被之后创建的任何线程继承,并使它们不会吃掉任何信号,因为只有主线程来处理它们(参见下面的步骤 2)。

2在创建所有线程后,再次使用pthread_sigmask()以使主线程接收SIGALRM和使用sigaction()(而不是signal();另请参阅我对 OP 的评论)为SIGALRM.

3为每个线程声明一个标志。当前,重置标志的线程可能会在另一个线程启动之前执行此操作。


如果主线程不需要做任何事情(或者你不介意产生另一个线程):或者使用安装信号处理程序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()

于 2012-07-14T14:23:07.590 回答
0

只是一个建议 - 可能/可能不是您正在寻找的那个 - 您可以执行一些操作,例如继续将 select 和 insert 查询添加到 reader_thread 中的队列中,并为从队列中获取查询的函数设置一个单独的线程,实际上执行它们。

于 2012-07-14T06:01:14.150 回答