从send.c发送消息和进程ID后,如何从get.c文件中的消息队列中获取消息?
来自send.c的:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_COUNT 200
#define BUF_SIZE 100
#define MSGSZ 255
#define KEY 10
//from http://www.tldp.org/LDP/LG/issue89/misc/raghu/send.c.txt
/*
* Declare the message structure.
*/
typedef struct msgbuf {
long mtype;
char mtext[MSGSZ + 1];
} message_buf;
static message_buf sbuf;
static size_t buf_length;
static int mqid;
int main(int argc, char*argv[])
{
pid_t pid;
int i;
char buf[BUF_SIZE];
if ((pid = getpid()) < 0) { //getting child process id
perror("unable to get pid \n");
}
else {
printf("The process id is %d \n", pid);
}
char line[256];
int c = 0; //for character count
printf("enter word/s (must be less than or equal 256 characters): \n");
fgets(line, 256, stdin);
printf("\n");
if ( c > 256 )
{
printf("Must enter less than or equal to 256 characters.");
printf("Has %d characters", countChar(line));
exit(0);
}
(void) strcpy(sbuf.mtext, line);
buf_length = strlen(sbuf.mtext) + 1;
sbuf.mtype = pid;
logMessage(sbuf.mtype, line);
}
int countChar(char *s)
{
int len = 0;
for(; *s != '\0'; s++, len++);
return len;
}
int logMessage(int serviceId,char*message)
{
int rv, mask, msgid;
key_t key = KEY;
mask = 0644|IPC_CREAT;
msgid = msgget(key, mask);
if (msgsnd(msgid, &sbuf, buf_length, IPC_NOWAIT) < 0) //sending message
{
perror("msgsnd");
exit(1);
}
else
{
printf("id - %d : message - %s \n", serviceId, message);
}
return rv;
}
来自get.c的:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#define MSGSZ 255
#define MSGCHARS 255
#define KEY 10
typedef struct msgbuf
{
int mtype;
char mtext[MSGSZ];
}message_buf;
static int queue_id;
void INThandler(int);
int main(int argc, char*argv[])
{
key_t key = KEY
message_buf rbuf;
int msgflg = 0644;
int msqid = msgget(key, msgflg);
if (msqid < 0) {
perror("msgget");
exit(1);
}
rbuf.mtype = 1;
for(;;){
if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0) {
perror("msgrcv");
exit(1);
}
printf("id - %d : message - %s ", rbuf.mtype, rbuf.mtext);
}
signal(SIGINT, INThandler);//the function starts with ctrl+c.
while (1)
pause();
return 0;
}
void INThandler(int sig)//this function deletes the message queue
{
signal(sig, SIG_IGN);
int mask, msgid;
key_t key = KEY;
mask = 0644;
msgid = msgget(key, mask);
if (msgid == -1) {
printf("Message queue does not exist.\n");
exit(EXIT_SUCCESS);
}
if (msgctl(msgid, IPC_RMID, NULL) == -1) {
fprintf(stderr, "Message queue could not be deleted.\n");
exit(EXIT_FAILURE);
}
else {
printf("Message queue was deleted.\n");
}
exit(0);
return EXIT_SUCCESS;
}
我能够从send.c成功发送进程id和消息,但是当执行get.c时,代码什么都不返回。你是怎么解决的?
答案 0 :(得分:1)
您的问题由msgrcv()
的POSIX规范确定。 msgtyp
参数是第四个参数,在代码中指定为1
:
参数
msgtyp
指定请求的消息类型,如下所示:
如果
msgtyp
为0,则应收到队列中的第一条消息。如果
msgtyp
大于0,则应收到msgtyp
类型的第一条消息。如果
msgtyp
小于0,则应收到小于或等于msgtyp绝对值的最低类型的第一条消息。
由于发送过程不是init
过程,因此从来没有来自PID = 1的消息。只需更改您的来电:
if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0)
到
if (msgrcv(msqid, &rbuf, MSGSZ, 0, 0) < 0)
意味着接收器的下一次运行得到了:
Waiting...
id - 60464 : message - Waiting...
id - 60478 : message - Waiting...
id - 60482 : message - Waiting...
id - 71796 : message - Waiting...
其中Waiting...
在printf()
语句之前的循环内的if
语句中打印。这表明先前中止尝试阅读邮件的消息等待阅读。
消息返回为零长度,因为您在定义消息结构时没有足够小心。特别是,接收消息结构使用int
而不是规范要求的long
,因此在我的sizeof(int) == 4
和sizeof(long) == 8
并且值为little-endian的机器上,接收器中的字符串相对于发送器中的字符串放错位置,并放置0个字节。解决这个问题并传输消息。
请注意,中断处理程序设置不够早;它实际上从未在原始代码中使用过。
经验:
printf()
in a signal handler。它在这里相当安全,但它在技术上是未定义的行为,应该避免。send.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#define MSGSZ 255
#define KEY 10
typedef struct msgbuf
{
long mtype;
char mtext[MSGSZ+1];
} message_buf;
int main(void)
{
message_buf sbuf;
sbuf.mtype = getpid();
printf("The process id is %ld\n", sbuf.mtype);
printf("enter word/s (must be less than %d characters):\n", MSGSZ+1);
if (fgets(sbuf.mtext, sizeof(sbuf.mtext), stdin) == 0)
{
printf("EOF detected\n");
exit(EXIT_FAILURE);
}
printf("\n");
key_t key = KEY;
int mask = 0644 | IPC_CREAT;
int msgid = msgget(key, mask);
if (msgid < 0)
{
fprintf(stderr, "Failed to create msg key %d\n", key);
exit(EXIT_FAILURE);
}
if (msgsnd(msgid, &sbuf, strlen(sbuf.mtext)+1, IPC_NOWAIT) < 0)
{
perror("msgsnd");
exit(EXIT_FAILURE);
}
printf("id - %ld : message - %s\n", sbuf.mtype, sbuf.mtext);
return 0;
}
recv.c
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#define MSGSZ 255
#define KEY 10
typedef struct msgbuf
{
long mtype;
char mtext[MSGSZ+1];
} message_buf;
static void INThandler(int);
int main(void)
{
key_t key = KEY;
int msgflg = 0644;
message_buf rbuf;
int msqid = msgget(key, msgflg);
if (msqid < 0)
{
perror("msgget");
exit(1);
}
signal(SIGINT, INThandler);
rbuf.mtype = 1;
for ( ; ; )
{
printf("Waiting...\n");
ssize_t nbytes = msgrcv(msqid, &rbuf, MSGSZ, 0, 0);
if (nbytes < 0)
{
perror("msgrcv");
exit(1);
}
printf("id - %ld : message (%d) - %s", rbuf.mtype, (int)nbytes, rbuf.mtext);
}
return 0;
}
static void INThandler(int sig)
{
signal(sig, SIG_IGN);
int mask, msgid;
key_t key = KEY;
mask = 0644;
msgid = msgget(key, mask);
if (msgid == -1)
{
printf("Message queue does not exist.\n");
exit(EXIT_SUCCESS);
}
if (msgctl(msgid, IPC_RMID, NULL) == -1)
{
fprintf(stderr, "Message queue could not be deleted.\n");
exit(EXIT_FAILURE);
}
else
printf("Message queue was deleted.\n");
exit(0);
}
$ ./send <<< "The message to be sent."
The process id is 71901
enter word/s (must be less than 256 characters):
id - 71901 : message - The message to be sent.
$ ./send <<< "Another message to be sent."
The process id is 71902
enter word/s (must be less than 256 characters):
id - 71902 : message - Another message to be sent.
$ ./send <<< "A third message sent to the receiver."
The process id is 71903
enter word/s (must be less than 256 characters):
id - 71903 : message - A third message sent to the receiver.
$ ./recv
Waiting...
id - 71901 : message (25) - The message to be sent.
Waiting...
id - 71902 : message (29) - Another message to be sent.
Waiting...
id - 71903 : message (39) - A third message sent to the receiver.
Waiting...
^CMessage queue was deleted.
$