最近我在Linux上学习进程通信。我写了一个C程序来做以下事情:
我首先在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);
}
高级谢谢!
答案 0 :(得分:1)
如果您打印错误消息本身而不仅仅是错误代码,将会很有帮助。
无论如何,我认为这是因为the message queue size appears to be 2048 bytes on macOS,但在Linux上通常是16384。加上MAX_TEXT
大小为1024,当队列已满时,无法发送第三条消息。它可能会阻塞,直到第一个msgrcv
调用出列第一条消息,释放空间,但是macOS没有给出man页面,所以我要离开Linux页面。
无论如何,您都有竞争条件,因为进程D会立即删除消息队列,而不会等待它变空。因此,如果进程B由于队列已满而阻塞,并且进程D将其删除,则B将返回错误。但这完全取决于过程的安排,因此也就是竞争条件。
您可以在macOS中更改队列大小,但需要具有超级用户权限才能使其生效。您可以通过将MAX_TEXT
定义减少到128并验证它是否适用于两者来验证这一点而不以root身份运行。