1

以下にコードがあり、毎秒カチカチ音をたてて完全に正常に動作します。この問題は、//選択と挿入のクエリを1秒ごとに処理する必要がある場合に始まり、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

単なる提案 - あなたが探しているものであるかもしれないし、そうでないかもしれません - 選択および挿入クエリをreader_threadのキューに追加し続け、キューからクエリを取得する関数用に別のスレッドを作成し、実際に実行することができますそれらを実行します。

于 2012-07-14T06:01:14.150 に答える