gpt4 book ai didi

c - 如何从一个文件获取消息和消息ID到另一个文件?

转载 作者:太空宇宙 更新时间:2023-11-04 03:38:25 26 4
gpt4 key购买 nike

从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 时代码没有返回任何内容。你如何解决这个问题?

最佳答案

您的问题由 msgrcv() 的 POSIX 规范确定. msgtyp 参数是第四个参数,在您的代码中指定为 1:

The argument msgtyp specifies the type of message requested as follows:

  • If msgtyp is 0, the first message on the queue shall be received.

  • If msgtyp is greater than 0, the first message of type msgtyp shall be received.

  • If msgtyp is less than 0, the first message of the lowest type that is less than or equal to the absolute value of msgtyp shall be received.

由于发送过程不是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) == 4sizeof(long) == 8 并且值为小端,接收方的字符串相对于发送方的字符串错位,放置了 0 个字节。修复该问题并传输消息。

请注意,中断处理程序设置得不够早;它从未在原始代码中实际使用过。

教训:

  1. 仔细阅读规范。
  2. 使用一致的结构定义(创建一个供发送方和接收方使用的 header )。
  3. 正确定位信号处理代码。
  4. 继续阅读 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);
}

sample 运行

$ ./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.
$

关于c - 如何从一个文件获取消息和消息ID到另一个文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30437486/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com