Linux 为什么macOS和Ubuntu上的消息队列结果不同
最近我在学习Linux上的进程通信。我写了一个C程序来做以下事情:Linux 为什么macOS和Ubuntu上的消息队列结果不同,linux,message-queue,ubuntu-16.04,macos-sierra,Linux,Message Queue,Ubuntu 16.04,Macos Sierra,最近我在学习Linux上的进程通信。我写了一个C程序来做以下事情: 进程A设置消息队列(如邮箱) 进程B向队列发送三条消息“111”、“222”、“333” 进程C从队列中以“333”、“111”、“222”的顺序读取消息 进程D删除队列 我首先在Ubuntu 16.04上编写了这个程序,它工作得很好,正如我所想: 然而,当我编译相同的代码并尝试在macOS(Sierra 10.12.3)上运行时,结果与Ubuntu上的结果不同: 无论我如何更改代码(例如,在进程a中睡眠几秒钟),队列总是在
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <errno.h>
#define MAX_TEXT 1024
struct mymsg123
{
long int priority;
char text[MAX_TEXT];
};
int main()
{
int msgid = -1; //message id
struct mymsg123 data; //message to send
//set up message queue(mailbox) in Process A
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr, "msgget failed in Process A with error: %d\n", errno);
exit(EXIT_FAILURE);
}
printf("Mailbox created in Process A\n");
pid_t pid = fork(); //to create Process B
if (pid < 0) {fprintf(stderr, "Fork failed in Process A"); exit(EXIT_FAILURE); }
//child Process B
else if (pid == 0)
{
const char msg1[] = "111";
//set the first message
data.priority = 2;
strcpy(data.text, msg1);
//send the first message
if (msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1)
{
fprintf(stderr, "msgsnd failed in Process B when sending msg1\n");
exit(EXIT_FAILURE);
}
printf("Sent msg %s, priority %ld to mailbox\n", data.text, data.priority);
const char msg2[] = "222";
//set the second message
data.priority = 3;
strcpy(data.text, msg2);
//send the second message
if (msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1)
{
fprintf(stderr, "msgsnd failed in Porcess B when sending msg2\n");
exit(EXIT_FAILURE);
}
printf("Sent msg %s, priority %ld to mailbox\n", data.text, data.priority);
const char msg3[] = "333";
//set the third message
data.priority = 1;
strcpy(data.text, msg3);
//send the third message
if (msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1)
{
fprintf(stderr, "msgsnd failed in Process B when sending msg3\n");
exit(EXIT_FAILURE);
}
printf("Sent msg %s, priority %ld to mailbox\n", data.text, data.priority);
}
//parent Process A
else
{
pid_t pid = fork(); //to create Process C
if (pid < 0) {fprintf(stderr, "Fork failed in Process A"); exit(EXIT_FAILURE); }
//child process C
else if (pid == 0)
{
//receiving priority 1 message
long int priority = 1;
if(msgrcv(msgid, (void*)&data, BUFSIZ, priority, 0) == -1)
{
fprintf(stderr, "msgrcv failed with error in Process C when receiving priority 1 msg: %d\n", errno);
exit(EXIT_FAILURE);
}
printf("Received priority 1 message in Process C from mailbox: %s\n", data.text);
//receiving priority 2 message
priority = 2;
if(msgrcv(msgid, (void*)&data, BUFSIZ, priority, 0) == -1)
{
fprintf(stderr, "msgrcv failed with error in Prcess C when receiving priority 2 msg: %d\n", errno);
exit(EXIT_FAILURE);
}
printf("Received priority 2 message in Process C from mailbox: %s\n", data.text);
//receiving priority 3 message
priority = 3;
if(msgrcv(msgid, (void*)&data, BUFSIZ, priority, 0) == -1)
{
fprintf(stderr, "msgrcv failed with error in Process C when receiving priority 3 msg: %d\n", errno);
exit(EXIT_FAILURE);
}
printf("Received priority 3 message in Process C from mailbox: %s\n", data.text);
}
//parent Process A
else
{
pid_t pid = fork(); //to create Process D
if (pid < 0) {fprintf(stderr, "Fork failed in Process A"); exit(EXIT_FAILURE); }
//child process D
else if (pid == 0)
{
//sleep(10);
if (msgctl(msgid, IPC_RMID, 0) == -1)
{
fprintf(stderr, "msgctl(IPC_RMID) failed in Process D\n");
exit(EXIT_FAILURE);
}
printf("Mailbox deleted in Process D\n");
}
//parent Process A
else
;
}
}
//sleep(10);
exit(EXIT_SUCCESS);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义最大文本1024
结构mymsg123
{
长整数优先级;
字符文本[最大文本];
};
int main()
{
int msgid=-1;//消息id
struct mymsg123 data;//要发送的消息
//在进程A中设置消息队列(邮箱)
msgid=msgget((键)12340666 | IPC|u CREAT);
如果(msgid==-1)
{
fprintf(stderr,“进程A中的msgget失败,错误:%d\n”,错误号);
退出(退出失败);
}
printf(“在进程A中创建的邮箱”);
pid_t pid=fork();//创建进程B
if(pid<0){fprintf(stderr,“Fork在进程A中失败”);exit(exit_FAILURE);}
//子进程B
否则如果(pid==0)
{
常量字符msg1[]=“111”;
//设置第一条消息
data.priority=2;
strcpy(data.text,msg1);
//发送第一条消息
if(msgsnd(msgid,(void*)和数据,最大文本,0)=-1)
{
fprintf(stderr,“发送msg1时进程B中的msgsnd失败\n”);
退出(退出失败);
}
printf(“已将消息%s,优先级%ld发送到邮箱\n”,data.text,data.priority);
常量字符msg2[]=“222”;
//设置第二条消息
data.priority=3;
strcpy(data.text,msg2);
//发送第二条消息
if(msgsnd(msgid,(void*)和数据,最大文本,0)=-1)
{
fprintf(stderr,“发送msg2时在进程B中msgsnd失败\n”);
退出(退出失败);
}
printf(“已将消息%s,优先级%ld发送到邮箱\n”,data.text,data.priority);
常量字符msg3[]=“333”;
//设置第三条消息
data.priority=1;
strcpy(data.text,msg3);
//发送第三条消息
if(msgsnd(msgid,(void*)和数据,最大文本,0)=-1)
{
fprintf(stderr,“发送msg3时进程B中的msgsnd失败\n”);
退出(退出失败);
}
printf(“已将消息%s,优先级%ld发送到邮箱\n”,data.text,data.priority);
}
//父进程A
其他的
{
pid_t pid=fork();//创建进程C
if(pid<0){fprintf(stderr,“Fork在进程A中失败”);exit(exit_FAILURE);}
//子进程C
否则如果(pid==0)
{
//接收优先级1消息
长整数优先级=1;
if(msgrcv(msgid,(void*)和数据,BUFSIZ,优先级,0)=-1)
{
fprintf(stderr,“当接收到优先级为1的消息:%d\n”时,msgrcv在进程C中出现错误失败,错误号);
退出(退出失败);
}
printf(“从邮箱%s\n接收到进程C中优先级为1的消息”,data.text);
//接收优先级2消息
优先级=2;
if(msgrcv(msgid,(void*)和数据,BUFSIZ,优先级,0)=-1)
{
fprintf(stderr,“当接收到优先级为2的消息:%d\n时,msgrcv在过程C中出错失败”,errno);
退出(退出失败);
}
printf(“从邮箱%s\n接收到进程C中优先级为2的消息”,data.text);
//接收优先级为3的消息
优先级=3;
if(msgrcv(msgid,(void*)和数据,BUFSIZ,优先级,0)=-1)
{
fprintf(stderr,“当接收到优先级为3的消息:%d\n”时,msgrcv在进程C中失败,并出现错误”,errno);
退出(退出失败);
}
printf(“在进程C中从邮箱%s\n接收到优先级为3的消息”,data.text);
}
//父进程A
其他的
{
pid_t pid=fork();//创建进程D
if(pid<0){fprintf(stderr,“Fork在进程A中失败”);exit(exit_FAILURE);}
//子进程D
否则如果(pid==0)
{
//睡眠(10);
如果(msgctl(msgid,IPC_RMID,0)=-1)
{
fprintf(stderr,“进程D中的msgctl(IPC_RMID)失败”);
退出(退出失败);
}
printf(“在进程D中删除的邮箱”);
}
//父进程A
其他的
;
}
}
//睡眠(10);
退出(退出成功);
}
提前谢谢 如果您打印错误消息本身,而不仅仅是错误代码,这将非常有用 无论如何,我认为这是因为,但在Linux上通常是16384。再加上您的
MAX_TEXT
大小为1024,第三条消息无法发送,因为队列已满。它可能会一直阻塞,直到第一个msgrcv
调用将第一条消息出列,从而释放空间,但macOS没有为此提供手册页,因此我将退出Linux页面
无论如何,您有一个竞争条件,因为进程D将立即删除消息队列,而不等待它变为空。因此,如果进程B由于队列已满而阻塞,而进程D将其删除,那么进程B将返回一个错误。但这一切都取决于进程的调度,因此也取决于竞争条件
你可以