消息队列应该如何工作?

时间:2017-02-01 20:12:12

标签: c unix message-queue

我正在尝试了解消息队列。在我看到的示例中,msg strunct只有一个属性,除了第一个(类型)必须是long。所以,它会像struct msg{long mtype; char text[100]};

我尝试添加一个新的int属性x,看看我是否收到了文字和数字,并确实有效。

这是消息队列应该如何工作的吗?我可以在struct中拥有尽可能多的属性吗?

而且,也可以调用msgrcvmsgsnd函数,并将长度参数设置为sizeof(send) - sizeof(send.x),因为我知道结构的大小并不总是相同的作为每个属性sizeof的总和? 谢谢。

int main(){

    struct msg{
        long mtype;
        char text[100];
        int x;
    };

    int key = ftok(".", 10);
    int qid = msgget(key, 0666|IPC_CREAT);

    int pid = fork();

    if(pid == 0){
        struct msg send;
        send.mtype = 1;
        strcpy(send.text, "hello");
        send.x = 99;
        if(msgsnd(qid, (void*)&send, sizeof(send) - sizeof(send.x), 0)<0){
             printf("Error child: ");
        }
    }
    else{
        struct msg recieve;
        if(msgrcv(qid, (void*)&recieve, sizeof(recieve) - sizeof(recieve.x), 1, 0)<0){
             perror("Error parent: ");
        };
        printf("text: %s\nnumber: %d", recieve.text, recieve.x);
    }

    return 0;
}

3 个答案:

答案 0 :(得分:4)

来自man page,位于:

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

msgp定义为:

  

msgp参数是指向调用者定义的结构的指针          遵循一般形式:

      struct msgbuf {
           long mtype;       /* message type, must be > 0 */
           char mtext[1];    /* message data */
       };

大胆 是我的

这里的主要观点是调用者定义的。因此,只要输入结构(由msgsnd发送)和输出结构(由msgrcv接收)相同,mtype之后的数据就可以是您想要的任何数据(只要您正确指定大小)。对于您的情况,您真的只需要:

msgsnd(qid, (void*)&send, sizeof(send) - sizeof(send.mtype), 0)

msgrcv(qid, (void*)&recieve, sizeof(recieve) - sizeof(send.mtype), 1, 0)

答案 1 :(得分:1)

char []只是一个占位符,您可以在所需的long mtype字段后在结构中拥有您想要的任何内容。 msgsnd()调用的大小不包括mtype。

你差不多了。

这是一个工作版本:

class BadLengthException: public exception{
    public:
        int n;
        BadLengthException(int x) { n=x; };
        virtual int what() throw() {
            return n;
        }
    };
/*
This function checks the username's length, 
and returns true when length is greater than or equal to 5.
Otherwise it returns false.
*/
bool checkUsername(string username) {
    bool isValid = true;
    int n = username.length();
    if(n < 5) {
        throw BadLengthException(n);    //the problem
    }
    for(int i = 0; i < n-1; i++) {
        if(username[i] == 'w' && username[i+1] == 'w') {
            isValid = false;
        }
    }
    return isValid;
}

int main() {
    int T; cin >> T;
    while(T--) {
        string username;
        cin >> username;
        try {
            bool isValid = checkUsername(username);
            if(isValid) {
                cout << "Valid" << '\n';
            } else {
                cout << "Invalid" << '\n';
            }
        } catch (BadLengthException e) {
            cout << "Too short: " << e.what() << '\n';
        }
    }
    return 0;
}

答案 2 :(得分:0)

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

由于msgp参数声明为const void*,因此您可以使用所需的任何数据类型。没有任何内容表明它必须是struct而只有longchar[]。这意味着你可以sizeof(send)。您无需调整要发送的额外结构成员。实际上,这样做会导致问题,因为整个结构都不会被处理。唯一重要的是msgrcv()使用与前一个msgsnd()相同的结构。请参阅this example