您只在子级中设置了mtype,而在父级中没有。
此外,子级中的msgctl 调用与父级中的最终msgrcv 进行竞赛。也就是说,孩子可能会在父母有机会完成其最终的msgrcv 之前完成msgctl 调用。
而且,我认为,孩子的 return 0; 应该是 exit(0); 以防止落入父代码。
在下面的重构代码中,我使用了cpp 条件来表示旧/损坏与新/固定代码:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
这是重构后的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#if 1
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#endif
#define BUF_SIZE 16
#define MSG_KEY1 75
#define MSG_KEY2 76
struct msgform {
long mtype;
char mbuf[BUF_SIZE];
long mind;
} msg;
struct msgping {
long mtype;
long ping;
} msgPing;
#define ONERR(_fd) \
do { \
if (_fd >= 0) \
break; \
printf("msgget error " #_fd " at line %d cldpid=%d -- %s\n", \
__LINE__,cldpid,strerror(errno)); \
exit(1); \
} while (0)
int
main()
{
#if 0
if (fork() == 0) {
#else
pid_t cldpid = fork();
if (cldpid == 0) {
#endif
// child process
int msgid1;
int msgid2;
msgid1 = msgget(MSG_KEY1, 0666 | IPC_CREAT);
ONERR(msgid1);
msgid2 = msgget(MSG_KEY2, 0666 | IPC_CREAT);
ONERR(msgid2);
msg.mtype = 1;
msgPing.mtype = 1;
printf("1 - started, sending msgPing\n");
msgsnd(msgid1, &msgPing, sizeof(msgPing), 0);
msgrcv(msgid2, &msg, sizeof(msg), 1, 0);
printf("3 - msg received, sending msgPing\n");
msgsnd(msgid1, &msgPing, sizeof(msgPing), 0);
#if 0
msgctl(msgid1, IPC_RMID, 0);
msgctl(msgid2, IPC_RMID, 0);
#endif
#if 0
return 0;
#else
exit(0);
#endif
}
// parent process
sleep(1);
int msgid1;
int msgid2;
msgid1 = msgget(MSG_KEY1, 0666 | IPC_CREAT);
ONERR(msgid1);
msgid2 = msgget(MSG_KEY2, 0666 | IPC_CREAT);
ONERR(msgid2);
// NOTE/FIX: the parent needs to set this as well as the child
#if 1
msg.mtype = 1;
msgPing.mtype = 1;
#endif
msgrcv(msgid1, &msgPing, sizeof(msgPing), 1, 0);
printf("2 - msgPing received, sending msg\n");
msgsnd(msgid2, &msg, sizeof(msg), 0);
msgrcv(msgid1, &msgPing, sizeof(msgPing), 1, 0);
printf("4 - msgPing received, finished\n");
#if 1
waitpid(cldpid,NULL,0);
msgctl(msgid1, IPC_RMID, 0);
msgctl(msgid2, IPC_RMID, 0);
#endif
return 0;
}
当我为实时、关键任务、生产代码完成msgsnd/msgrcv 后,我在两个方向都使用了一个单个 msgid,使用了一个不同 mtype 值(例如,mtype = 1 用于父级,mtype = 2 用于 ping)。
这是一个进一步清理和简化的版本:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#if 1
#include <sys/wait.h>
#endif
#define BUF_SIZE 16
#define MSG_KEY1 75
#define MSG_KEY2 76
struct msgform {
long mtype;
char mbuf[BUF_SIZE];
long mind;
} msg;
struct msgping {
long mtype;
long ping;
} msgPing;
enum {
MSGTYPE = 1,
MSGPING = 2,
};
int
main(void)
{
int msgid = msgget(MSG_KEY1, 0666 | IPC_CREAT);
pid_t cldpid = fork();
msg.mtype = MSGTYPE;
msgPing.mtype = MSGPING;
if (cldpid == 0) {
sleep(1);
printf("1 - started, sending msgPing\n");
msgsnd(msgid, &msgPing, sizeof(msgPing), 0);
msgrcv(msgid, &msg, sizeof(msg), MSGTYPE, 0);
printf("3 - msg received, sending msgPing\n");
msgsnd(msgid, &msgPing, sizeof(msgPing), 0);
exit(0);
}
// parent process
sleep(1);
msgrcv(msgid, &msgPing, sizeof(msgPing), MSGPING, 0);
printf("2 - msgPing received, sending msg\n");
msgsnd(msgid, &msg, sizeof(msg), 0);
msgrcv(msgid, &msgPing, sizeof(msgPing), MSGPING, 0);
printf("4 - msgPing received, finished\n");
waitpid(cldpid,NULL,0);
msgctl(msgid, IPC_RMID, 0);
return 0;
}