如何从一个文件获取消息和消息 ID 到另一个文件?
Posted
技术标签:
【中文标题】如何从一个文件获取消息和消息 ID 到另一个文件?【英文标题】:How to get message and message id from one file to another file? 【发布时间】:2015-05-25 11:37:16 【问题描述】:在从 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 时,代码什么也没有返回。你如何解决这个问题?
【问题讨论】:
如果你能更好地缩进你的代码会很有帮助。 你的意思是get.c和send.c需要整理一下吗?还是其中之一? 你应该在问之前做。您想节省一些时间,但是,您会花费更多时间,因为没有人愿意阅读您的代码,也不想提供答案。 我刚刚修复了代码中的基本错误,但我希望 get.c 返回一些打印的东西,而不是什么。 【参考方案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...
是在 if
语句之前的循环内的 printf()
语句中打印的。这表明来自先前中止尝试读取消息的消息正在等待读取。
消息返回为零长度,因为您在定义消息结构时不够小心。特别是,接收消息结构使用int
而不是规范要求的long
,所以在我的机器上sizeof(int) == 4
和sizeof(long) == 8
的值是little-endian,接收器中的字符串相对错位到发送方中的字符串,并放置 0 个字节。修复它并传输消息。
请注意,中断处理程序设置得不够早;它从未在原始代码中实际使用过。
课程:
-
仔细阅读规范。
使用一致的结构定义(创建发送方和接收方都使用的标头)。
正确定位信号处理代码。
阅读How to avoid using
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.
$
【讨论】:
以上是关于如何从一个文件获取消息和消息 ID 到另一个文件?的主要内容,如果未能解决你的问题,请参考以下文章