2010-12-01 16 views
0

メッセージキューのイベントについて通知するのにmq_notifyを使用していますが、登録されている通知機能が呼び出されていません。私は何か見落としてますか?mq_notifyはイベントについて通知していません(Linuxプログラミング)

私は以下の私のコードスニペット貼り付けています:コードはmanページからコピーしているので、私が求めるだろう


static void sigNotifier(union sigval sv) 
{ 
    printf ("I'm called.\n"); 
}  

int main() 
{ 
    mqd_t queueID = 0; 
    message_t msg; 
    int retval; 
    struct mq_attr attr; 
    struct sigevent sev; 

    attr.mq_msgsize = MSG_SIZE; 
    attr.mq_maxmsg = 30; 

    errno = 0; 

    queueID = mq_open(MSG_QUEUE_NAME, O_RDONLY, 0666, &attr); 

    if (queueID == -1) { 
     printf ("Message queue open failed: %d\n", errno); 
    } 

    sev.sigev_notify = SIGEV_THREAD; 
    sev.sigev_notify_function = sigNotifier; 
    sev.sigev_notify_attributes = NULL; 
    sev.sigev_value.sival_ptr = &queueID; 

    retval = mq_notify(queueID, &sev); 
    if (retval < 0) { 
     printf ("Notification failed: %d\n", errno); 
    } 

    while (1);  
} 
+0

'struct mq_attr attr = {0};構造体sigevent sev = {0}; 'それは何か違いはありますか?あなたはそれらの構造物のすべてのフィールドを初期化していないので、ゴミ値を渡すことができます。 – nos

答えて

0

を:

  1. はあなたが正しくキューにメッセージを送信してください。 ?
  2. ブロッキングリードを使って最初に読んで、何かが得られたかどうかを確認してください。 Linuxでは

あなたは、キューに関する通知を待つだけでなく、 mqd_tは、通常のファイルディスクリプタであるために選択/世論調査/ファイルディスクリプタを使用することができます。

0

また、キューにはすでにメッセージがあるかどうかを確認します。メッセージがキューに存在する場合、mq_notify()はキューが空で新しいメッセージが来るまで通知を受け取ることはありません。 キューはプログラム間で永続的に実行されるため、mq_unlink()がすでに開いている前に待ち行列。

0

マンページmq_notify:新しいメッセージが到着するとキューが以前に空であった場合にのみ、

1)メッセージ通知が発生します。 mq_notify()が呼び出された時点でキューが空でない場合は、キューが空になって新しいメッセージが到着した後にのみ通知が発生します。

2)通知は一度発生します。通知が配信された後、通知登録が削除され、別のプロセスがメッセージ通知に登録できます。通知されたプロセスが次の通知を受信したい場合は、mq_notify()を使用してさらに通知を要求できます。

3)メッセージキューから通知を受け取るために登録できるプロセスは1つだけです。

ので:

1)すぐにmq_notifyに登録した後、リーダーの過程で新しいメッセージをrecvをするMSGQを空に()。

2)次のメッセージを受信するために通知機能に再登録してください。

3)ここQ.

からメッセージを受信するための1つだけのプロセスは、C++で単純なメッセージキューリーダーコードレジスタ:

:ここ

#include <iostream> 
#include <mqueue.h> 
#include <string.h> 
#include <sstream> 
#include <unistd.h> 
#include <errno.h> 

using namespace std; 

#define MSG_Q_NAME "/MY_MSGQ_3" 

static void      /* Thread start function */ 
tfunc(union sigval sv) 
{ 
    mqd_t msq_id = *(static_cast<mqd_t*>(sv.sival_ptr)); 

    struct mq_attr attr; 
    if(mq_getattr(msq_id, &attr) < 0) 
    { 
    cout << "Error in mq_getattr " << strerror(errno) << endl; 
    return; 
    } 

    // Reregister for new messages on Q 
    struct sigevent sev; 
    sev.sigev_notify = SIGEV_THREAD; 
    sev.sigev_notify_function = tfunc; 
    sev.sigev_notify_attributes = NULL; 
    sev.sigev_value.sival_ptr = sv.sival_ptr; 
    if (mq_notify(msq_id, &sev) < 0) 
    { 
    cout << "Error during Reregister in msq_notify : " 
     << strerror(errno) << endl; 
    exit(EXIT_FAILURE); 
    } 

    // Read new message on the Q 
    char* arr = new char[attr.mq_msgsize]; 
    memset(arr, 0, attr.mq_msgsize); 
    if(mq_receive(msq_id, arr, attr.mq_msgsize, 0) < 0) 
    { 
    if(errno != EAGAIN) 
    { 
     cout << "Error in mq_receive " << strerror(errno) << endl; 
     exit(EXIT_FAILURE); 
    } 
    } 
    else 
    { 
    cout << "Msg rcvd " << arr << endl; 
    } 
} 

int main() 
{ 
    mqd_t msq_id = mq_open(MSG_Q_NAME, O_RDONLY | O_NONBLOCK | O_CREAT, 0666, 0); 
    if(msq_id == (mqd_t) -1) 
    { 
    cout << "Error on msg Q creation: " << strerror(errno) << endl; 
    exit(EXIT_FAILURE); 
    } 

    // The process is registered for notification for new message on the Q 
    struct sigevent sev; 
    sev.sigev_notify = SIGEV_THREAD; 
    sev.sigev_notify_function = tfunc; 
    sev.sigev_notify_attributes = NULL; 
    sev.sigev_value.sival_ptr = &msq_id; 

    if (mq_notify(msq_id, &sev) < 0) 
    { 
    cout << "Error on msg Q notify : " << strerror(errno) << endl; 
    exit(EXIT_FAILURE); 
    } 
    else 
    { 
    cout << "Notify for msg Q reception " << MSG_Q_NAME << endl; 
    } 

    // Man Page mq_notify: Message notification occurs only when a new 
    // message arrives and the queue was previously empty. If the queue was 
    // not empty at the time mq_notify() was called, then a notification will 
    // occur only after the queue is emptied and a new message arrives. 
    // 
    // So emptying the Q to recv new messages 
    ssize_t n = 0; 
    struct mq_attr attr; 
    if(mq_getattr(msq_id, &attr) < 0) 
    { 
    cout << "Error in mq_getattr " << strerror(errno) << endl; 
    exit(EXIT_FAILURE); 
    } 
    char* arr = new char[attr.mq_msgsize]; 
    memset(arr, 0, attr.mq_msgsize); 
    while((n = mq_receive(msq_id, arr, attr.mq_msgsize, 0) >= 0)) 
    { 
    cout << "Empty the Q. Msg rcvd " << arr << endl; 
    } 

    while(1) 
    ; 

    mq_close(msq_id); 
} 

は、単純なメッセージQライタコードであります

#include <iostream> 
#include <mqueue.h> 
#include <string.h> 
#include <sstream> 
#include <unistd.h> 
#include <errno.h> 
#include <sys/stat.h> 

using namespace std; 

#define MSG_Q_NAME "/MY_MSGQ_3" 

int main() 
{ 
    struct mq_attr attr; 
    memset(&attr, 0, sizeof attr); 
    attr.mq_msgsize = 8192; 
    attr.mq_flags = 0; 
    attr.mq_maxmsg = 10; 

    mqd_t msq_id = mq_open(MSG_Q_NAME, O_RDWR | O_CREAT | O_NONBLOCK, 
         0777, &attr); 
    if(msq_id == (mqd_t) -1) 
    { 
    cout << "Error on msg Q creation: " << strerror(errno) << endl; 
    exit(1); 
    } 

    // Write 5 msgs on message Q 
    for(int i = 0; i < 5; ++i) 
    { 
    stringstream s; 
    s << "My Msg " << i; 

    if(mq_send(msq_id, s.str().c_str(), strlen(s.str().c_str()), 0) < 0) 
    { 
     if(errno != EAGAIN) 
     { 
     cout << "Error on sending msg on MsgQ " << strerror(errno); 
     mq_close(msq_id); 
     exit(1); 
     } 
    } 
    else 
    { 
     cout << "Sent msg " << s.str() << endl; 
    } 

    sleep(1); // Easily see the received message in reader 
    } 

    mq_close(msq_id); 
} 
関連する問題