我正在尝试使用队列在两个线程之间传递消息,但到目前为止我还没有得到任何结果。当我在收到邮件之后和邮件发送之前打印邮件内容时,它似乎只能保持其价值。我需要用1个服务器线程和多个客户端线程来实现它,但是现在我只使用1个。这是我的代码
struct msg //struct for client requests to server
{
long mtype;
int numResources; //number of resources to be requested
int ID; //ID associated with client thread
};
int c1PID; //process ID variable for client thread 1
int serverPID;
key_t key1;
key_t keyS;
int msqid1;
int msqidS;
int main(int arc, char *argv[])
{
key1 = ftok(".", '1'); //queue for client thread 1 to receive msgs from server
msqid1 = msgget(key1, 666 | IPC_CREAT);
keyS = ftok(".", 's'); //general queue for server
msqidS = msgget(keyS, 666 | IPC_CREAT);
pthread_t threads[2]; //create an array of pthreads
if ((serverPID = pthread_create(&threads[0], NULL, server, NULL)) != 0)
{
perror("server thread");
exit(1);
}
if ((c1PID = pthread_create(&threads[1], NULL, client, NULL)) != 0)
{
perror("client thread");
exit(1);
}
pthread_exit(NULL);
}
void *server()
{
struct msg request;
size_t size = sizeof(struct msg) - offsetof(struct msg, numResources);
while (1)
{
msgrcv(msqidS, &request, size, 2, 0);
printf("received: numResources requested = %d\n", request.numResources);
request.numResources = 9001;
printf("sending: numResources requested = %d\n", request.numResources);
msgsnd(msqid1, &request, size, 0);
sleep(1);
}
}
void *client()
{
struct msg request;
size_t size;
request.numResources = 0;
size = sizeof(struct msg) - offsetof(struct msg, numResources);
msgsnd(msqidS, &request, size, 0);
while(1)
{
msgrcv(msqid1, &request, size, 2, 0);
printf("received: numResources requested = %d\n", request.numResources);
request.numResources += 1;//(int)(ceil((double)(rand()%2)) + 1);
printf("sending: numResources requested = %d\n", request.numResources);
msgsnd(msqidS, &request, size, 0);
sleep(1);
}
我拿出了很多我的印刷语句,但它看起来像这样:
Server thread:
received: numResources = 9001;
sending: numResources = 9001;
client thread:
received: numResources = 1;
sending: numResources = 2;
Server thread:
received: numResources = 9001;
sending: numResources = 9001;
client thread:
received: numResources = 2;
sending: numResources = 3;
答案 0 :(得分:2)
您的问题是您已在邮件队列中设置了无意义的权限。在这些行中,您使用了十进制常量666
,您应该使用八进制常量0666
:
msqid1 = msgget(key1, 666 | IPC_CREAT);
msqid1 = msgget(key1, 666 | IPC_CREAT);
这意味着您已经创建了具有八进制权限01232
的队列,但不包括读取权限 - 因此您之后的msgget()
次调用现在都失败了EPERM
(其中你会看到你是否检查了那些错误的来电。)
您必须删除邮件队列,并允许程序使用正确的权限重新创建它们。您需要使用msqid
作为队列,使用IPC_RMID
命令msgctl()
来执行此操作,如以下程序所示:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: %s <msqid> [<msgqid> ...]\n", argv[0]);
return 1;
}
while (*++argv)
{
int msqid = atoi(*argv);
printf("Removing msqid %d\n", msqid);
if (msgctl(msqid, IPC_RMID, NULL) != 0) {
perror("msgctl");
return 2;
}
}
return 0;
}
由于SYS V消息队列设计糟糕,您无法再从msqid
获取msgget()
值,因为msgget()
失败。要获取要移除的msqid
值,请查看文件/proc/sysvipc/msg
。
<强> PS:强>
我强烈建议您使用POSIX消息队列(mq_open()
,mq_send()
,mq_receive()
等)。界面得到了显着改善。
答案 1 :(得分:1)
这是它在运行中打印出来的效果。
program starting
Msg sent from client
*****In client thread*****
Msg received by client
received: numResources requested = 0
sending: numResources requested = 1
Msg sent from client
*****In server thread*****
Msg received by server
received: numResources requested = 1
sending: numResources requested = 9001
Msg sent from server.
*****In client thread*****
Msg received by client
received: numResources requested = 9001
sending: numResources requested = 9002
Msg sent from client
*****In server thread*****
Msg received by server
received: numResources requested = 9002
sending: numResources requested = 9001
Msg sent from server.
*****In client thread*****
Msg received by client
received: numResources requested = 9001
sending: numResources requested = 9002
Msg sent from client
*****In server thread*****
Msg received by server
received: numResources requested = 9002
sending: numResources requested = 9001
Msg sent from server.
*****In client thread*****
Msg received by client
received: numResources requested = 9001
sending: numResources requested = 9002
Msg sent from client
紧接着......
program starting
Msg sent from client
*****In client thread*****
Msg received by client
received: numResources requested = 9001
sending: numResources requested = 9002
Msg sent from client
*****In server thread*****
Msg received by server
received: numResources requested = 0
sending: numResources requested = 9001
Msg sent from server.
*****In client thread*****
Msg received by client
received: numResources requested = 9002
sending: numResources requested = 9003
Msg sent from client
*****In server thread*****
Msg received by server
received: numResources requested = 9001
sending: numResources requested = 9001
Msg sent from server.
*****In client thread*****
Msg received by client
received: numResources requested = 9003
sending: numResources requested = 9004
Msg sent from client
*****In server thread*****
Msg received by server
received: numResources requested = 9001
sending: numResources requested = 9001
Msg sent from server.
这些是一个接一个地运行,没有对代码进行任何更改。
答案 2 :(得分:0)
编辑: sizeof(struct msg) - offsetof(struct msg,numResources);应该没问题。
但是,根据docs,您的mtype
需要一个正整数。将其初始化为2,因为您对msgrecv的调用表示只接收消息类型2。
为所有msgsnd / msgrecv调用添加错误检查,因此您确定没有默默地收到错误。
将错误检查添加到您的ftok和msgget调用中。